Procházet zdrojové kódy

Checkout new GDScriptLanguageClient branch

geequlim před 6 roky
rodič
revize
ece1f3118d

+ 7 - 0
.editorconfig

@@ -0,0 +1,7 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_style = tab
+insert_final_newline = true

+ 21 - 25
.vscode/launch.json

@@ -1,28 +1,24 @@
 // A launch configuration that compiles the extension and then opens it inside a new window
+// Use IntelliSense to learn about possible attributes.
+// Hover to view descriptions of existing attributes.
+// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
 {
-    "version": "0.1.0",
-    "configurations": [
-        {
-            "name": "Launch Extension",
-            "type": "extensionHost",
-            "request": "launch",
-            "runtimeExecutable": "${execPath}",
-            "args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
-            "stopOnEntry": false,
-            "sourceMaps": true,
-            "outFiles": ["${workspaceRoot}/out/src/**/*.js"],
-            "preLaunchTask": "npm"
-        },
-        {
-            "name": "Launch Tests",
-            "type": "extensionHost",
-            "request": "launch",
-            "runtimeExecutable": "${execPath}",
-            "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
-            "stopOnEntry": false,
-            "sourceMaps": true,
-            "outFiles": ["${workspaceRoot}/out/test"],
-            "preLaunchTask": "npm"
-        }
-    ]
+	"version": "0.2.0",
+	"configurations": [{
+			"name": "Run Extension",
+			"type": "extensionHost",
+			"request": "launch",
+			"runtimeExecutable": "${execPath}",
+			"args": [
+				"--extensionDevelopmentPath=${workspaceFolder}"
+			],
+			"outFiles": [
+				"${workspaceFolder}/out/**/*.js"
+			],
+			"preLaunchTask": "npm: watch",
+			"env": {
+				"VSCODE_DEBUG_MODE": true
+			}
+		},
+	]
 }

+ 2 - 1
.vscode/settings.json

@@ -6,5 +6,6 @@
     "search.exclude": {
         "out": true // set this to false to include "out" folder in search results
     },
-    "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
+    // Turn off tsc task auto detection since we have the necessary tasks as npm scripts
+    "typescript.tsc.autoDetect": "off"
 }

+ 19 - 29
.vscode/tasks.json

@@ -1,30 +1,20 @@
-// Available variables which can be used inside of strings.
-// ${workspaceRoot}: the root folder of the team
-// ${file}: the current opened file
-// ${fileBasename}: the current opened file's basename
-// ${fileDirname}: the current opened file's dirname
-// ${fileExtname}: the current opened file's extension
-// ${cwd}: the current working directory of the spawned process
-
-// A task runner that calls a custom npm script that compiles the extension.
+// See https://go.microsoft.com/fwlink/?LinkId=733558
+// for the documentation about the tasks.json format
 {
-    "version": "0.1.0",
-
-    // we want to run npm
-    "command": "npm",
-
-    // the command is a shell script
-    "isShellCommand": true,
-
-    // show the output window only if unrecognized errors occur.
-    "showOutput": "silent",
-
-    // we run the custom script "compile" as defined in package.json
-    "args": ["run", "compile", "--loglevel", "silent"],
-
-    // The tsc compiler is started in watching mode
-    "isBackground": true,
-
-    // use the standard tsc in watch mode problem matcher to find compile problems in the output.
-    "problemMatcher": "$tsc-watch"
-}
+	"version": "2.0.0",
+	"tasks": [
+		{
+			"type": "npm",
+			"script": "watch",
+			"problemMatcher": "$tsc-watch",
+			"isBackground": true,
+			"presentation": {
+				"reveal": "never"
+			},
+			"group": {
+				"kind": "build",
+				"isDefault": true
+			}
+		}
+	]
+}

+ 4 - 3
.vscodeignore

@@ -1,9 +1,10 @@
 .vscode/**
 .vscode-test/**
 out/test/**
-test/**
 src/**
-**/*.map
 .gitignore
-tsconfig.json
 vsc-extension-quickstart.md
+**/tsconfig.json
+**/tslint.json
+**/*.map
+**/*.ts

+ 2 - 2
LICENSE

@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2016-2017 Geequlim
+Copyright (c) 2016-2019 Geequlim
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+SOFTWARE.

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 202
configurations/GDScript.full.tmLanguage.json


+ 1 - 1
configurations/GDScript.tmLanguage.json

@@ -96,7 +96,7 @@
     },
 
     "keywords": {
-      "match": "\\b(?i:elif|else|for|if|while|break|continue|pass|in|is|return|onready|setget|enum|match|breakpoint|tool|extends|signal|class)\\b",
+      "match": "\\b(?i:elif|else|for|if|while|break|continue|pass|in|is|return|onready|setget|enum|match|breakpoint|tool|extends|signal|class|class_name)\\b",
       "name": "keyword.control.gdscript"
     },
     "letter": {

+ 0 - 2
doc/.gitignore

@@ -1,2 +0,0 @@
-classes/*.xml
-classes-*.xml

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 16126
doc/classes-2.1.json


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 49
doc/classes-3.0.json


+ 0 - 66
doc/xmldoc2json-2.1.py

@@ -1,66 +0,0 @@
-#!/usr/bin/python
-import sys
-import xml.etree.ElementTree as ET
-import json
-
-def parseClass(data):
-    dictCls = dict(data.attrib)
-    dictCls['brief_description'] = data.find("brief_description").text.strip()
-    dictCls['description'] = data.find("description").text.strip()
-    dictCls['methods'] = []
-    for m in data.find("methods"):
-        dictCls['methods'].append(parseMethod(m))
-    dictCls['signals'] = []
-    for s in (data.find("signals") if data.find("signals") is not None else []):
-        dictCls['signals'].append(parseMethod(s))
-    dictCls['constants'] = []
-    for c in (data.find("constants") if data.find("constants") is not None else []):
-        dictCls['constants'].append(parseConstant(c))
-    dictCls['properties'] = []
-    for m in (data.find("members") if data.find("members") is not None else []):
-        dictCls['properties'].append(parseProperty(m))
-    dictCls['theme_properties'] = []
-    for thi in (data.find("theme_items") if data.find("theme_items") is not None else []):
-        dictCls['theme_properties'].append(parseProperty(thi))
-    return dictCls
-
-def parseMethod(data):
-    dictMethod = dict(data.attrib)
-    dictMethod['description'] = data.find("description").text.strip()
-    dictMethod['return_type'] = data.find("return").attrib["type"] if data.find("return") is not None else ""
-    if "qualifiers" not in dictMethod:  dictMethod["qualifiers"] = ""
-    dictMethod["arguments"] = []
-    for arg in data.iter('argument'):
-        dictMethod["arguments"].append(parseArgument(arg))
-    return dictMethod
-
-def parseArgument(data):
-    dictArg = dict(data.attrib)
-    if "dictArg" in dictArg: dictArg.pop("index")
-    dictArg["default_value"] = dictArg["default"] if "default" in dictArg else ""
-    if "default" in dictArg: dictArg.pop("default")
-    return dictArg
-
-def parseConstant(data):
-    dictConst = dict(data.attrib)
-    dictConst["description"] = data.text.strip()
-    return dictConst
-
-def parseProperty(data):
-    dictProp = dict(data.attrib)
-    dictProp["description"] = data.text.strip()
-    return dictProp
-
-def main():
-    if len(sys.argv) >=2 :
-        tree = ET.parse(open(sys.argv[1], 'r'))
-        classes = {}
-        for cls in tree.getroot():
-            dictCls = parseClass(cls)
-            classes[dictCls['name']] = dictCls
-        jsonContent = json.dumps({"classes": classes, "version": "2.1.4"}, ensure_ascii=False, indent=2)
-        print(jsonContent)
-
-if __name__ == '__main__':
-    main()
-

+ 0 - 80
doc/xmldoc2json-3.0.py

@@ -1,80 +0,0 @@
-#!/usr/bin/python
-import sys
-import xml.etree.ElementTree as ET
-import json
-import os
-
-def glob_path(path, pattern):
-    import os, fnmatch
-    result = []
-    for root, _, files in os.walk(path):
-        for filename in files:
-            if fnmatch.fnmatch(filename, pattern):
-                result.append(os.path.join(root, filename))
-    return result
-
-def parseClass(data):
-    dictCls = dict(data.attrib)
-    dictCls['brief_description'] = data.find("brief_description").text.strip()
-    dictCls['description'] = data.find("description").text.strip()
-    dictCls['methods'] = []
-    for m in data.find("methods"):
-        dictCls['methods'].append(parseMethod(m))
-    dictCls['signals'] = []
-    for s in (data.find("signals") if data.find("signals") is not None else []):
-        dictCls['signals'].append(parseMethod(s))
-    dictCls['constants'] = []
-    for c in (data.find("constants") if data.find("constants") is not None else []):
-        dictCls['constants'].append(parseConstant(c))
-    dictCls['properties'] = []
-    for m in (data.find("members") if data.find("members") is not None else []):
-        dictCls['properties'].append(parseProperty(m))
-    dictCls['theme_properties'] = []
-    for thi in (data.find("theme_items") if data.find("theme_items") is not None else []):
-        dictCls['theme_properties'].append(parseProperty(thi))
-    return dictCls
-
-def parseMethod(data):
-    dictMethod = dict(data.attrib)
-    dictMethod['description'] = data.find("description").text.strip()
-    dictMethod['return_type'] = data.find("return").attrib["type"] if data.find("return") is not None else ""
-    if "qualifiers" not in dictMethod:  dictMethod["qualifiers"] = ""
-    dictMethod["arguments"] = []
-    for arg in data.iter('argument'):
-        dictMethod["arguments"].append(parseArgument(arg))
-    return dictMethod
-
-def parseArgument(data):
-    dictArg = dict(data.attrib)
-    if "dictArg" in dictArg: dictArg.pop("index")
-    dictArg["default_value"] = dictArg["default"] if "default" in dictArg else ""
-    if "default" in dictArg: dictArg.pop("default")
-    return dictArg
-
-def parseConstant(data):
-    dictConst = dict(data.attrib)
-    dictConst["description"] = data.text.strip()
-    return dictConst
-
-def parseProperty(data):
-    dictProp = dict(data.attrib)
-    dictProp["description"] = data.text.strip()
-    return dictProp
-
-def main():
-    if len(sys.argv) >=2 :
-        if os.path.isdir(sys.argv[1]):
-            classes = {}
-            for f in glob_path(sys.argv[1], "**.xml"):
-                if f.find("/classes/") == -1 and f.find("/doc_classes/") == -1:
-                    continue
-                tree = ET.parse(open(f, 'r'))
-                cls = tree.getroot()
-                dictCls = parseClass(cls)
-                classes[dictCls['name']] = dictCls
-            jsonContent = json.dumps({"classes": classes, "version": "3.0.4"}, ensure_ascii=False, indent=2)
-            print(jsonContent)
-
-if __name__ == '__main__':
-    main()
-

+ 0 - 2236
package-lock.json

@@ -1,2236 +0,0 @@
-{
-  "name": "godot-tools",
-  "version": "0.3.7",
-  "lockfileVersion": 1,
-  "requires": true,
-  "dependencies": {
-    "@types/mocha": {
-      "version": "5.2.5",
-      "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz",
-      "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==",
-      "dev": true
-    },
-    "@types/node": {
-      "version": "10.9.4",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-10.9.4.tgz",
-      "integrity": "sha512-fCHV45gS+m3hH17zgkgADUSi2RR1Vht6wOZ0jyHP8rjiQra9f+mIcgwPQHllmDocYOstIEbKlxbFDYlgrTPYqw==",
-      "dev": true
-    },
-    "ajv": {
-      "version": "5.5.2",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
-      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
-      "dev": true,
-      "requires": {
-        "co": "^4.6.0",
-        "fast-deep-equal": "^1.0.0",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.3.0"
-      }
-    },
-    "ansi-cyan": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz",
-      "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=",
-      "dev": true,
-      "requires": {
-        "ansi-wrap": "0.1.0"
-      }
-    },
-    "ansi-red": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
-      "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=",
-      "dev": true,
-      "requires": {
-        "ansi-wrap": "0.1.0"
-      }
-    },
-    "ansi-wrap": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
-      "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
-      "dev": true
-    },
-    "arr-diff": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
-      "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
-      "dev": true,
-      "requires": {
-        "arr-flatten": "^1.0.1",
-        "array-slice": "^0.2.3"
-      }
-    },
-    "arr-flatten": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
-      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
-      "dev": true
-    },
-    "arr-union": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
-      "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
-      "dev": true
-    },
-    "array-differ": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
-      "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=",
-      "dev": true
-    },
-    "array-slice": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
-      "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
-      "dev": true
-    },
-    "array-union": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
-      "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=",
-      "dev": true,
-      "requires": {
-        "array-uniq": "^1.0.1"
-      }
-    },
-    "array-uniq": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
-      "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=",
-      "dev": true
-    },
-    "array-unique": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
-      "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
-      "dev": true
-    },
-    "arrify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
-      "dev": true
-    },
-    "asn1": {
-      "version": "0.2.4",
-      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
-      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
-      "dev": true,
-      "requires": {
-        "safer-buffer": "~2.1.0"
-      }
-    },
-    "assert-plus": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
-      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
-      "dev": true
-    },
-    "asynckit": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
-      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
-      "dev": true
-    },
-    "aws-sign2": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
-      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
-      "dev": true
-    },
-    "aws4": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
-      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
-      "dev": true
-    },
-    "balanced-match": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
-      "dev": true
-    },
-    "bcrypt-pbkdf": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
-      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "tweetnacl": "^0.14.3"
-      }
-    },
-    "block-stream": {
-      "version": "0.0.9",
-      "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
-      "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
-      "dev": true,
-      "requires": {
-        "inherits": "~2.0.0"
-      }
-    },
-    "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "dev": true,
-      "requires": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "braces": {
-      "version": "1.8.5",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
-      "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
-      "dev": true,
-      "requires": {
-        "expand-range": "^1.8.1",
-        "preserve": "^0.2.0",
-        "repeat-element": "^1.1.2"
-      }
-    },
-    "browser-stdout": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
-      "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=",
-      "dev": true
-    },
-    "buffer-crc32": {
-      "version": "0.2.13",
-      "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
-      "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
-      "dev": true
-    },
-    "buffer-from": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
-      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
-      "dev": true
-    },
-    "caseless": {
-      "version": "0.12.0",
-      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
-      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
-      "dev": true
-    },
-    "clone": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
-      "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=",
-      "dev": true
-    },
-    "clone-buffer": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz",
-      "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=",
-      "dev": true
-    },
-    "clone-stats": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
-      "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=",
-      "dev": true
-    },
-    "cloneable-readable": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz",
-      "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==",
-      "dev": true,
-      "requires": {
-        "inherits": "^2.0.1",
-        "process-nextick-args": "^2.0.0",
-        "readable-stream": "^2.3.5"
-      }
-    },
-    "co": {
-      "version": "4.6.0",
-      "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
-      "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
-      "dev": true
-    },
-    "combined-stream": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz",
-      "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=",
-      "dev": true,
-      "requires": {
-        "delayed-stream": "~1.0.0"
-      }
-    },
-    "commander": {
-      "version": "2.15.1",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
-      "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
-      "dev": true
-    },
-    "concat-map": {
-      "version": "0.0.1",
-      "resolved": false,
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
-      "dev": true
-    },
-    "convert-source-map": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.1.tgz",
-      "integrity": "sha1-uCeAl7m8IpNl3lxiz1/K7YtVmeU=",
-      "dev": true
-    },
-    "core-util-is": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
-      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
-      "dev": true
-    },
-    "dashdash": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
-      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "^1.0.0"
-      }
-    },
-    "debug": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-      "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-      "dev": true,
-      "requires": {
-        "ms": "2.0.0"
-      }
-    },
-    "deep-assign": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz",
-      "integrity": "sha1-sJJ0O+hCfcYh6gBnzex+cN0Z83s=",
-      "dev": true,
-      "requires": {
-        "is-obj": "^1.0.0"
-      }
-    },
-    "delayed-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
-      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
-      "dev": true
-    },
-    "diff": {
-      "version": "3.5.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
-      "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
-      "dev": true
-    },
-    "duplexer": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
-      "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
-      "dev": true
-    },
-    "duplexify": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz",
-      "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==",
-      "dev": true,
-      "requires": {
-        "end-of-stream": "^1.0.0",
-        "inherits": "^2.0.1",
-        "readable-stream": "^2.0.0",
-        "stream-shift": "^1.0.0"
-      }
-    },
-    "ecc-jsbn": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
-      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "jsbn": "~0.1.0",
-        "safer-buffer": "^2.1.0"
-      }
-    },
-    "end-of-stream": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz",
-      "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==",
-      "dev": true,
-      "requires": {
-        "once": "^1.4.0"
-      }
-    },
-    "escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
-      "dev": true
-    },
-    "event-stream": {
-      "version": "3.3.4",
-      "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz",
-      "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=",
-      "dev": true,
-      "requires": {
-        "duplexer": "~0.1.1",
-        "from": "~0",
-        "map-stream": "~0.1.0",
-        "pause-stream": "0.0.11",
-        "split": "0.3",
-        "stream-combiner": "~0.0.4",
-        "through": "~2.3.1"
-      }
-    },
-    "expand-brackets": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
-      "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
-      "dev": true,
-      "requires": {
-        "is-posix-bracket": "^0.1.0"
-      }
-    },
-    "expand-range": {
-      "version": "1.8.2",
-      "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
-      "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
-      "dev": true,
-      "requires": {
-        "fill-range": "^2.1.0"
-      }
-    },
-    "extend": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
-      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
-      "dev": true
-    },
-    "extend-shallow": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
-      "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
-      "dev": true,
-      "requires": {
-        "kind-of": "^1.1.0"
-      }
-    },
-    "extglob": {
-      "version": "0.3.2",
-      "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
-      "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
-      "dev": true,
-      "requires": {
-        "is-extglob": "^1.0.0"
-      },
-      "dependencies": {
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        }
-      }
-    },
-    "extsprintf": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
-      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
-      "dev": true
-    },
-    "fast-deep-equal": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
-      "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
-      "dev": true
-    },
-    "fast-json-stable-stringify": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
-      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
-      "dev": true
-    },
-    "fd-slicer": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
-      "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
-      "dev": true,
-      "requires": {
-        "pend": "~1.2.0"
-      }
-    },
-    "filename-regex": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
-      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
-      "dev": true
-    },
-    "fill-range": {
-      "version": "2.2.4",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
-      "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
-      "dev": true,
-      "requires": {
-        "is-number": "^2.1.0",
-        "isobject": "^2.0.0",
-        "randomatic": "^3.0.0",
-        "repeat-element": "^1.1.2",
-        "repeat-string": "^1.5.2"
-      }
-    },
-    "first-chunk-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz",
-      "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=",
-      "dev": true
-    },
-    "for-in": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
-      "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
-      "dev": true
-    },
-    "for-own": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
-      "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
-      "dev": true,
-      "requires": {
-        "for-in": "^1.0.1"
-      }
-    },
-    "forever-agent": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
-      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
-      "dev": true
-    },
-    "form-data": {
-      "version": "2.3.2",
-      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz",
-      "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=",
-      "dev": true,
-      "requires": {
-        "asynckit": "^0.4.0",
-        "combined-stream": "1.0.6",
-        "mime-types": "^2.1.12"
-      }
-    },
-    "from": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
-      "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
-      "dev": true
-    },
-    "fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
-    },
-    "fstream": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
-      "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.2",
-        "inherits": "~2.0.0",
-        "mkdirp": ">=0.5 0",
-        "rimraf": "2"
-      }
-    },
-    "getpass": {
-      "version": "0.1.7",
-      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
-      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "^1.0.0"
-      }
-    },
-    "glob": {
-      "version": "7.1.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
-      "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
-      "requires": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.0.4",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "dependencies": {
-        "balanced-match": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
-          "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
-        },
-        "brace-expansion": {
-          "version": "1.1.11",
-          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-          "requires": {
-            "balanced-match": "^1.0.0",
-            "concat-map": "0.0.1"
-          }
-        },
-        "concat-map": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-          "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
-        },
-        "inflight": {
-          "version": "1.0.6",
-          "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-          "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-          "requires": {
-            "once": "^1.3.0",
-            "wrappy": "1"
-          }
-        },
-        "inherits": {
-          "version": "2.0.3",
-          "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
-          "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
-        },
-        "minimatch": {
-          "version": "3.0.4",
-          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-          "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-          "requires": {
-            "brace-expansion": "^1.1.7"
-          }
-        },
-        "once": {
-          "version": "1.4.0",
-          "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-          "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-          "requires": {
-            "wrappy": "1"
-          }
-        },
-        "path-is-absolute": {
-          "version": "1.0.1",
-          "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-          "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
-        },
-        "wrappy": {
-          "version": "1.0.2",
-          "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-          "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
-        }
-      }
-    },
-    "glob-base": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
-      "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
-      "dev": true,
-      "requires": {
-        "glob-parent": "^2.0.0",
-        "is-glob": "^2.0.0"
-      },
-      "dependencies": {
-        "glob-parent": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
-          "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
-          "dev": true,
-          "requires": {
-            "is-glob": "^2.0.0"
-          }
-        },
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        }
-      }
-    },
-    "glob-parent": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
-      "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
-      "dev": true,
-      "requires": {
-        "is-glob": "^3.1.0",
-        "path-dirname": "^1.0.0"
-      }
-    },
-    "glob-stream": {
-      "version": "5.3.5",
-      "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz",
-      "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=",
-      "dev": true,
-      "requires": {
-        "extend": "^3.0.0",
-        "glob": "^5.0.3",
-        "glob-parent": "^3.0.0",
-        "micromatch": "^2.3.7",
-        "ordered-read-streams": "^0.3.0",
-        "through2": "^0.6.0",
-        "to-absolute-glob": "^0.1.1",
-        "unique-stream": "^2.0.2"
-      },
-      "dependencies": {
-        "glob": {
-          "version": "5.0.15",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
-          "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
-          "dev": true,
-          "requires": {
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "2 || 3",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-          "dev": true
-        },
-        "readable-stream": {
-          "version": "1.0.34",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
-          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
-          "dev": true,
-          "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.1",
-            "isarray": "0.0.1",
-            "string_decoder": "~0.10.x"
-          }
-        },
-        "string_decoder": {
-          "version": "0.10.31",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
-          "dev": true
-        },
-        "through2": {
-          "version": "0.6.5",
-          "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
-          "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
-          "dev": true,
-          "requires": {
-            "readable-stream": ">=1.0.33-1 <1.1.0-0",
-            "xtend": ">=4.0.0 <4.1.0-0"
-          }
-        }
-      }
-    },
-    "graceful-fs": {
-      "version": "4.1.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
-      "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
-      "dev": true
-    },
-    "growl": {
-      "version": "1.10.3",
-      "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
-      "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
-      "dev": true
-    },
-    "gulp-chmod": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz",
-      "integrity": "sha1-AMOQuSigeZslGsz2MaoJ4BzGKZw=",
-      "dev": true,
-      "requires": {
-        "deep-assign": "^1.0.0",
-        "stat-mode": "^0.2.0",
-        "through2": "^2.0.0"
-      }
-    },
-    "gulp-filter": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/gulp-filter/-/gulp-filter-5.1.0.tgz",
-      "integrity": "sha1-oF4Rr/sHz33PQafeHLe2OsN4PnM=",
-      "dev": true,
-      "requires": {
-        "multimatch": "^2.0.0",
-        "plugin-error": "^0.1.2",
-        "streamfilter": "^1.0.5"
-      }
-    },
-    "gulp-gunzip": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/gulp-gunzip/-/gulp-gunzip-1.0.0.tgz",
-      "integrity": "sha1-FbdBFF6Dqcb1CIYkG1fMWHHxUak=",
-      "dev": true,
-      "requires": {
-        "through2": "~0.6.5",
-        "vinyl": "~0.4.6"
-      },
-      "dependencies": {
-        "isarray": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
-          "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
-          "dev": true
-        },
-        "readable-stream": {
-          "version": "1.0.34",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
-          "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
-          "dev": true,
-          "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.1",
-            "isarray": "0.0.1",
-            "string_decoder": "~0.10.x"
-          }
-        },
-        "string_decoder": {
-          "version": "0.10.31",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
-          "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
-          "dev": true
-        },
-        "through2": {
-          "version": "0.6.5",
-          "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
-          "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=",
-          "dev": true,
-          "requires": {
-            "readable-stream": ">=1.0.33-1 <1.1.0-0",
-            "xtend": ">=4.0.0 <4.1.0-0"
-          }
-        }
-      }
-    },
-    "gulp-remote-src-vscode": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/gulp-remote-src-vscode/-/gulp-remote-src-vscode-0.5.0.tgz",
-      "integrity": "sha512-/9vtSk9eI9DEWCqzGieglPqmx0WUQ9pwPHyHFpKmfxqdgqGJC2l0vFMdYs54hLdDsMDEZFLDL2J4ikjc4hQ5HQ==",
-      "dev": true,
-      "requires": {
-        "event-stream": "^3.3.4",
-        "node.extend": "^1.1.2",
-        "request": "^2.79.0",
-        "through2": "^2.0.3",
-        "vinyl": "^2.0.1"
-      },
-      "dependencies": {
-        "clone": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
-          "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
-          "dev": true
-        },
-        "clone-stats": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
-          "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
-          "dev": true
-        },
-        "vinyl": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
-          "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
-          "dev": true,
-          "requires": {
-            "clone": "^2.1.1",
-            "clone-buffer": "^1.0.0",
-            "clone-stats": "^1.0.0",
-            "cloneable-readable": "^1.0.0",
-            "remove-trailing-separator": "^1.0.1",
-            "replace-ext": "^1.0.0"
-          }
-        }
-      }
-    },
-    "gulp-sourcemaps": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz",
-      "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=",
-      "dev": true,
-      "requires": {
-        "convert-source-map": "^1.1.1",
-        "graceful-fs": "^4.1.2",
-        "strip-bom": "^2.0.0",
-        "through2": "^2.0.0",
-        "vinyl": "^1.0.0"
-      },
-      "dependencies": {
-        "clone": {
-          "version": "1.0.4",
-          "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
-          "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
-          "dev": true
-        },
-        "replace-ext": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
-          "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
-          "dev": true
-        },
-        "vinyl": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
-          "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
-          "dev": true,
-          "requires": {
-            "clone": "^1.0.0",
-            "clone-stats": "^0.0.1",
-            "replace-ext": "0.0.1"
-          }
-        }
-      }
-    },
-    "gulp-symdest": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/gulp-symdest/-/gulp-symdest-1.1.0.tgz",
-      "integrity": "sha1-wWUyBzLRks5W/ZQnH/oSMjS/KuA=",
-      "dev": true,
-      "requires": {
-        "event-stream": "^3.3.1",
-        "mkdirp": "^0.5.1",
-        "queue": "^3.1.0",
-        "vinyl-fs": "^2.4.3"
-      }
-    },
-    "gulp-untar": {
-      "version": "0.0.7",
-      "resolved": "https://registry.npmjs.org/gulp-untar/-/gulp-untar-0.0.7.tgz",
-      "integrity": "sha512-0QfbCH2a1k2qkTLWPqTX+QO4qNsHn3kC546YhAP3/n0h+nvtyGITDuDrYBMDZeW4WnFijmkOvBWa5HshTic1tw==",
-      "dev": true,
-      "requires": {
-        "event-stream": "~3.3.4",
-        "streamifier": "~0.1.1",
-        "tar": "^2.2.1",
-        "through2": "~2.0.3",
-        "vinyl": "^1.2.0"
-      },
-      "dependencies": {
-        "clone": {
-          "version": "1.0.4",
-          "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
-          "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
-          "dev": true
-        },
-        "replace-ext": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
-          "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
-          "dev": true
-        },
-        "vinyl": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
-          "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
-          "dev": true,
-          "requires": {
-            "clone": "^1.0.0",
-            "clone-stats": "^0.0.1",
-            "replace-ext": "0.0.1"
-          }
-        }
-      }
-    },
-    "gulp-vinyl-zip": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/gulp-vinyl-zip/-/gulp-vinyl-zip-2.1.0.tgz",
-      "integrity": "sha1-JOQGhdwFtxSZlSRQmeBZAmO+ja0=",
-      "dev": true,
-      "requires": {
-        "event-stream": "^3.3.1",
-        "queue": "^4.2.1",
-        "through2": "^2.0.3",
-        "vinyl": "^2.0.2",
-        "vinyl-fs": "^2.0.0",
-        "yauzl": "^2.2.1",
-        "yazl": "^2.2.1"
-      },
-      "dependencies": {
-        "clone": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
-          "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
-          "dev": true
-        },
-        "clone-stats": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
-          "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
-          "dev": true
-        },
-        "queue": {
-          "version": "4.5.0",
-          "resolved": "https://registry.npmjs.org/queue/-/queue-4.5.0.tgz",
-          "integrity": "sha512-DwxpAnqJuoQa+wyDgQuwkSshkhlqIlWEvwvdAY27fDPunZ2cVJzXU4JyjY+5l7zs7oGLaYAQm4MbLOVFAHFBzA==",
-          "dev": true,
-          "requires": {
-            "inherits": "~2.0.0"
-          }
-        },
-        "vinyl": {
-          "version": "2.2.0",
-          "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
-          "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
-          "dev": true,
-          "requires": {
-            "clone": "^2.1.1",
-            "clone-buffer": "^1.0.0",
-            "clone-stats": "^1.0.0",
-            "cloneable-readable": "^1.0.0",
-            "remove-trailing-separator": "^1.0.1",
-            "replace-ext": "^1.0.0"
-          }
-        }
-      }
-    },
-    "har-schema": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
-      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
-      "dev": true
-    },
-    "har-validator": {
-      "version": "5.1.0",
-      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz",
-      "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==",
-      "dev": true,
-      "requires": {
-        "ajv": "^5.3.0",
-        "har-schema": "^2.0.0"
-      }
-    },
-    "has-flag": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
-      "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
-      "dev": true
-    },
-    "he": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
-      "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
-      "dev": true
-    },
-    "http-signature": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
-      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "^1.0.0",
-        "jsprim": "^1.2.2",
-        "sshpk": "^1.7.0"
-      }
-    },
-    "inflight": {
-      "version": "1.0.6",
-      "resolved": false,
-      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
-      "dev": true,
-      "requires": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "inherits": {
-      "version": "2.0.3",
-      "resolved": false,
-      "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
-      "dev": true
-    },
-    "is": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz",
-      "integrity": "sha1-0Kwq1V63sL7JJqUmb2xmKqqD3KU=",
-      "dev": true
-    },
-    "is-buffer": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
-      "dev": true
-    },
-    "is-dotfile": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
-      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
-      "dev": true
-    },
-    "is-equal-shallow": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
-      "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
-      "dev": true,
-      "requires": {
-        "is-primitive": "^2.0.0"
-      }
-    },
-    "is-extendable": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
-      "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
-      "dev": true
-    },
-    "is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
-      "dev": true
-    },
-    "is-glob": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
-      "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
-      "dev": true,
-      "requires": {
-        "is-extglob": "^2.1.0"
-      }
-    },
-    "is-number": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
-      "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
-      "dev": true,
-      "requires": {
-        "kind-of": "^3.0.2"
-      },
-      "dependencies": {
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "^1.1.5"
-          }
-        }
-      }
-    },
-    "is-obj": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
-      "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=",
-      "dev": true
-    },
-    "is-posix-bracket": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
-      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
-      "dev": true
-    },
-    "is-primitive": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
-      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
-      "dev": true
-    },
-    "is-stream": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
-      "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
-      "dev": true
-    },
-    "is-typedarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
-      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
-      "dev": true
-    },
-    "is-utf8": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
-      "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
-      "dev": true
-    },
-    "is-valid-glob": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz",
-      "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=",
-      "dev": true
-    },
-    "isarray": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-      "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-      "dev": true
-    },
-    "isobject": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-      "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
-      "dev": true,
-      "requires": {
-        "isarray": "1.0.0"
-      }
-    },
-    "isstream": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
-      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
-      "dev": true
-    },
-    "jsbn": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
-      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
-      "dev": true,
-      "optional": true
-    },
-    "json-schema": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
-      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
-      "dev": true
-    },
-    "json-schema-traverse": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
-      "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
-      "dev": true
-    },
-    "json-stable-stringify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz",
-      "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=",
-      "dev": true,
-      "requires": {
-        "jsonify": "~0.0.0"
-      }
-    },
-    "json-stringify-safe": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
-      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
-      "dev": true
-    },
-    "jsonify": {
-      "version": "0.0.0",
-      "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
-      "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=",
-      "dev": true
-    },
-    "jsprim": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
-      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "1.0.0",
-        "extsprintf": "1.3.0",
-        "json-schema": "0.2.3",
-        "verror": "1.10.0"
-      }
-    },
-    "kind-of": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
-      "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
-      "dev": true
-    },
-    "lazystream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
-      "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
-      "dev": true,
-      "requires": {
-        "readable-stream": "^2.0.5"
-      }
-    },
-    "lodash.isequal": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
-      "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=",
-      "dev": true
-    },
-    "map-stream": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
-      "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
-      "dev": true
-    },
-    "math-random": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
-      "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
-      "dev": true
-    },
-    "merge-stream": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
-      "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=",
-      "dev": true,
-      "requires": {
-        "readable-stream": "^2.0.1"
-      }
-    },
-    "micromatch": {
-      "version": "2.3.11",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
-      "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
-      "dev": true,
-      "requires": {
-        "arr-diff": "^2.0.0",
-        "array-unique": "^0.2.1",
-        "braces": "^1.8.2",
-        "expand-brackets": "^0.1.4",
-        "extglob": "^0.3.1",
-        "filename-regex": "^2.0.0",
-        "is-extglob": "^1.0.0",
-        "is-glob": "^2.0.1",
-        "kind-of": "^3.0.2",
-        "normalize-path": "^2.0.1",
-        "object.omit": "^2.0.0",
-        "parse-glob": "^3.0.4",
-        "regex-cache": "^0.4.2"
-      },
-      "dependencies": {
-        "arr-diff": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
-          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.0.1"
-          }
-        },
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "^1.1.5"
-          }
-        }
-      }
-    },
-    "mime-db": {
-      "version": "1.36.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz",
-      "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==",
-      "dev": true
-    },
-    "mime-types": {
-      "version": "2.1.20",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz",
-      "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==",
-      "dev": true,
-      "requires": {
-        "mime-db": "~1.36.0"
-      }
-    },
-    "minimatch": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
-      "dev": true,
-      "requires": {
-        "brace-expansion": "^1.1.7"
-      }
-    },
-    "minimist": {
-      "version": "0.0.8",
-      "resolved": false,
-      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
-      "dev": true
-    },
-    "mkdirp": {
-      "version": "0.5.1",
-      "resolved": false,
-      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
-      "dev": true,
-      "requires": {
-        "minimist": "0.0.8"
-      }
-    },
-    "mocha": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
-      "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
-      "dev": true,
-      "requires": {
-        "browser-stdout": "1.3.1",
-        "commander": "2.15.1",
-        "debug": "3.1.0",
-        "diff": "3.5.0",
-        "escape-string-regexp": "1.0.5",
-        "glob": "7.1.2",
-        "growl": "1.10.5",
-        "he": "1.1.1",
-        "minimatch": "3.0.4",
-        "mkdirp": "0.5.1",
-        "supports-color": "5.4.0"
-      },
-      "dependencies": {
-        "browser-stdout": {
-          "version": "1.3.1",
-          "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
-          "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
-          "dev": true
-        },
-        "glob": {
-          "version": "7.1.2",
-          "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
-          "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
-          "dev": true,
-          "requires": {
-            "fs.realpath": "^1.0.0",
-            "inflight": "^1.0.4",
-            "inherits": "2",
-            "minimatch": "^3.0.4",
-            "once": "^1.3.0",
-            "path-is-absolute": "^1.0.0"
-          }
-        },
-        "growl": {
-          "version": "1.10.5",
-          "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
-          "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
-          "dev": true
-        }
-      }
-    },
-    "ms": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-      "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-      "dev": true
-    },
-    "multimatch": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz",
-      "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=",
-      "dev": true,
-      "requires": {
-        "array-differ": "^1.0.0",
-        "array-union": "^1.0.1",
-        "arrify": "^1.0.0",
-        "minimatch": "^3.0.0"
-      }
-    },
-    "node.extend": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz",
-      "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=",
-      "dev": true,
-      "requires": {
-        "is": "^3.1.0"
-      }
-    },
-    "normalize-path": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
-      "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
-      "dev": true,
-      "requires": {
-        "remove-trailing-separator": "^1.0.1"
-      }
-    },
-    "oauth-sign": {
-      "version": "0.9.0",
-      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
-      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
-      "dev": true
-    },
-    "object-assign": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-      "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
-      "dev": true
-    },
-    "object.omit": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
-      "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
-      "dev": true,
-      "requires": {
-        "for-own": "^0.1.4",
-        "is-extendable": "^0.1.1"
-      }
-    },
-    "once": {
-      "version": "1.4.0",
-      "resolved": false,
-      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
-      "dev": true,
-      "requires": {
-        "wrappy": "1"
-      }
-    },
-    "ordered-read-streams": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz",
-      "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=",
-      "dev": true,
-      "requires": {
-        "is-stream": "^1.0.1",
-        "readable-stream": "^2.0.1"
-      }
-    },
-    "parse-glob": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
-      "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
-      "dev": true,
-      "requires": {
-        "glob-base": "^0.3.0",
-        "is-dotfile": "^1.0.0",
-        "is-extglob": "^1.0.0",
-        "is-glob": "^2.0.0"
-      },
-      "dependencies": {
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        }
-      }
-    },
-    "path-dirname": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
-      "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
-      "dev": true
-    },
-    "path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": false,
-      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
-      "dev": true
-    },
-    "pause-stream": {
-      "version": "0.0.11",
-      "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
-      "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
-      "dev": true,
-      "requires": {
-        "through": "~2.3"
-      }
-    },
-    "pend": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
-      "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
-      "dev": true
-    },
-    "performance-now": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
-      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
-      "dev": true
-    },
-    "plugin-error": {
-      "version": "0.1.2",
-      "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
-      "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
-      "dev": true,
-      "requires": {
-        "ansi-cyan": "^0.1.1",
-        "ansi-red": "^0.1.1",
-        "arr-diff": "^1.0.1",
-        "arr-union": "^2.0.1",
-        "extend-shallow": "^1.1.2"
-      }
-    },
-    "preserve": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
-      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
-      "dev": true
-    },
-    "process-nextick-args": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
-      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
-      "dev": true
-    },
-    "psl": {
-      "version": "1.1.29",
-      "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz",
-      "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==",
-      "dev": true
-    },
-    "punycode": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
-      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
-      "dev": true
-    },
-    "qs": {
-      "version": "6.5.2",
-      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
-      "dev": true
-    },
-    "querystringify": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.0.0.tgz",
-      "integrity": "sha512-eTPo5t/4bgaMNZxyjWx6N2a6AuE0mq51KWvpc7nU/MAqixcI6v6KrGUKES0HaomdnolQBBXU/++X6/QQ9KL4tw==",
-      "dev": true
-    },
-    "queue": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/queue/-/queue-3.1.0.tgz",
-      "integrity": "sha1-bEnQHwCeIlZ4h4nyv/rGuLmZBYU=",
-      "dev": true,
-      "requires": {
-        "inherits": "~2.0.0"
-      }
-    },
-    "randomatic": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz",
-      "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==",
-      "dev": true,
-      "requires": {
-        "is-number": "^4.0.0",
-        "kind-of": "^6.0.0",
-        "math-random": "^1.0.1"
-      },
-      "dependencies": {
-        "is-number": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
-          "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
-          "dev": true
-        },
-        "kind-of": {
-          "version": "6.0.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
-          "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==",
-          "dev": true
-        }
-      }
-    },
-    "readable-stream": {
-      "version": "2.3.6",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-      "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
-      "dev": true,
-      "requires": {
-        "core-util-is": "~1.0.0",
-        "inherits": "~2.0.3",
-        "isarray": "~1.0.0",
-        "process-nextick-args": "~2.0.0",
-        "safe-buffer": "~5.1.1",
-        "string_decoder": "~1.1.1",
-        "util-deprecate": "~1.0.1"
-      }
-    },
-    "regex-cache": {
-      "version": "0.4.4",
-      "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
-      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
-      "dev": true,
-      "requires": {
-        "is-equal-shallow": "^0.1.3"
-      }
-    },
-    "remove-trailing-separator": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
-      "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
-      "dev": true
-    },
-    "repeat-element": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
-      "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
-      "dev": true
-    },
-    "repeat-string": {
-      "version": "1.6.1",
-      "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
-      "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
-      "dev": true
-    },
-    "replace-ext": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz",
-      "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=",
-      "dev": true
-    },
-    "request": {
-      "version": "2.88.0",
-      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
-      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
-      "dev": true,
-      "requires": {
-        "aws-sign2": "~0.7.0",
-        "aws4": "^1.8.0",
-        "caseless": "~0.12.0",
-        "combined-stream": "~1.0.6",
-        "extend": "~3.0.2",
-        "forever-agent": "~0.6.1",
-        "form-data": "~2.3.2",
-        "har-validator": "~5.1.0",
-        "http-signature": "~1.2.0",
-        "is-typedarray": "~1.0.0",
-        "isstream": "~0.1.2",
-        "json-stringify-safe": "~5.0.1",
-        "mime-types": "~2.1.19",
-        "oauth-sign": "~0.9.0",
-        "performance-now": "^2.1.0",
-        "qs": "~6.5.2",
-        "safe-buffer": "^5.1.2",
-        "tough-cookie": "~2.4.3",
-        "tunnel-agent": "^0.6.0",
-        "uuid": "^3.3.2"
-      }
-    },
-    "requires-port": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
-      "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
-      "dev": true
-    },
-    "rimraf": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
-      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
-      "dev": true,
-      "requires": {
-        "glob": "^7.0.5"
-      }
-    },
-    "safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
-      "dev": true
-    },
-    "safer-buffer": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
-      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
-      "dev": true
-    },
-    "semver": {
-      "version": "5.5.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz",
-      "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==",
-      "dev": true
-    },
-    "source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-      "dev": true
-    },
-    "source-map-support": {
-      "version": "0.5.9",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz",
-      "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==",
-      "dev": true,
-      "requires": {
-        "buffer-from": "^1.0.0",
-        "source-map": "^0.6.0"
-      }
-    },
-    "split": {
-      "version": "0.3.3",
-      "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz",
-      "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=",
-      "dev": true,
-      "requires": {
-        "through": "2"
-      }
-    },
-    "sshpk": {
-      "version": "1.14.2",
-      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz",
-      "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=",
-      "dev": true,
-      "requires": {
-        "asn1": "~0.2.3",
-        "assert-plus": "^1.0.0",
-        "bcrypt-pbkdf": "^1.0.0",
-        "dashdash": "^1.12.0",
-        "ecc-jsbn": "~0.1.1",
-        "getpass": "^0.1.1",
-        "jsbn": "~0.1.0",
-        "safer-buffer": "^2.0.2",
-        "tweetnacl": "~0.14.0"
-      }
-    },
-    "stat-mode": {
-      "version": "0.2.2",
-      "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz",
-      "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=",
-      "dev": true
-    },
-    "stream-combiner": {
-      "version": "0.0.4",
-      "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz",
-      "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=",
-      "dev": true,
-      "requires": {
-        "duplexer": "~0.1.1"
-      }
-    },
-    "stream-shift": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz",
-      "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=",
-      "dev": true
-    },
-    "streamfilter": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/streamfilter/-/streamfilter-1.0.7.tgz",
-      "integrity": "sha512-Gk6KZM+yNA1JpW0KzlZIhjo3EaBJDkYfXtYSbOwNIQ7Zd6006E6+sCFlW1NDvFG/vnXhKmw6TJJgiEQg/8lXfQ==",
-      "dev": true,
-      "requires": {
-        "readable-stream": "^2.0.2"
-      }
-    },
-    "streamifier": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz",
-      "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=",
-      "dev": true
-    },
-    "string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "~5.1.0"
-      }
-    },
-    "strip-bom": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
-      "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
-      "dev": true,
-      "requires": {
-        "is-utf8": "^0.2.0"
-      }
-    },
-    "strip-bom-stream": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz",
-      "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=",
-      "dev": true,
-      "requires": {
-        "first-chunk-stream": "^1.0.0",
-        "strip-bom": "^2.0.0"
-      }
-    },
-    "supports-color": {
-      "version": "5.4.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
-      "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
-      "dev": true,
-      "requires": {
-        "has-flag": "^3.0.0"
-      },
-      "dependencies": {
-        "has-flag": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
-          "dev": true
-        }
-      }
-    },
-    "tar": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
-      "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
-      "dev": true,
-      "requires": {
-        "block-stream": "*",
-        "fstream": "^1.0.2",
-        "inherits": "2"
-      }
-    },
-    "through": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
-      "dev": true
-    },
-    "through2": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz",
-      "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=",
-      "dev": true,
-      "requires": {
-        "readable-stream": "^2.1.5",
-        "xtend": "~4.0.1"
-      }
-    },
-    "through2-filter": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz",
-      "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=",
-      "dev": true,
-      "requires": {
-        "through2": "~2.0.0",
-        "xtend": "~4.0.0"
-      }
-    },
-    "to-absolute-glob": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz",
-      "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=",
-      "dev": true,
-      "requires": {
-        "extend-shallow": "^2.0.1"
-      },
-      "dependencies": {
-        "extend-shallow": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
-          "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
-          "dev": true,
-          "requires": {
-            "is-extendable": "^0.1.0"
-          }
-        }
-      }
-    },
-    "tough-cookie": {
-      "version": "2.4.3",
-      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
-      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
-      "dev": true,
-      "requires": {
-        "psl": "^1.1.24",
-        "punycode": "^1.4.1"
-      }
-    },
-    "tunnel-agent": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
-      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
-      "dev": true,
-      "requires": {
-        "safe-buffer": "^5.0.1"
-      }
-    },
-    "tweetnacl": {
-      "version": "0.14.5",
-      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
-      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
-      "dev": true,
-      "optional": true
-    },
-    "typescript": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.0.3.tgz",
-      "integrity": "sha512-kk80vLW9iGtjMnIv11qyxLqZm20UklzuR2tL0QAnDIygIUIemcZMxlMWudl9OOt76H3ntVzcTiddQ1/pAAJMYg==",
-      "dev": true
-    },
-    "unique-stream": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz",
-      "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=",
-      "dev": true,
-      "requires": {
-        "json-stable-stringify": "^1.0.0",
-        "through2-filter": "^2.0.0"
-      }
-    },
-    "url-parse": {
-      "version": "1.4.3",
-      "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.3.tgz",
-      "integrity": "sha512-rh+KuAW36YKo0vClhQzLLveoj8FwPJNu65xLb7Mrt+eZht0IPT0IXgSv8gcMegZ6NvjJUALf6Mf25POlMwD1Fw==",
-      "dev": true,
-      "requires": {
-        "querystringify": "^2.0.0",
-        "requires-port": "^1.0.0"
-      }
-    },
-    "util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
-      "dev": true
-    },
-    "uuid": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
-      "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==",
-      "dev": true
-    },
-    "vali-date": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz",
-      "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=",
-      "dev": true
-    },
-    "verror": {
-      "version": "1.10.0",
-      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
-      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
-      "dev": true,
-      "requires": {
-        "assert-plus": "^1.0.0",
-        "core-util-is": "1.0.2",
-        "extsprintf": "^1.2.0"
-      }
-    },
-    "vinyl": {
-      "version": "0.4.6",
-      "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
-      "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=",
-      "dev": true,
-      "requires": {
-        "clone": "^0.2.0",
-        "clone-stats": "^0.0.1"
-      }
-    },
-    "vinyl-fs": {
-      "version": "2.4.4",
-      "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz",
-      "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=",
-      "dev": true,
-      "requires": {
-        "duplexify": "^3.2.0",
-        "glob-stream": "^5.3.2",
-        "graceful-fs": "^4.0.0",
-        "gulp-sourcemaps": "1.6.0",
-        "is-valid-glob": "^0.3.0",
-        "lazystream": "^1.0.0",
-        "lodash.isequal": "^4.0.0",
-        "merge-stream": "^1.0.0",
-        "mkdirp": "^0.5.0",
-        "object-assign": "^4.0.0",
-        "readable-stream": "^2.0.4",
-        "strip-bom": "^2.0.0",
-        "strip-bom-stream": "^1.0.0",
-        "through2": "^2.0.0",
-        "through2-filter": "^2.0.0",
-        "vali-date": "^1.0.0",
-        "vinyl": "^1.0.0"
-      },
-      "dependencies": {
-        "clone": {
-          "version": "1.0.4",
-          "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
-          "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
-          "dev": true
-        },
-        "replace-ext": {
-          "version": "0.0.1",
-          "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
-          "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=",
-          "dev": true
-        },
-        "vinyl": {
-          "version": "1.2.0",
-          "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
-          "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=",
-          "dev": true,
-          "requires": {
-            "clone": "^1.0.0",
-            "clone-stats": "^0.0.1",
-            "replace-ext": "0.0.1"
-          }
-        }
-      }
-    },
-    "vinyl-source-stream": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/vinyl-source-stream/-/vinyl-source-stream-1.1.2.tgz",
-      "integrity": "sha1-YrU6E1YQqJbpjKlr7jqH8Aio54A=",
-      "dev": true,
-      "requires": {
-        "through2": "^2.0.3",
-        "vinyl": "^0.4.3"
-      }
-    },
-    "vscode": {
-      "version": "1.1.21",
-      "resolved": "https://registry.npmjs.org/vscode/-/vscode-1.1.21.tgz",
-      "integrity": "sha512-tJl9eL15ZMm6vzCYYeQ26sSYRuXGMGPsaeIAmG2rOOYRn01jdaDg6I4b9G5Ed6FISdmn6egpKThk4o4om8Ax/A==",
-      "dev": true,
-      "requires": {
-        "glob": "^7.1.2",
-        "gulp-chmod": "^2.0.0",
-        "gulp-filter": "^5.0.1",
-        "gulp-gunzip": "1.0.0",
-        "gulp-remote-src-vscode": "^0.5.0",
-        "gulp-symdest": "^1.1.0",
-        "gulp-untar": "^0.0.7",
-        "gulp-vinyl-zip": "^2.1.0",
-        "mocha": "^4.0.1",
-        "request": "^2.83.0",
-        "semver": "^5.4.1",
-        "source-map-support": "^0.5.0",
-        "url-parse": "^1.4.3",
-        "vinyl-source-stream": "^1.1.0"
-      },
-      "dependencies": {
-        "commander": {
-          "version": "2.11.0",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
-          "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
-          "dev": true
-        },
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "dev": true,
-          "requires": {
-            "ms": "2.0.0"
-          }
-        },
-        "diff": {
-          "version": "3.3.1",
-          "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz",
-          "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
-          "dev": true
-        },
-        "mocha": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz",
-          "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==",
-          "dev": true,
-          "requires": {
-            "browser-stdout": "1.3.0",
-            "commander": "2.11.0",
-            "debug": "3.1.0",
-            "diff": "3.3.1",
-            "escape-string-regexp": "1.0.5",
-            "glob": "7.1.2",
-            "growl": "1.10.3",
-            "he": "1.1.1",
-            "mkdirp": "0.5.1",
-            "supports-color": "4.4.0"
-          },
-          "dependencies": {
-            "glob": {
-              "version": "7.1.2",
-              "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
-              "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
-              "dev": true,
-              "requires": {
-                "fs.realpath": "^1.0.0",
-                "inflight": "^1.0.4",
-                "inherits": "2",
-                "minimatch": "^3.0.4",
-                "once": "^1.3.0",
-                "path-is-absolute": "^1.0.0"
-              }
-            }
-          }
-        },
-        "ms": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
-          "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
-          "dev": true
-        },
-        "supports-color": {
-          "version": "4.4.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
-          "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
-          "dev": true,
-          "requires": {
-            "has-flag": "^2.0.0"
-          }
-        }
-      }
-    },
-    "vscode-debugadapter": {
-      "version": "1.31.0",
-      "resolved": "https://registry.npmjs.org/vscode-debugadapter/-/vscode-debugadapter-1.31.0.tgz",
-      "integrity": "sha512-BbgaXlbLwHnIkndr/hZC6YqmI1aG5sqbIX8qmzpLPGY5hHaDTMB0zzdbDB6+ocSXG7z+FX4vE1l3V07977c4UA==",
-      "requires": {
-        "mkdirp": "^0.5.1",
-        "vscode-debugprotocol": "1.31.0"
-      },
-      "dependencies": {
-        "minimist": {
-          "version": "0.0.8",
-          "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
-          "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
-        },
-        "mkdirp": {
-          "version": "0.5.1",
-          "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
-          "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
-          "requires": {
-            "minimist": "0.0.8"
-          }
-        }
-      }
-    },
-    "vscode-debugprotocol": {
-      "version": "1.31.0",
-      "resolved": "https://registry.npmjs.org/vscode-debugprotocol/-/vscode-debugprotocol-1.31.0.tgz",
-      "integrity": "sha512-li8S5Z6eDoskVRxiGThaUSTw/WhevA6XcoprTZNvhwfqm1bLAb+bxqNPN6Qj2crh1XOEQOn5cL0DaZsDT2kxyQ=="
-    },
-    "wrappy": {
-      "version": "1.0.2",
-      "resolved": false,
-      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
-      "dev": true
-    },
-    "xtend": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
-      "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=",
-      "dev": true
-    },
-    "yauzl": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
-      "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=",
-      "dev": true,
-      "requires": {
-        "buffer-crc32": "~0.2.3",
-        "fd-slicer": "~1.1.0"
-      }
-    },
-    "yazl": {
-      "version": "2.4.3",
-      "resolved": "https://registry.npmjs.org/yazl/-/yazl-2.4.3.tgz",
-      "integrity": "sha1-7CblzIfVYBud+EMtvdPNLlFzoHE=",
-      "dev": true,
-      "requires": {
-        "buffer-crc32": "~0.2.3"
-      }
-    }
-  }
-}

+ 87 - 155
package.json

@@ -1,157 +1,89 @@
 {
-  "name": "godot-tools",
-  "displayName": "Godot Tools",
-  "icon": "icon.png",
-  "description": "Tools for game development with godot game engine",
-  "version": "0.3.7",
-  "publisher": "geequlim",
-  "repository": "https://github.com/GodotExplorer/godot-tools",
-  "license": "MIT",
-  "engines": {
-    "vscode": "^1.1.21"
-  },
-  "categories": [
-    "Other"
-  ],
-  "activationEvents": [
-    "workspaceContains:engine.cfg",
-    "workspaceContains:project.godot",
-    "onLanguage:gdscript"
-  ],
-  "main": "./out/src/extension",
-  "contributes": {
-    "commands": [
-      {
-        "command": "godot.updateWorkspaceSymbols",
-        "title": "GodotTools: Update workspace symbols"
-      },
-      {
-        "command": "godot.runWorkspace",
-        "title": "GodotTools: Run workspace as Godot project"
-      },
-      {
-        "command": "godot.openWithEditor",
-        "title": "GodotTools: Open workspace with Godot editor"
-      },
-      {
-        "command": "godot.runCurrentScene",
-        "title": "GodotTools: Run current scene"
-      }
-    ],
-    "configuration": {
-      "type": "object",
-      "title": "Godot Tools configuration",
-      "properties": {
-        "GodotTools.maxNumberOfProblems": {
-          "type": "number",
-          "default": 100,
-          "description": "Controls the maximum number of problems produced by the server."
-        },
-        "GodotTools.editorPath": {
-          "type": "string",
-          "default": "",
-          "description": "The absolute path to the Godot executable"
-        },
-        "GodotTools.workspaceDocumentWithMarkdown": {
-          "type": "boolean",
-          "default": false,
-          "description": "Render workspace documentations as Markdown content"
-        },
-        "GodotTools.ignoreIndentedVars": {
-          "type": "boolean",
-          "default": false,
-          "description": "Only parse variables without indents in GDScript"
-        },
-        "GodotTools.godotVersion": {
-          "type": "number",
-          "default": 3.0,
-          "description": "The Godot version of your project"
-        },
-        "GodotTools.parseTextScene": {
-          "type": "boolean",
-          "default": true,
-          "description": "Parse a file as a Godot scene when the file name ends with tscn"
-        },
-        "GodotTools.completeNodePath": {
-          "type": "boolean",
-          "default": false,
-          "description": "Show node paths within a workspace as part of code completion"
-        },
-        "GodotTools.godotProjectRoot": {
-          "type": "string",
-          "default": "${workspaceRoot}",
-          "description": "Your Godot project's directory"
-        },
-        "GodotTools.enableSyntaxChecking": {
-          "type": "boolean",
-          "default": true,
-          "description": "Turn on/off syntax checking for GDScript"
-        },
-        "GodotTools.lint": {
-          "type": "object",
-          "default": {
-            "semicolon": false,
-            "conditionBrackets": false,
-            "unusedSymbols": true
-          },
-          "description": "Lint configuration"
-        }
-      }
-    },
-    "languages": [
-      {
-        "id": "gdscript",
-        "aliases": [
-          "GDScript",
-          "gdscript"
-        ],
-        "extensions": [
-          ".gd"
-        ],
-        "configuration": "./configurations/gdscript-configuration.json"
-      },
-      {
-        "id": "properties",
-        "extensions": [
-          "cfg",
-          "tres",
-          "tscn",
-          "godot",
-          "gdns",
-          "gdnlib"
-        ]
-      }
-    ],
-    "grammars": [
-      {
-        "language": "gdscript",
-        "scopeName": "source.gdscript",
-        "path": "./configurations/GDScript.tmLanguage.json"
-      }
-    ],
-    "snippets": [
-      {
-        "language": "gdscript",
-        "path": "./configurations/snippets.json"
-      }
-    ]
-  },
-  "scripts": {
-    "vscode:prepublish": "tsc -p ./",
-    "compile": "node ./node_modules/typescript/bin/tsc -p ./",
-    "postinstall": "node ./node_modules/vscode/bin/install",
-    "test": "node ./node_modules/vscode/bin/test"
-  },
-  "devDependencies": {
-    "@types/mocha": "^5.2.5",
-    "@types/node": "^10.9.4",
-    "mocha": "^5.2.0",
-    "typescript": "^3.0.3",
-    "vscode": "^1.1.21"
-  },
-  "dependencies": {
-    "glob": "^7.1.1",
-    "vscode-debugprotocol": "^1.17.0",
-    "vscode-debugadapter": "^1.17.0"
-  }
+	"name": "godot-tools",
+	"displayName": "godot-tools",
+	"icon": "icon.png",
+	"version": "1.0.0",
+	"description": "Tools for game development with godot game engine",
+	"repository": "https://github.com/GodotExplorer/godot-tools",
+	"publisher": "geequlim",
+	"engines": {
+		"vscode": "^1.33.0"
+	},
+	"categories": [
+		"Other"
+	],
+	"activationEvents": [
+		"workspaceContains:project.godot",
+		"onLanguage:gdscript"
+	],
+	"main": "./out/extension.js",
+	"scripts": {
+		"vscode:prepublish": "yarn run compile",
+		"compile": "tsc -p ./",
+		"watch": "tsc -watch -p ./",
+		"postinstall": "node ./node_modules/vscode/bin/install",
+		"test": "yarn run compile && node ./node_modules/vscode/bin/test"
+	},
+	"contributes": {
+		"commands": [],
+		"configuration": {
+			"type": "object",
+			"title": "Godot Tools configuration",
+			"properties": {
+				"godot_tools.gdscript_lsp_server_port": {
+					"type": "number",
+					"default": 6008,
+					"description": "The websocket server port of the GDScript Langugae Protocol server"
+				}
+			}
+		},
+		"languages": [
+			{
+				"id": "gdscript",
+				"aliases": [
+					"GDScript",
+					"gdscript"
+				],
+				"extensions": [
+					".gd"
+				],
+				"configuration": "./configurations/gdscript-configuration.json"
+			},
+			{
+				"id": "properties",
+				"extensions": [
+					"cfg",
+					"tres",
+					"tscn",
+					"godot",
+					"gdns",
+					"gdnlib"
+				]
+			}
+		],
+		"grammars": [
+			{
+				"language": "gdscript",
+				"scopeName": "source.gdscript",
+				"path": "./configurations/GDScript.tmLanguage.json"
+			}
+		],
+		"snippets": [
+			{
+				"language": "gdscript",
+				"path": "./configurations/snippets.json"
+			}
+		]
+	},
+	"dependencies": {},
+	"devDependencies": {
+		"@types/mocha": "^2.2.42",
+		"@types/node": "^10.12.21",
+		"@types/ws": "^6.0.1",
+		"tslint": "^5.16.0",
+		"typescript": "^3.4.5",
+		"vscode": "^1.1.33",
+		"vscode-languageclient": "^5.2.1",
+		"websocket-stream": "^5.5.0"
+	}
 }

+ 0 - 331
src/config.ts

@@ -1,331 +0,0 @@
-import GDScriptSymbolParser from './gdscript/symbolparser';
-import * as fs from 'fs';
-import {CompletionItem, CompletionItemKind, TextEdit, Range, workspace} from 'vscode';
-
-interface NodeInfo {
-  name: string,
-  type: string,
-  parent: string,
-  instance: string
-};
-
-interface CompletionSymbols  {
-  classes : CompletionItem[],
-  functions : CompletionItem[],
-  signals : CompletionItem[],
-  constants : CompletionItem[],
-  properties : CompletionItem[],
-  nodes : CompletionItem[],
-  builtinConstants: CompletionItem[]
-};
-
-class Config {
-  
-  private workspaceSymbols; // filePath: GDScript in symbolparser.ts
-  private builtinCompletions : CompletionSymbols;
-  private builtinClassDoc;
-  public parser: GDScriptSymbolParser;
-  // scriptpath : scenepath
-  public scriptSceneMap: Object;
-  // scenepath : NodeInfo[]
-  public nodeInfoMap: Object;
-  // symbolname: {completionItem: CompletionItem, rowDoc: docdata}
-  public builtinSymbolInfoMap: Object;
-
-  constructor() {
-    this.builtinCompletions = {
-      classes : [],
-      functions : [],
-      signals : [],
-      constants : [],
-      properties : [],
-      nodes : [],
-      builtinConstants: []
-    };
-    this.workspaceSymbols = {};
-    this.builtinSymbolInfoMap = {};
-    this.nodeInfoMap = {};
-    this.scriptSceneMap = {};
-    this.parser = new GDScriptSymbolParser();
-  }
-
-  loadSymbolsFromFile(path) {
-    var ignoreIndentedVars = false;
-    if(workspace)
-      ignoreIndentedVars = workspace.getConfiguration("GodotTools").get("ignoreIndentedVars", false);
-    const script = this.parser.parseFile(path, ignoreIndentedVars);
-    this.setSymbols(path, script);
-    return script;
-  }
-
-  setSymbols(path, s) {
-    this.workspaceSymbols[this.normalizePath(path)] = s;
-  }
-
-  getSymbols(path) {
-    return this.workspaceSymbols[this.normalizePath(path)];
-  }
-
-  setAllSymbols(s) {
-    this.workspaceSymbols = s;
-  }
-  
-  getAllSymbols() {
-    return this.workspaceSymbols;
-  }
-
-  normalizePath(path) {
-    let newpath = path;
-    if( path.indexOf(":") != -1){
-      let parts = path.split(":");
-      newpath = parts[0].toUpperCase();
-      newpath += ":";
-      for(let i=1; i<parts.length; i++)
-        newpath += parts[i];
-    }
-    newpath = newpath.replace(/\\/g, "/");
-    return newpath;
-  }
-
-  loadClasses(docfile: string): boolean {
-    let done: boolean = false;
-    try {
-      if(fs.existsSync(docfile) && fs.statSync(docfile).isFile()) {
-        const content = fs.readFileSync(docfile, "utf-8");
-        const docdata = JSON.parse(content);
-        if(docdata.classes) {
-          this.builtinClassDoc = docdata.classes;
-          done = true;
-        }
-      }
-    } catch (error) {
-        console.error(error);
-    }
-    if(done) {
-      for (let key of Object.keys(this.builtinClassDoc)) {
-        const classdoc = this.builtinClassDoc[key];
-        const builtinSymbolInfoMap = this.builtinSymbolInfoMap;
-        // ----------------------  class -----------------
-        const item: CompletionItem = new CompletionItem(classdoc.name, CompletionItemKind.Class);
-        item.detail = 'Native Class';
-        item.documentation = classdoc.brief_description + " \n" +classdoc.description;
-        this.builtinCompletions.classes.push(item);
-        builtinSymbolInfoMap[classdoc.name] = {completionItem: item, rowDoc: classdoc};
-        // ----------------------- functions -----------------------
-        const parsMethod = (m, kind: CompletionItemKind, insertAction=(name)=>name)=>{
-          const mi = new CompletionItem(m.name, kind);
-          mi.insertText = insertAction(m.name) + (m.arguments.length==0?"()":"");
-          mi.filterText = m.name
-          mi.sortText = m.name
-          mi.detail = m.return_type;
-          let argstr = "";
-          m.arguments.map(arg=>{
-            argstr += `${arg.type} ${arg.name}${arg.default_value.length>0?'='+arg.default_value:''}${m.arguments.indexOf(arg)==m.arguments.length-1?'':', '}`;
-          });
-          // mi.label=`${m.name}(${argstr}) ${m.qualifiers}`;
-          let methodName = `${classdoc.name}.${m.name}`;
-          if (classdoc.name == m.name) methodName = m.name;
-          let mdoc = `${m.return_type} ${methodName}(${argstr}) ${m.qualifiers}`;
-          mdoc += " \n\n";
-          mdoc += m.description;
-          mi.documentation = mdoc;
-          if(CompletionItemKind.Interface == kind)
-            this.builtinCompletions.signals.push(mi);
-          else
-            this.builtinCompletions.functions.push(mi);
-          builtinSymbolInfoMap[`${classdoc.name}.${m.name}`] = {completionItem: mi, rowDoc: m};
-        };
-        // methods
-        const methods = classdoc.methods
-        methods.map(m=>parsMethod(m, CompletionItemKind.Method));
-        // signals
-        const signals = classdoc.signals;
-        signals.map(s=>parsMethod(s, CompletionItemKind.Interface));
-        // ------------------------------ constants ---------------------
-        const constants = classdoc.constants;
-        constants.map(c=>{
-          const ci = new CompletionItem(c.name, CompletionItemKind.Enum);
-          ci.detail = c.value;
-          ci.documentation = `${classdoc.name}.${c.name} = ${c.value}`;
-          if(key[0] == "@" || key == "Node" || key == "Control")
-            this.builtinCompletions.builtinConstants.push(ci);
-          else
-            this.builtinCompletions.constants.push(ci);
-          builtinSymbolInfoMap[`${classdoc.name}.${c.name}`] = {completionItem: ci, rowDoc: c};
-        });          
-        // ----------------------- properties -----------------------
-        const parseProp = (p) => {
-          const pi = new CompletionItem(p.name, CompletionItemKind.Property);
-          pi.detail = `${p.type} of ${classdoc.name}`;
-          pi.documentation = p.description;
-          this
-            .builtinCompletions
-            .properties
-            .push(pi);
-          builtinSymbolInfoMap[`${classdoc.name}.${p.name}`] = {
-            completionItem: pi,
-            rowDoc: p
-          };
-        };
-        // properties
-        const properties = classdoc.properties;
-        properties.map(p=>parseProp(p));
-        // theme_properties
-        const theme_properties = classdoc.theme_properties;
-        theme_properties.map(p=>parseProp(p));
-      }
-    }
-    return done;
-  };
-
-  getWorkspaceCompletionItems(script_files = []) : CompletionSymbols {
-      const symbols = {
-        classes: [],
-        functions: [],
-        signals: [],
-        constants: [],
-        properties: [],
-        nodes: [],
-        builtinConstants: []
-      };
-      if (script_files.length == 0)
-        script_files = Object.keys(this.workspaceSymbols);
-      for (let path of script_files) {
-        const script = this.workspaceSymbols[path];
-        if (workspace) {
-          const root = this.normalizePath(workspace.rootPath) + "/";
-          if (path.startsWith(root))
-            path = path.replace(root, "");
-        }
-        const addScriptItems = (items, kind: CompletionItemKind, kindName:string = "Symbol", insertText = (n)=>n)=>{
-          const _items: CompletionItem[] = [];
-          for (let name of Object.keys(items)) {
-            const signature = (script.signatures && script.signatures[name])?script.signatures[name]:"";
-            const cvalue = (script.constvalues && script.constvalues[name])?script.constvalues[name]:""; 
-            const item = new CompletionItem(name+signature, kind);
-            item.sortText = name;
-            item.filterText = name;
-            item.detail = cvalue;
-            item.insertText = insertText(name) + (signature=="()"?"()":"");
-            item.documentation = (script.documents && script.documents[name])?script.documents[name]+"\r\n":"";
-            item.documentation += `${kindName} defined in ${path}`;
-            _items.push(item);
-          }
-          return _items;
-        }
-
-        symbols.classes = [ ...(symbols.classes), ...(addScriptItems(script.classes, CompletionItemKind.Class, "Class"))]
-        symbols.functions = [ ...(symbols.functions), ...(addScriptItems(script.functions, CompletionItemKind.Method, "Method"))]
-        symbols.signals = [ ...(symbols.signals), ...(addScriptItems(script.signals, CompletionItemKind.Interface, "Signal"))]
-        symbols.properties = [ ...(symbols.properties), ...(addScriptItems(script.variables, CompletionItemKind.Variable, "Variable"))]
-        symbols.constants = [ ...(symbols.constants), ...(addScriptItems(script.constants, CompletionItemKind.Enum, "Constant"))]
-        
-        if(script.enumerations)
-          symbols.constants = [...(symbols.constants), ...(addScriptItems(script.enumerations, CompletionItemKind.Enum, "Enumeration"))];
-      }
-      
-      if(workspace.getConfiguration("GodotTools").get("completeNodePath", false)) {
-        const addSceneNodes = ()=>{
-          const _items: CompletionItem[] = [];
-          for (let scnenepath of Object.keys(this.nodeInfoMap)) {
-            const nodes: NodeInfo[] = this.nodeInfoMap[scnenepath];
-            nodes.map((n=>{
-              const item = new CompletionItem(n.name, CompletionItemKind.Reference);
-              item.detail = n.type;
-              item.documentation = `${n.parent}/${n.name} in ${scnenepath}`;
-              _items.push(item);
-
-              const fullitem = new CompletionItem(`${n.parent}/${n.name}`, CompletionItemKind.Reference);
-              fullitem.detail = n.type;
-              fullitem.filterText = n.name;
-              fullitem.sortText = n.name;
-              fullitem.documentation = `${n.parent}/${n.name} in ${scnenepath}`;
-              _items.push(fullitem);
-            }));
-          }
-          return _items;
-        };
-        symbols.nodes = [...(symbols.nodes), ...(addSceneNodes())];
-      }
-
-      return symbols;
-  }
-
-  loadScene(scenePath: string) {
-    if(fs.existsSync(scenePath) && fs.statSync(scenePath).isFile()) {
-      try {
-        const content: string = fs.readFileSync(scenePath, 'utf-8');
-        if(content) {
-          // extern resources
-          const exteres = {};
-          let reg = /ext_resource path="res:\/\/(.*)" type="(.*)" id=(\d+)/g;
-          let match = reg.exec(content);
-          while (match != null) {
-            const path = match[1];
-            const type = match[2];
-            const id = match[3];
-            exteres[id] = {path, type};
-            if (type == "Script") {
-              let workspacescenepath = scenePath;
-              if(workspace)
-                workspacescenepath = workspace.asRelativePath(scenePath);
-              this.scriptSceneMap[path] = workspacescenepath;
-            }
-            match = reg.exec(content);
-          }
-          // nodes
-          const nodes: NodeInfo[] = [];
-          reg = /node\s+name="(.*)"\s+type="(.*)"\s+parent="(.*)"/g;
-          match = reg.exec(content);
-          while (match != null) {
-            nodes.push({
-              name : match[1],
-              type : match[2],
-              parent : match[3],
-              instance: ""
-            });
-            match = reg.exec(content);
-          }
-          // packed scenes
-          reg = /node name="(.*)" parent="(.*)" instance=ExtResource\(\s*(\d+)\s*\)/g;
-          match = reg.exec(content);
-          while (match != null) {
-            const id = match[3];
-            nodes.push({
-              name : match[1],
-              type : exteres[id].type,
-              parent : match[2],
-              instance: exteres[id].path
-            });
-            match = reg.exec(content);
-          }
-          if(workspace)
-            scenePath = workspace.asRelativePath(scenePath);
-          this.nodeInfoMap[scenePath] = nodes;
-        }
-      } catch (error) {
-        console.error(error);
-      }
-    }
-  }
-
-  getClass(name: string) {
-    return this.builtinClassDoc[name];
-  }
-
-  getBuiltinCompletions() {
-    return this.builtinCompletions;
-  }
-
-  getBuiltinClassNameList() {
-    let namelist = null;
-    if (this.builtinClassDoc)
-      namelist = Object.keys(this.builtinClassDoc);
-    if(!namelist)
-      namelist = [];
-    return namelist;
-  }
-
-};
-
-export default new Config();

+ 0 - 162
src/debug/godotDebugger.ts

@@ -1,162 +0,0 @@
-// import {
-// 	DebugSession,
-// 	InitializedEvent, TerminatedEvent, StoppedEvent, BreakpointEvent, OutputEvent, Event,
-// 	Thread, StackFrame, Scope, Source, Handles, Breakpoint
-// } from 'vscode-debugadapter';
-// import {DebugProtocol} from 'vscode-debugprotocol';
-// import * as fs from 'fs';
-// import * as path from 'path';
-// const cmd = require('node-cmd');
-
-// export interface LaunchRequestArguments extends DebugProtocol.LaunchRequestArguments {
-// 	godot: string;
-// 	projectDir: string;
-// 	runWithEditor: boolean;
-// 	params: string[];
-// }
-
-// class GodotDebugSession extends DebugSession {
-
-// 	// we don't support multiple threads, so we can use a hardcoded ID for the default thread
-// 	private static THREAD_ID = 1;
-
-// 	/**
-// 	 * Creates a new debug adapter that is used for one debug session.
-// 	 * We configure the default implementation of a debug adapter here.
-// 	 */
-// 	public constructor() {
-// 		super();
-// 	}
-
-// 	/**
-// 	 * The 'initialize' request is the first request called by the frontend
-// 	 * to interrogate the features the debug adapter provides.
-// 	 */
-// 	protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
-
-// 		// since this debug adapter can accept configuration requests like 'setBreakpoint' at any time,
-// 		// we request them early by sending an 'initializeRequest' to the frontend.
-// 		// The frontend will end the configuration sequence by calling 'configurationDone' request.
-// 		this.sendEvent(new InitializedEvent());
-
-// 		// This debug adapter implements the configurationDoneRequest.
-// 		response.body.supportsConfigurationDoneRequest = true;
-
-// 		// make VS Code to use 'evaluate' when hovering over source
-// 		response.body.supportsEvaluateForHovers = true;
-
-// 		// make VS Code to show a 'step back' button
-// 		response.body.supportsStepBack = true;
-
-// 		this.log("initializeRequest");
-// 		this.log_err("initializeRequest");
-// 		this.log_console("initializeRequest");
-// 		this.sendResponse(response);
-// 	}
-
-// 	protected launchRequest(response: DebugProtocol.LaunchResponse, args: LaunchRequestArguments): void {
-// 		for(let key of Object.keys(args))
-// 			this.log(`${key} : ${args[key]}`);
-// 		let workspaceValid = false
-//         if(args.godot && fs.existsSync(args.godot) && fs.statSync(args.godot).isFile() ) {
-// 			if(args.projectDir && fs.existsSync(args.projectDir) && fs.statSync(args.projectDir).isDirectory() ) {
-// 				let cfg = path.join(args.projectDir, "engine.cfg");
-// 				if( fs.existsSync(cfg) && fs.statSync(cfg).isFile())
-// 					workspaceValid = true;
-// 			}
-// 		}
-// 		if(workspaceValid) {
-// 			let params = `-path ${args.projectDir} `;
-// 			if(args.runWithEditor)
-// 				params += "-e";
-// 			if(args.params) {
-// 				for(let p of args.params)
-// 					params += " " + p;
-// 			}
-// 			let cmdcontent = `${args.godot} ${params}`;
-// 			this.log(cmdcontent)
-// 			//  TODO: print outputs in terminal console
-// 			cmd.run(cmdcontent);
-// 			this.sendEvent(new TerminatedEvent());
-// 		}
-// 		else {
-// 			this.log_err("Invalidate path of projectDir or godot:");
-// 			this.log_err(JSON.stringify(args, null, '\t'));
-// 			this.sendEvent(new TerminatedEvent());
-// 		}
-// 	}
-	
-
-// 	protected setBreakPointsRequest(response: DebugProtocol.SetBreakpointsResponse, args: DebugProtocol.SetBreakpointsArguments): void {
-
-// 		this.sendResponse(response);
-// 	}
-
-// 	protected threadsRequest(response: DebugProtocol.ThreadsResponse): void {
-
-// 		// return the default thread
-// 		response.body = {
-// 			threads: [
-// 				new Thread(GodotDebugSession.THREAD_ID, "thread 1")
-// 			]
-// 		};
-// 		this.sendResponse(response);
-// 	}
-
-// 	/**
-// 	 * Returns a fake 'stacktrace' where every 'stackframe' is a word from the current line.
-// 	 */
-// 	protected stackTraceRequest(response: DebugProtocol.StackTraceResponse, args: DebugProtocol.StackTraceArguments): void {
-// 		this.sendResponse(response);
-// 	}
-
-// 	protected scopesRequest(response: DebugProtocol.ScopesResponse, args: DebugProtocol.ScopesArguments): void {
-// 		this.sendResponse(response);
-// 	}
-
-// 	protected variablesRequest(response: DebugProtocol.VariablesResponse, args: DebugProtocol.VariablesArguments): void {
-// 		this.sendResponse(response);
-// 	}
-
-// 	protected continueRequest(response: DebugProtocol.ContinueResponse, args: DebugProtocol.ContinueArguments): void {
-// 		this.sendEvent(new TerminatedEvent());
-// 	}
-
-// 	protected reverseContinueRequest(response: DebugProtocol.ReverseContinueResponse, args: DebugProtocol.ReverseContinueArguments) : void {
-// 		this.sendResponse(response);
-//  	}
-
-// 	protected nextRequest(response: DebugProtocol.NextResponse, args: DebugProtocol.NextArguments): void {
-// 		this.sendResponse(response);
-// 	}
-
-// 	protected stepBackRequest(response: DebugProtocol.StepBackResponse, args: DebugProtocol.StepBackArguments): void {
-// 		this.sendResponse(response);
-// 	}
-
-// 	protected evaluateRequest(response: DebugProtocol.EvaluateResponse, args: DebugProtocol.EvaluateArguments): void {
-// 		this.sendResponse(response);
-// 	}
-
-// 	/**
-// 	 * Fire StoppedEvent if line is not empty.
-// 	 */
-// 	private fireStepEvent(response: DebugProtocol.Response, ln: number): boolean {
-// 		return false;
-// 	}
-
-// 	private log(msg: string) {
-// 		const e = new OutputEvent(msg, "stdout");
-// 		this.sendEvent(e);
-// 	}
-// 	private log_err(msg: string) {
-// 		const e = new OutputEvent(msg, "stderr");
-// 		this.sendEvent(e);
-// 	}
-// 	private log_console(msg: string) {
-// 		const e = new OutputEvent(msg, "console");
-// 		this.sendEvent(e);
-// 	}
-// }
-
-// DebugSession.run(GodotDebugSession);

+ 16 - 13
src/extension.ts

@@ -1,13 +1,16 @@
-'use strict';
-import { workspace, Disposable, ExtensionContext } from 'vscode';
-import WindowWatch from "./window_watcher";
-import ToolManager from './tool_manager';
-
-let tool: ToolManager = null;
-
-export function activate(context: ExtensionContext) {
-	tool = new ToolManager(context);
-	context.subscriptions.push(tool);
-	context.subscriptions.push(new WindowWatch());
-	console.log("[GodotTools]: Extension Activated");
-}
+import { ExtensionContext } from "vscode";
+import GDScriptLanguageClient from "./lsp/GDScriptLanguageClient";
+
+let client: GDScriptLanguageClient = null;
+
+export function activate(context: ExtensionContext) {
+	client = new GDScriptLanguageClient();
+	context.subscriptions.push(client.start());
+}
+
+export function deactivate(): Thenable<void> {
+	if (client) {
+		return client.stop();
+	}
+	return new Promise((resolve, reject) => {});
+}

+ 0 - 106
src/gdscript/completion.ts

@@ -1,106 +0,0 @@
-import {
-  CompletionItemProvider,
-  Position,
-  TextDocument,
-  CancellationToken,
-  CompletionItem,
-  CompletionList,
-  languages,
-  Disposable,
-  CompletionItemKind
-} from 'vscode';
-
-import requestGodot from '../request';
-import config from '../config';
-
-interface CompleteRequest {
-  path: string,
-  text: string,
-  cursor: {
-    row: number,
-    column: number
-  }
-}
-
-interface CompletionResult {
-  suggestions: string[],
-  hint: string,
-  prefix: string,
-  valid: boolean
-}
-
-class GDScriptCompletionItemProvider implements CompletionItemProvider {
-
-  constructor() {
-  }
-
-  private get_previous_flag(document : TextDocument, position : Position): string {
-    const line = document.lineAt(position).text;
-    let res = "";
-    for (let index = position.character; index >= 0; index--) {
-      res = line[index];
-      if (['.', '$', '"', "'"].indexOf(res) != -1 )
-        break;
-    }
-    return res;
-  }
-
-  provideCompletionItems(document : TextDocument, position : Position, token : CancellationToken) : CompletionItem[] | Thenable < CompletionItem[] > | CompletionList | Thenable < CompletionList > {
-    
-    const lastFlag = this.get_previous_flag(document, position);
-    const builtins = config.getBuiltinCompletions();
-    
-    let items:CompletionItem[] = [...(builtins.builtinConstants)];
-    if(!lastFlag || lastFlag.trim().length == 0) {
-      const workspaces = config.getWorkspaceCompletionItems([config.normalizePath(document.fileName)]);
-      items = [
-        ...items,
-        ...(workspaces.functions),
-        ...(workspaces.classes),
-        ...(workspaces.constants),
-        ...(workspaces.properties),
-        ...(builtins.functions),
-        ...(builtins.classes),
-        ...(builtins.constants),
-      ]
-    }
-    else {
-      const workspaces = config.getWorkspaceCompletionItems();
-      if(lastFlag.trim() == ".") {
-        items = [
-          ...items,
-          ...(workspaces.functions),
-          ...(workspaces.constants),
-          ...(workspaces.properties),
-          ...(workspaces.classes),
-          ...(builtins.functions),
-          ...(builtins.constants),
-          ...(builtins.properties)
-        ]
-      }
-      else if(lastFlag.trim() == "'" || lastFlag.trim() == '"') {
-        items = [
-          ...items,
-          ...(workspaces.signals),
-          ...(workspaces.functions),
-          ...(workspaces.properties),
-          ...(builtins.signals),
-          ...(builtins.functions),
-          ...(builtins.properties),
-          ...(workspaces.nodes),
-        ]
-      }
-      else if(lastFlag.trim() == "$") {
-        items = [ ...(workspaces.nodes) ]
-      }
-    }
-    return items;
-  }
-
-  resolveCompletionItem(item : CompletionItem, token : CancellationToken) : CompletionItem | Thenable < CompletionItem > {
-    return item;
-  }
-
-}
-
-export default GDScriptCompletionItemProvider;

+ 0 - 91
src/gdscript/definitionprovider.ts

@@ -1,91 +0,0 @@
-import {
-    DefinitionProvider,
-    TextDocument,
-    Position,
-    CancellationToken,
-    Definition,
-    Location,
-    workspace,
-    Uri,
-    Range
-} from 'vscode';
-import * as path from 'path';
-import * as fs from 'fs';
-import config from '../config';
-import {isStr, getSelectedContent, getStrContent} from './utils';
-
-class GDScriptDefinitionProivder implements DefinitionProvider {
-    private _rootFolder : string = "";
-
-    constructor(rootFolder: string) {
-        this._rootFolder = rootFolder;
-    }
-
-    provideDefinition(document: TextDocument, position: Position, token: CancellationToken): Definition | Thenable < Definition > {
-        const getDefinitions = (content: string):Location[]| Location => {
-            if(content.startsWith("res://")) {
-                content = content.replace("res://", "");
-                if(workspace && workspace.rootPath) {
-                    content = path.join(this._rootFolder, content);
-                }
-                return new Location(Uri.file(content), new Range(0,0,0,0));
-            }
-            else if(fs.existsSync(content) && fs.statSync(content).isFile()) {
-                return new Location(Uri.file(content), new Range(0,0,0,0));
-            }
-            else {
-                const workspaceSymbols = config.getAllSymbols();
-                let locations: Location[] = [];
-                // check from workspace
-                for (let path of Object.keys(workspaceSymbols)) {
-                    const script = workspaceSymbols[path];
-                    if(path == "autoload" && script.constpathes && script.constpathes[content])
-                        path = script.constpathes[content];
-                    let scriptitems: Location[] = [];
-                    const checkDifinition = (items)=>{
-                        const _items: Location[] = [];
-                        for (let name of Object.keys(items)) {
-                            if(name == content) {
-                                _items.push(new Location(Uri.file(path), items[name]));
-                                break;
-                            }
-                        }
-                        return _items;
-                    }
-                    scriptitems = [...scriptitems, ...checkDifinition(script.variables)];
-                    scriptitems = [...scriptitems, ...checkDifinition(script.constants)];
-                    scriptitems = [...scriptitems, ...checkDifinition(script.functions)];
-                    scriptitems = [...scriptitems, ...checkDifinition(script.signals)];
-                    scriptitems = [...scriptitems, ...checkDifinition(script.classes)];
-                    if(script.enumerations)
-                        scriptitems = [...scriptitems, ...checkDifinition(script.enumerations)];
-                    locations = [...locations, ...scriptitems];
-                }
-                // check from builtin
-                if(config.getClass(content) != null) {
-                    const uri = encodeURI('command:vscode.previewHtml?' + JSON.stringify(Uri.parse(`godotdoc://${content}`)));
-                    locations.push(new Location(Uri.parse(uri), new Range(0,0,0,0)));
-                }
-                return locations;
-            }
-        };
-        
-        return new Promise((resolve, reject) => {
-            let selStr = getSelectedContent(document, position);
-            if(selStr) {
-                // For strings
-                if(isStr(selStr)) {
-                    selStr =  getStrContent(selStr);
-                    let fpath = path.join(path.dirname(document.uri.fsPath), selStr)
-                    if(fs.existsSync(fpath) && fs.statSync(fpath).isFile())
-                        selStr = fpath
-                }
-                resolve(getDefinitions(selStr));
-            }
-            else
-                reject(new Error("Empty selection"));
-        });
-    }
-}
-
-export default GDScriptDefinitionProivder;

+ 0 - 194
src/gdscript/diagnostic.ts

@@ -1,194 +0,0 @@
-import requestGodot from "../request";
-import * as vscode from 'vscode';
-import {DiagnosticCollection, DiagnosticSeverity} from 'vscode';
-import config from '../config';
-
-interface GDParseError {
-  message : string,
-  column : number,
-  row : number
-}
-
-interface GDScript {
-  members : {
-    constants: {},
-    functions: {},
-    variables: {},
-    signals: {}
-  },
-  base : string,
-  errors : GDParseError[],
-  valid : boolean,
-  is_tool : boolean,
-  native : string
-}
-
-interface ParseRequest {
-  text : string,
-  path : string
-}
-
-class GDScriptDiagnosticSeverity {
-  private _subscription : DiagnosticCollection;
-
-  constructor() {
-    this._subscription = vscode.languages.createDiagnosticCollection("gdscript")
-  }
-
-  dispose() {
-    this._subscription.dispose()
-  }
-
-  async validateScript(doc : vscode.TextDocument, script : any) {
-    if (doc.languageId == 'gdscript') {
-      if (script) {
-        let diagnostics = [ ...(this.validateExpression(doc)), ...(this.validateUnusedSymbols(doc, script)) ];
-        this._subscription.set(doc.uri, diagnostics);
-        return true;
-      }
-    }
-    return false;
-  }
-
-  private validateUnusedSymbols(doc : vscode.TextDocument, script) {
-    let diagnostics = [];
-    let cfg : any = vscode.workspace.getConfiguration("GodotTools").get("lint");
-    if (!cfg.unusedSymbols)
-      return diagnostics
-
-    const text = doc.getText();
-    const check = (name : string, range : vscode.Range) => {
-      var matchs = text.match(new RegExp(`([^\\w]|\\[|\\{)\\s*${name}\\s*([^\\w]|\\[|\\{)`, 'g'));
-      let count = matchs ? matchs.length : 0;
-      var incomment = text.match(new RegExp(`#.*?([^\\w]|\\[|\\{)\\s*${name}\\s*([^\\w]|\\[|\\{)`, 'g'));
-      count -= incomment ? incomment.length : 0;
-      if (count <= 1) 
-        diagnostics.push(new vscode.Diagnostic(range, `${name} is never used.`, DiagnosticSeverity.Warning));
-    };
-    // Unused variables
-    for (let key of Object.keys(script.variables)) 
-      check(key, script.variables[key]);
-    for (let key of Object.keys(script.constants)) 
-      check(key, script.constants[key]);
-    return diagnostics;
-  }
-
-  private validateExpression(doc : vscode.TextDocument) {
-    let cfg : any = vscode.workspace.getConfiguration("GodotTools").get("lint");
-
-    let diagnostics = [];
-    let expectEndOfLine = false;
-    const text = doc.getText();
-    const lines = text.split(/\r?\n/);
-    lines.map((line : string, i : number) => {
-      let matchstart = /[^\s]+.*/.exec(line);
-      let curLineStartAt = 0;
-      if (matchstart) 
-        curLineStartAt = matchstart.index;
-      
-      // ignore comments
-      if (line.match(/^\s*#.*/) || line.match(/^#.*/)) 
-        return
-      // normalize line content
-      line = "\t" + line + "\t";
-      var range = new vscode.Range(i, curLineStartAt, i, line.length);
-
-      if (cfg.semicolon && line.match(/[^#].*?\;/) && !line.match(/[#].*?\;/)) {
-        const semicolonIndex = line.indexOf(';');
-        diagnostics.push(new vscode.Diagnostic(new vscode.Range(i, semicolonIndex, i, semicolonIndex + 1), "Statement contains a semicolon.", DiagnosticSeverity.Warning));
-      }
-      if (line.match(/[^#].*?/) && expectEndOfLine) {
-        if (!line.match(/.*?(\\|\:)/)) {
-          diagnostics.push(new vscode.Diagnostic(range, "': or \\' expected at end of the line.", DiagnosticSeverity.Error));
-          expectEndOfLine = false;
-        }
-        if (line.match(/.*?\:/)) 
-          expectEndOfLine = false;
-      }
-      const colonKeywords = /\b(if|elif|else|for|while|func|class|match)\b/;
-      let keywords = line.match(colonKeywords)
-      if (keywords) {
-        if(line.match(new RegExp(`".*?\\s${keywords[1]}\\s.*?"`)) || line.match(new RegExp(`'.*?\\s${keywords[1]}\\s.*?\'`)))
-          return
-        if(line.match(new RegExp(`.*?#.*?\\s${keywords[1]}\\s.*?`)))
-          return
-        if(line.match(/.*?\sif\s+(\!|\[|\{|\w|").*?\s+else\s+[^\s]+/))
-          return
-        if (line.match(/.*?\\/))
-          expectEndOfLine = true;
-        else if (line.match(/.*?\:[\s+]+[^#\s]+/)) 
-          return
-        else if (!line.match(/.*?(\\|\:)/))
-          diagnostics.push(new vscode.Diagnostic(range, "': or \\' expected at end of the line.", DiagnosticSeverity.Error));
-        else if (line.match(/\s(if|elif|while|func|class|match)\s*\:/)) 
-          diagnostics.push(new vscode.Diagnostic(range, "Indentifier expected before ':'", DiagnosticSeverity.Error));
-        else if (line.match(/[^\w]for[^\w]/) && !line.match(/\s+for\s\w+\s+in\s+|[\w+]|\{.*?\}|\[.*?\]|\(.*?\)/)){
-          if(!(line.match(/".*?for.*?"/) || line.match(/'.*?for.*?'/)))
-            diagnostics.push(new vscode.Diagnostic(range, "Invalid for expression", DiagnosticSeverity.Error));
-        }
-        else if (cfg.conditionBrackets && line.match(/\s(if|elif|while|match)\s*\(.*\)\s*:\s*$/)) 
-          diagnostics.push(new vscode.Diagnostic(range, "Extra brackets in condition expression.", DiagnosticSeverity.Warning));
-        const blockIndetCheck = function() {
-          const err = new vscode.Diagnostic(range, "Expected indented block after expression", DiagnosticSeverity.Error);
-          if (i < lines.length - 1) {
-            let next = i + 1;
-            let nextline = lines[next];
-            // changes nextline until finds a line containg text or comes to the last line
-            while (((!nextline || !nextline.trim().length) || nextline.match(/^\s*#/)) && next < lines.length - 1) {
-              ++next;
-              nextline = lines[next];
-            }
-            let nextLineStartAt = -1;
-            let match = /[^\s]+.*/.exec(nextline);
-            if (match) 
-              nextLineStartAt = match.index;
-            
-            if (nextLineStartAt <= curLineStartAt) 
-              diagnostics.push(err);
-          }
-          else if(line.match(/\:\s*$/))
-            diagnostics.push(err);
-        };
-        if(!expectEndOfLine)
-          blockIndetCheck();
-      }
-      // Do not check : for end of statement as it breaks match statment
-      let endOfStateMentWithComma = false;
-      if(endOfStateMentWithComma && !line.match(colonKeywords) && line.match(/\:\s*$/)) {
-        let showErr = true;
-        if( i >= 1 ) {
-          let previous = i - 1;
-          let previousline = lines[previous];
-          while(previousline.match(/\\\s*$/) && previous>=1) {
-            --previous;
-            const ppreviousline = lines[previous];
-            if(ppreviousline.match(/\\\s*$/))
-              previousline = ppreviousline;
-          }
-          const keywords = previousline.match(colonKeywords);
-          if(keywords && !(previousline.match(new RegExp(`".*?\\s${keywords[1]}\\s.*?"`)) || previousline.match(new RegExp(`'.*?\\s${keywords[1]}\\s.*?'`)) ))
-            showErr = false
-        }
-        if(showErr)
-          diagnostics.push(new vscode.Diagnostic(range, "Expected end of statement after expression", DiagnosticSeverity.Error));
-      }
-      if (line.match(/(if|elif|while|return)\s+\w+\s*=\s*\w+/)) 
-        diagnostics.push(new vscode.Diagnostic(range, "Assignment in condition or return expressions", DiagnosticSeverity.Warning));
-      else if (line.indexOf("==") > 0 && !line.match(/\:\s*/)) {
-        const endAt = line.indexOf("==");
-        const precontent = line.substring(0, endAt);
-      if (!precontent.match(/\s(if|elif|while|return)\s/) && !precontent.match(/=[^=]/) && !precontent.match(/assert\s*\(/) && !expectEndOfLine) {
-          diagnostics.push(new vscode.Diagnostic(range, "Unhandled comparation expression contains", DiagnosticSeverity.Warning));
-        }
-      }
-      let match = /var\s+(\w+)\s*=\s*(\w+)/.exec(line);
-      if (match && match.length > 2 && match[1].length > 0 && match[1] == match[2]) {
-        diagnostics.push(new vscode.Diagnostic(range, "Self Assignment may cause error.", DiagnosticSeverity.Warning));
-      }
-    });
-    return diagnostics;
-  }
-
-}
-
-export default GDScriptDiagnosticSeverity;

+ 0 - 325
src/gdscript/docprovider.ts

@@ -1,325 +0,0 @@
-import {TextDocumentContentProvider, DocumentLinkProvider, Uri, CancellationToken } from 'vscode';
-import config from '../config';
-
-const linkStyle = `
-<style>
-    a { color: #6e8ae7; text-decoration: none;}
-</style>
-`;
-
-function genLink(title:string, uri:string, span=true):string {
-    const u = encodeURI('command:vscode.previewHtml?' + JSON.stringify(Uri.parse(`godotdoc://${uri}`)));
-    let link = `<a href="${u}">${title}</a>`;
-    if(span)
-        link = `<span>${link}</span>`;
-    return link;
-};
-
-function getProp(rawDoc:any, propname: string, action=(s :string)=>s): string {
-    let prop = rawDoc[propname];
-    return action(prop);
-}
-
-class GDScriptDocumentContentProvider implements TextDocumentContentProvider{
-    constructor() {
-    }
-
-    /**
-     * Provide textual content for a given uri.
-     *
-     * The editor will use the returned string-content to create a readonly
-     * [document](TextDocument). Resources allocated should be released when
-     * the corresponding document has been [closed](#workspace.onDidCloseTextDocument).
-     *
-     * @param uri An uri which scheme matches the scheme this provider was [registered](#workspace.registerTextDocumentContentProvider) for.
-     * @param token A cancellation token.
-     * @return A string or a thenable that resolves to such.
-     */
-    provideTextDocumentContent(uri: Uri, token: CancellationToken): string | Thenable<string> {
-        const request = uri.authority;
-        let classname = request;
-        let membername = null;
-        const self = this;
-        return new Promise((resolve, reject) => {
-            if(request.indexOf(".") != -1) {
-                classname = request.substring(0, request.indexOf("."));
-                if(!request.endsWith("."))
-                    membername = request.substring(request.indexOf(".")+1, request.length);
-            }
-            if(classname.length >= 1) {
-                for(let key of config.getBuiltinClassNameList()) {
-                    if(key.toLowerCase() == classname) {
-                        classname = key;
-                        break;
-                    }
-                }
-            }
-
-            if(classname && classname.length > 0) {
-                if(membername && membername.length >0 )
-                    resolve(self.genMemberDoc(classname, membername)) ;
-                else
-                    resolve(self.genClassDoc(config.getClass(classname)));
-            }
-            reject(new Error("Open Documentation Failed!"));
-        });
-    }
-
-    format_documentation(text: string): string {
-        let doc = text.replace(/\[code\]/g, "<code>").replace(/\[\/code\]/g, "</code>");    
-        doc = doc.replace(/\[codeblock\]/g, '<pre><code class="gdscript">').replace(/\[\/codeblock]/g, "</code></pre>");
-        doc = doc.replace(/\[i\]/g, "<i>").replace(/\[\/i\]/g, "</i>");
-        doc = doc.replace(/\[b\]/g, "<b>").replace(/\[\/b\]/g, "</b>");
-        doc = doc.replace(/\[u\]/g, "<u>").replace(/\[\/u\]/g, "</u>");
-        doc = doc.replace(/\n\t\t\t\t/g, "\n\t");        
-        return doc;
-    };
-
-    genMethodDoc(mDoc:any):string {
-        let ret_type = getProp(mDoc, "return_type", (type:string):string =>{
-            if(type.length > 0)
-                return `${genLink(type,type)} `;
-            else
-                return "void";
-        });
-        let args = "";
-        for(let arg of mDoc.arguments){
-            if(mDoc.arguments.indexOf(arg)!=0)
-                args += ", ";
-            args += `${genLink(arg.type, arg.type)} ${arg.name}`
-            if(arg.default_value && arg.default_value.length > 0)
-                args += `=${arg.default_value}`;
-        }
-        var docContent = mDoc.description;
-        if (!docContent) {
-            docContent = `There is currently no description for this method. Please help us by <span><a href="http://docs.godotengine.org/en/latest/community/contributing/updating_the_class_reference.html">contributing one</a></span>!`;
-        }
-        let doc = `
-            <li>
-                <h4 id="${mDoc.name}">${ret_type} ${mDoc.name} (${args}) <i>${mDoc.qualifiers}</i></h4>
-                <p>${docContent}</p>
-            </li>
-        `;
-        return doc;
-    }
-
-    genPropHeader(mDoc:any, classname:string): string {
-        let type = getProp(mDoc, "type", (type:string):string => `${genLink(type,type)} `);
-        return `<li>${type} ${genLink(mDoc.name, classname+"."+mDoc.name)}</li>`;
-    }
-
-    genMethodHeader(mDoc:any, classname:string):string {
-        let ret_type = getProp(mDoc, "return_type", (type:string):string =>{
-            if(type.length > 0)
-                return `${genLink(type,type)} `;
-            else
-                return "void";
-        });
-        let args = "";
-        for(let arg of mDoc.arguments){
-            if(mDoc.arguments.indexOf(arg)!=0)
-                args += ", ";
-            args += `${genLink(arg.type, arg.type)} ${arg.name}`
-            if(arg.default_value && arg.default_value.length > 0)
-                args += `=${arg.default_value}`;
-        }
-        let doc = `
-            <li>
-                ${ret_type} ${genLink(mDoc.name, classname+"."+mDoc.name)} (${args}) <i>${mDoc.qualifiers}</i>
-            </li>
-        `;  
-        return doc;
-    }
-
-
-    genPropDoc(pDoc:any): string {
-        let setter = pDoc.setter;
-        if(setter) setter = `<li>Setter: ${setter}(value)</li>`; else setter = "";
-        let getter = pDoc.getter;
-        if(getter) getter = `<li>Getter: ${getter}()</li>`; else getter = "";
-        let descContent = pDoc.description;
-        if(!descContent) {
-            descContent = `There is currently no description for this property. Please help us by <span><a href="http://docs.godotengine.org/en/latest/community/contributing/updating_the_class_reference.html">contributing one</a></span>!`;
-        }
-        let doc = `
-            <li>
-                <h4>${genLink(pDoc.type,pDoc.type)} ${pDoc.name}</h4> 
-                <ul>
-                    ${setter}
-                    ${getter}
-                </ul>
-                <p>${descContent}</p>
-            </li>
-        `;
-        return doc;
-    }
-
-    genConstDoc(cDoc:any): string {
-        let doc = `
-            <li>
-                <h4>${cDoc.name} = ${cDoc.value}</h4>
-                <p>${cDoc.description}</p>
-            </li>
-        `;
-        return doc;
-    }
-
-    genMemberDoc(classname, membername): string {
-        let realDoc = null;
-        const classdoc = config.getClass(classname);
-        if(!classdoc)
-            return null;
-        for(let m of classdoc.methods) {
-            if(m.name.toLowerCase() == membername) {
-                realDoc = this.genMethodDoc(m);
-                break;
-            }
-        }
-        if(!realDoc) {
-            for(let s of classdoc.signals) {
-                if(s.name.toLowerCase() == membername) {
-                    realDoc = this.genMethodDoc(s);
-                    break;
-                }
-            }
-        }
-
-        if(!realDoc) {
-            for(let c of classdoc.constants) {
-                if(c.name.toLowerCase() == membername) {
-                    realDoc = this.genConstDoc(c);
-                    break;
-                }
-            }
-        }
-
-        if(!realDoc) {
-            for(let p of classdoc.properties) {
-                if(p.name.toLowerCase() == membername) {
-                    realDoc = this.genPropDoc(p);
-                    break;
-                }
-            }
-        }
-
-        if(!realDoc) {
-            for(let p of classdoc.theme_properties) {
-                if(p.name.toLowerCase() == membername) {
-                    realDoc = this.genPropDoc(p);
-                    break;
-                }
-            }
-        }
-        
-        if(!realDoc)
-            return null;
-        
-        let doc = `
-            ${linkStyle}
-            <h2>Documentation of ${genLink(classname, classname)}.${membername}</h2>
-            <ul>${realDoc}</ul>
-        `;
-        return doc;
-    }
-
-    genClassDoc(rawDoc): string {
-        if(!rawDoc)
-            return null;
-        const classname = rawDoc.name;
-        let inherits = getProp(rawDoc, "inherits", (inherits:string)=>{
-            if (!inherits) return "";
-            return "<h4>Inherits: " + genLink(inherits, inherits, true) +"</h4>";
-        });
-
-        let category = getProp(rawDoc, "category", (c:string)=>{
-            return "<h4>Category: " + c +"</h4>";
-        });
-
-        let subclasses = "";
-        for(let key of config.getBuiltinClassNameList()) {
-            let c = config.getClass(key);
-            if(c && c.inherits == classname) {
-                subclasses += genLink(key, key, true) + " "
-            }
-        };
-        if(subclasses && subclasses.length > 0)
-            subclasses = "<h3>Inherited by</h3> " + "<ul><li>" + subclasses + "</li></ul>";
-        
-        let briefDescript = getProp(rawDoc, "brief_description", (dec:string)=>{
-            return dec;
-        });
-        let descript = getProp(rawDoc, "description", (dec:string)=>{
-            if(dec)
-                return "<h3>Description</h3>" + "<ul><li>" + dec + "</li></ul>";
-            else
-                return "";
-        });
-
-        const setter_getters = {};
-        let propHeaders = ""
-        for(let p of rawDoc.properties) {
-            propHeaders += this.genPropHeader(p, classname);
-            if(p.setter)
-                setter_getters[p.setter] = true;
-            if(p.getter)
-                setter_getters[p.getter] = true;
-        }
-        if(propHeaders.length >0)
-            propHeaders = `<h3>Member List</h3><ul>${propHeaders}</ul/>`;
-
-        let methodHeaders = ""
-        let methods = "";
-        for(let m of rawDoc.methods) {
-            if(setter_getters[m.name]) continue;
-            methodHeaders += this.genMethodHeader(m, classname);
-            methods += this.genMethodDoc(m);
-        }
-        if(methodHeaders.length >0)
-            methodHeaders = `<h3>Public Methods</h3><ul>${methodHeaders}</ul/>`;
-        if(methods.length >0 )
-            methods = `<h3>Public Methods</h3><ul>${methods}</ul/>`;
-        
-        let signals = "";
-        for(let s of rawDoc.signals) {
-            signals += this.genMethodDoc(s);
-        }
-        if(signals.length >0 )
-            signals = `<h3>Signals</h3><ul>${signals}</ul/>`;
-
-        let props = "";
-        for(let p of rawDoc.properties) {
-            props += this.genPropDoc(p)
-        }
-        for(let p of rawDoc.theme_properties) {
-            props += this.genPropDoc(p)
-        }
-        if(props.length >0 )
-            props = `<h3>Properties</h3><ul>${props}</ul>`
-
-        let constants = "";
-        for(let c of rawDoc.constants) {
-            constants += this.genConstDoc(c);
-        }
-        if(constants.length >0 )
-            constants = `<h3>Constants</h3><ul>${constants}</ul>`
-        
-        let doc = `
-            ${linkStyle}
-            <h1>Native Class ${classname}</h1>
-            <h4>${briefDescript}</h4>
-            <p>${category}</p>
-            <p>${inherits}</p>
-            <p>${subclasses}</p>
-            <p>${descript}</p>
-            <p>${propHeaders}</p>
-            <p>${methodHeaders}</p>
-            <p>${signals}</p>
-            <p>${constants}</p>
-            <p>${props}</p>
-            <p>${methods}</p>
-        `;
-        return this.format_documentation(doc);
-    }
-}
-
-export default GDScriptDocumentContentProvider;

+ 0 - 195
src/gdscript/hoverprovider.ts

@@ -1,195 +0,0 @@
-import {
-    HoverProvider,
-    TextDocument,
-    Position,
-    CancellationToken,
-    Hover,
-    MarkdownString,
-    workspace,
-    Uri,
-    CompletionItem,
-    CompletionItemKind
-} from 'vscode';
-import {
-    isStr,
-    getSelectedContent,
-    getStrContent
-} from './utils';
-import config from '../config';
-import * as path from 'path';
-
-
-function genLink(title:string, uri:string):string {
-    const u = encodeURI('command:vscode.previewHtml?' + JSON.stringify(Uri.parse(`godotdoc://${uri}`)));
-    return `[${title}](${u})`;
-};
-
-class GDScriptHoverProvider implements HoverProvider {
-    constructor() {}
-
-    provideHover(document: TextDocument, position: Position, token: CancellationToken): Hover | Thenable < Hover > {
-        let hoverText = getSelectedContent(document, position);
-        if (isStr(hoverText))
-            hoverText = getStrContent(hoverText);
-        const workspaceSymbols = config.getAllSymbols();
-        let tips: MarkdownString[] = [];
-        const withMarkdwon = workspace.getConfiguration("GodotTools").get("workspaceDocumentWithMarkdown", false);
-
-
-        const makeMarkdown = (content): MarkdownString => {
-            let md = new MarkdownString(content);
-            md.isTrusted = true;
-            return md;
-        }
-
-        // check from workspace
-        const genWorkspaceTips = ()=> {
-            for (let filepath of Object.keys(workspaceSymbols)) {
-                const script = workspaceSymbols[filepath];
-                let scriptips: MarkdownString[] = [];
-                const getHoverText = (items, type, gdpath): MarkdownString[] => {
-                    const _items: MarkdownString[] = [];
-                    for (let name of Object.keys(items)) {
-                        if (name == hoverText) {
-                            let dfile = gdpath;
-                            if (workspace) {
-                                const root = config.normalizePath(workspace.rootPath) + "/";
-                                if (gdpath.startsWith(root))
-                                    dfile = gdpath.replace(root, "");
-                            }
-                            let signature = "";
-                            if(type == "func"|| type == "signal" && script.signatures[name])
-                                signature = script.signatures[name];
-                            if(type == "const" && script.constvalues[name])
-                                signature = ` = ${script.constvalues[name]}`;
-                            let doc ='```gdscript\n' + `${type} ${name}${signature}` + '\n```\n';
-                            let rowDoc = script.documents[name];
-                            if(!withMarkdwon)
-                                rowDoc += "```plaintext\r\n"+rowDoc+"\r\n```";
-                            doc += rowDoc;
-                            doc = doc?doc+"\r\n\r\n":"";
-                            if(gdpath != "autoload")
-                                doc += `*Defined in [${dfile}](${Uri.file(gdpath).toString()})*`;
-                            _items.push(makeMarkdown(doc));
-                            break;
-                        }
-                    }
-                    return _items;
-                }
-                scriptips = [...scriptips, ...getHoverText(script.variables, 'var', filepath)];
-                scriptips = [...scriptips, ...getHoverText(script.constants, 'const', filepath)];
-                scriptips = [...scriptips, ...getHoverText(script.functions, 'func', filepath)];
-                scriptips = [...scriptips, ...getHoverText(script.signals, 'signal', filepath)];
-                scriptips = [...scriptips, ...getHoverText(script.classes, 'class', filepath)];
-                if(script.enumerations)
-                    scriptips = [...scriptips, ...getHoverText(script.enumerations, 'const', filepath)];
-                tips = [...tips, ...scriptips];
-            }
-        };
-        
-        // check from scnes
-        const genNodePathTips = ()=> {
-            for (let scnenepath of Object.keys(config.nodeInfoMap)) {
-                const nodes: any[] = config.nodeInfoMap[scnenepath];
-                for (let index = 0; index < nodes.length; index++) {
-                    const node:any = nodes[index];
-                    const fullpath = node.parent + "/" + node.name;
-                    if(fullpath == hoverText || fullpath.endsWith(hoverText)) {
-                        let filepath = scnenepath;
-                        if(workspace && workspace.rootPath)
-                            filepath = path.join(workspace.rootPath, filepath);
-                        let instance = "";
-                        if(node.instance && node.instance.length > 1) {
-                            let instancepath = node.instance;
-                            if(workspace && workspace.rootPath)
-                                instancepath = path.join(workspace.rootPath, instancepath);
-                            instance = ` which is an instance of *[${node.instance}](${Uri.file(instancepath).toString()})*`;
-                        }
-                        tips = [...tips, 
-                            makeMarkdown(`${genLink(node.type, node.type)} ${fullpath}`),
-                            makeMarkdown(`${node.type} defined in *[${scnenepath}](${Uri.file(filepath).toString()})*${instance}`)
-                        ];
-                        break;
-                    }
-                }
-            }
-        };
-
-        const format_documentation = (text, cls="") => {
-            let doc = text.replace(/\[code\]/g, "`").replace(/\[\/code\]/g, "`");    
-            doc = doc.replace(/\[codeblock\]/g, "\n```gdscript\n").replace(/\[\/codeblock]/g, "\n```");
-            doc = doc.replace(/\[i\]/g, "*").replace(/\[\/i\]/g, "*");
-            doc = doc.replace(/\[b\]/g, "**").replace(/\[\/b\]/g, "**");
-            doc = doc.replace(/\[u\]/g, "__").replace(/\[\/u\]/g, "__");
-            doc = doc.replace(/\n\t\t\t\t/g, "\n");
-            return doc;
-        };
-
-        // check from builtin
-        const genBuiltinTips = ()=> {
-            const item2MarkdStrings = (name: string,item: CompletionItem, rowDoc: any):MarkdownString => {
-                let value = "";
-                let doc = format_documentation(item.documentation);
-                // get class name
-                let classname = name;
-                let matchs = name.match(/[@A-z][A-z0-9]*\./);
-                if(matchs) {
-                    classname = matchs[0];
-                    if(classname.endsWith("."))
-                        classname = classname.substring(0, classname.length -1);
-                }
-
-                const genMethodMarkDown = ():string =>{
-                    let content = `${genLink(rowDoc.return_type, rowDoc.return_type)} `;
-                    if (rowDoc.name != classname) content += `${genLink(classname, classname)}.`;
-                    let args = "";
-                    for(let arg of rowDoc.arguments){
-                        if(rowDoc.arguments.indexOf(arg)!=0)
-                            args += ", ";
-                        args += `${genLink(arg.type, arg.type)} ${arg.name}`
-                        if(arg.default_value && arg.default_value.length > 0)
-                            args += `=${arg.default_value}`;
-                    }
-                    content += `${genLink(rowDoc.name, classname+'.' + rowDoc.name)}(${args}) ${rowDoc.qualifiers}`;
-                    return content;
-                };
-                
-                switch (item.kind) {
-                    case CompletionItemKind.Class:
-                        return makeMarkdown(`Native Class ${genLink(classname, classname)}\n${doc}`);
-                    case CompletionItemKind.Method:
-                        doc = doc.substring(doc.indexOf("\n")+1, doc.length);
-                        return makeMarkdown(`${genMethodMarkDown()}\n${doc}`);
-                    case CompletionItemKind.Interface:
-                        doc = doc.substring(doc.indexOf("\n")+1, doc.length);
-                        return makeMarkdown(`signal ${genMethodMarkDown()}\n${doc}`);
-                    case CompletionItemKind.Variable:
-                    case CompletionItemKind.Property:
-                        return makeMarkdown(`${rowDoc.type} ${genLink(classname, classname)}.${genLink(rowDoc.name, classname + "." + rowDoc.name)}\n${doc}`);
-                    case CompletionItemKind.Enum:
-                        return makeMarkdown(`const ${genLink(classname, classname)}.${genLink(rowDoc.name, classname + "." + rowDoc.name)} = ${rowDoc.value}\n${doc}`);
-                    default:
-                        break;
-                }
-                return makeMarkdown(`${name}  ${doc}`);
-            };
-            for (let name of Object.keys(config.builtinSymbolInfoMap)) {
-                const pattern = `[A-z@_]+[A-z0-9_]*\\.${hoverText}\\b`;
-                if(name == hoverText || name.match(new RegExp(pattern))) {
-                    const item: {completionItem: CompletionItem, rowDoc: any} = config.builtinSymbolInfoMap[name];
-                    tips = [...tips, item2MarkdStrings(name, item.completionItem, item.rowDoc)];
-                }
-            }
-        };
-        genBuiltinTips();
-        genWorkspaceTips();
-        genNodePathTips();
-        
-        if (tips.length > 0)
-            return new Hover(tips);
-        else
-            return null;
-    }
-}
-
-export default GDScriptHoverProvider;

+ 0 - 109
src/gdscript/signature_helper.ts

@@ -1,109 +0,0 @@
-import {
-  SignatureHelpProvider,
-  TextDocument,
-  Position,
-  CancellationToken,
-  SignatureInformation,
-  SignatureHelp,
-  CompletionItemKind,
-  ParameterInformation,
-  workspace
-} from 'vscode';
-import config from '../config';
-import { countSubStr } from './utils';
-class GDScriptSignatureHelpProvider implements SignatureHelpProvider {
-  constructor() {}
-
-  provideSignatureHelp(document : TextDocument, position : Position, token : CancellationToken) : SignatureHelp | Thenable < SignatureHelp > {
-    const self = this;
-    return new Promise((resolve, reject) => {
-      const res = self.do_provideSignatureHelp(document, position);
-      resolve(res);
-    });
-  }
-  /**
-   * Provide help for the signature at the given position and document.
-   *
-   * @param document The document in which the command was invoked.
-   * @param position The position at which the command was invoked.
-   * @param token A cancellation token.
-   * @return Signature help or a thenable that resolves to such. The lack of a result can be
-   * signaled by returning `undefined` or `null`.
-   */
-  do_provideSignatureHelp(document : TextDocument, position : Position) : SignatureHelp | Thenable < SignatureHelp > {
-    const range = document.getWordRangeAtPosition(position);
-    let funcname = "";
-    let curparam = 0;
-    const checkPosition = () => {
-      const line = document.lineAt(position);
-      const startPos = line.firstNonWhitespaceCharacterIndex;
-      const endPos = position.character;
-      const queryStr = line.text.substring(startPos, endPos);
-      
-      var reg = /([A-z_]+[A-z0-9_]*)\(/g;
-      let match = reg.exec(queryStr);
-      while (match != null) {
-        funcname = match[1];
-        match = reg.exec(queryStr);
-      }
-      if(funcname != "") {
-        const funcrangestr = line.text.substring(line.text.indexOf(queryStr)+queryStr.indexOf(funcname)+funcname.length, endPos);
-        curparam = countSubStr(funcrangestr, ",");
-      }
-
-    };
-
-    checkPosition();
-
-    let resultSignatures: SignatureInformation[] = [];
-
-    if (funcname.length > 0) {
-      // Builtin functions
-      for (let key of Object.keys(config.builtinSymbolInfoMap)) {
-        if (key.endsWith(`\.${funcname}`)) {
-          if (config.builtinSymbolInfoMap[key].completionItem.kind == CompletionItemKind.Method || config.builtinSymbolInfoMap[key].completionItem.kind == CompletionItemKind.Function) {
-            const rawDoc = config.builtinSymbolInfoMap[key].rowDoc;
-            const item = config.builtinSymbolInfoMap[key].completionItem;
-            let signatureInfor: SignatureInformation = new SignatureInformation(item.documentation.split('\n')[0], rawDoc.description);
-            for(let arg of rawDoc.arguments){
-              let param: ParameterInformation = new ParameterInformation(`${arg.type} ${arg.name}${arg.default_value.length>0?'='+arg.default_value:''}`, "");
-              signatureInfor.parameters.push(param);
-            }
-            resultSignatures.push(signatureInfor);
-          }
-        }
-      }
-      // workspace functions
-      for (let path of Object.keys(config.getAllSymbols())) {
-          let script = config.getSymbols(path);
-          if(!script.signatures)
-            continue
-          let relaPath = path;
-          if(workspace && workspace.rootPath)
-            relaPath = workspace.asRelativePath(relaPath);
-          
-          for(let f of Object.keys(script.signatures)) {
-            if(f == funcname) {
-              const signatureStr = script.signatures[f];
-              let signature: SignatureInformation = new SignatureInformation(`func ${f}${signatureStr}`, `Method defined in ${relaPath}`);
-              const params = (signatureStr.substring(signatureStr.indexOf("(")+1, signatureStr.indexOf(")"))).split(",");
-              for(let p of params)
-                signature.parameters.push(new ParameterInformation(p, ""));
-              resultSignatures.push(signature);
-            }
-          }
-      }
-    }
-    if(resultSignatures.length > 0) {
-      return ({
-        signatures: resultSignatures,
-        activeSignature: 0,
-        activeParameter: curparam
-      });
-    }
-    return null
-}
-
-}
-
-export default GDScriptSignatureHelpProvider;

+ 0 - 236
src/gdscript/symbolparser.ts

@@ -1,236 +0,0 @@
-import {Range} from 'vscode';
-import * as fs from 'fs';
-
-interface GDScript {
-  constants: {},
-  functions: {},
-  variables: {},
-  signals: {},
-  classes: {},
-  base: string,
-  native: string,
-  signatures: {},
-  // symbol: marked string
-  documents: {},
-  // name : value
-  constvalues: {},
-  enumerations: {}
-}
-
-class GDScriptSymbolParser {
-  constructor() {
-  }
-
-  parseContent(content: string, ignoreIndentedVars:boolean = false): GDScript {
-    const script: GDScript = {
-        constants: {},
-        functions: {},
-        variables: {},
-        signals: {},
-        classes: {},
-        base: "",
-        native: "",
-        signatures: {},
-        documents: {},
-        constvalues: {},
-        enumerations: {}
-    }
-    const text  = content;
-    const lines = text.split(/\r?\n/);
-    
-    // Base class and native class
-    for (let line of lines) {
-      let match;
-      if (match = line.match(/extends\s+(\w+)/)) {
-        script.native = match[1];
-        break;
-      } else if (match = line.match(/extends\s+('|")(.*)('|")/)) {
-        script.base = match[2];
-      }
-    }
-
-    const getMatches = (regex:RegExp, index=1) => {
-      var matches = [];
-      for(let line of lines) {
-        let match;
-        if (match = regex.exec(line)) {
-          let commentReg = RegExp(/#.*?/.source+regex.source);
-          if(!commentReg.exec(line))
-            matches.push(match[index]);
-        }
-      }
-      return matches;
-      // var matches = [];
-      // var match;
-      // while (match = regex.exec(string)) {
-      //   matches.push(match[index]);
-      // }
-      // return matches;
-    };
-    
-    const findLineRanges = (symbols, reg)=>{
-      const sm = {};
-      symbols.map((name:string)=>{
-        let line = 0;
-        let curline = 0;
-        if(Object.keys(sm).indexOf(name) != -1) return;
-        lines.map(l=>{
-          const nreg = reg.replace("$X$", name);
-          if(l.match(nreg) != null) {
-            line = curline;
-            return;
-          }
-          curline += 1;
-        });
-        sm[name] = line;
-      });
-      return sm;
-    }
-    
-    const determRange = (key:string, array: any): Range =>{
-      let line = array[key];
-      let startAt = lines[line].indexOf(key);
-      if(line < 0) line = 0;
-      if(startAt < 0) startAt = 0;
-      return new Range(line, startAt, line, startAt + key.length);
-    };
-
-    const parseSignature = (range: Range):string => {
-      let res = "";
-      const line = lines[range.start.line];
-      if(line.indexOf("(")!= -1 && line.indexOf(")")!=-1) {
-        const signature = line.substring(line.indexOf("("), line.indexOf(")")+1);
-        if(signature && signature.length >0)
-          res = signature;
-      }
-      return res;
-    };
-
-    const parseDocument = (range: Range):string => {
-      let mdoc = ""
-      let line = range.start.line;
-      while( line > 0){
-        const linecontent = lines[line];
-        let match = linecontent.match(/\s*#\s*(.*)/);
-        let commentAtEnd = linecontent.match(/[\w'",\[\{\]\}\(\)]+\s*#\s*(.*)/) != null;
-        if(commentAtEnd && linecontent.match(/^#/))
-          commentAtEnd = false;
-        if(!match && line != range.start.line)
-          break;
-        if(commentAtEnd && line != range.start.line)
-          break;
-        if(match) {
-          let lmcontent = linecontent.substring(linecontent.indexOf("#")+1, linecontent.length);
-          if(lmcontent.startsWith(" ") && lmcontent != " ")
-            lmcontent = lmcontent.substring(1, lmcontent.length);
-          mdoc = lmcontent + "\r\n" + mdoc;
-        }
-        else if(line != range.start.line)
-          break
-        --line;
-      }
-      return mdoc;
-    }
-    
-    let funcsnames = getMatches(/func\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*\(/, 1);
-    const funcs = findLineRanges(funcsnames, "func\\s+$X$\\s*\\(");
-    for (let key of Object.keys(funcs)) {
-      let r: Range = determRange(key, funcs);
-      script.functions[key] = r;
-      script.signatures[key] = parseSignature(r);
-      script.documents[key] = parseDocument(r);
-    }
-    
-    let signalnames = getMatches(/signal\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*\(/, 1);
-    const signals = findLineRanges(signalnames, "signal\\s+$X$\\s*\\(");
-    for (let key of Object.keys(signals)) {
-      let r: Range = determRange(key, signals);
-      script.signals[key] = r;
-      script.signatures[key] = parseSignature(r);
-      script.documents[key] = parseDocument(r);
-    }
-
-    let varreg = /var\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*/;
-    let varreg2 = "var\\s+$X$([^\\w]|$)";
-    let vargroup = 1;
-    if(ignoreIndentedVars) {
-      varreg = /^((export.*?var)|var)\s+([_A-Za-z]+[_A-Za-z0-9]*)\s?/;
-      varreg2 = "^((export.*?var)|var)\\s+$X$\\s?";
-      vargroup = 3;
-    }
-    let varnames = getMatches(varreg, vargroup);
-    const vars = findLineRanges(varnames, varreg2);
-    for (let key of Object.keys(vars)){
-      const r:Range = determRange(key, vars)
-      script.variables[key] = r;
-      let newdoc = parseDocument(r);
-      if(newdoc == "" && script.documents[key])
-        newdoc = script.documents[key];
-      script.documents[key] = newdoc;
-    }
-    
-    let constnames = getMatches(/const\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*/, 1);
-    const consts = findLineRanges(constnames, "const\\s+$X$\\s*");
-    for (let key of Object.keys(consts)){
-      const r:Range = determRange(key, consts)
-      script.constants[key] = r;
-      let newdoc = parseDocument(r);
-      if(newdoc == "" && script.documents[key])
-        newdoc = script.documents[key];
-      script.documents[key] = newdoc;
-      
-      const linecontent = lines[r.start.line];
-      const match = linecontent.match(/const\s+([_A-Za-z]+[_A-Za-z0-9]*)\s*=\s*([\w+]+\(.*\)|"[^"]*"|\-?\d+\.?\d*|\[.*\]|\{.*\})/);
-      if(match && match.length && match.length >1)
-        script.constvalues[key] = match[2];
-    }
-    
-    let classnames = getMatches(/class\s+([_A-Za-z]+[_A-Za-z0-9]*)(\s|\:)/, 1);
-    const classes = findLineRanges(classnames, "class\\s+$X$(\\s|\\:)");
-    for (let key of Object.keys(classes)) {
-      const r:Range = determRange(key, classes)
-      script.classes[key] = r;
-      script.documents[key] = parseDocument(r);
-    }
-
-    let enumnames = getMatches(/enum\s+([_A-Za-z]+[_A-Za-z0-9]*)\s+\{/, 1);
-    const enums = findLineRanges(enumnames, "enum\\s+$X$\\s+\{");
-    for (let key of Object.keys(enums)) {
-      const r:Range = determRange(key, enums)
-      script.constants[key] = r;
-      script.documents[key] = parseDocument(r);
-      
-      let curindex = r.start.line
-      while (curindex < lines.length) {
-        const line = lines[curindex];
-        let matchs = line.match(/([_A-Za-z]+[_A-Za-z0-9]*)/g);
-        if(matchs && matchs.length >= 1 ){
-          for (var i = 0; i < matchs.length; i++)
-            if(line.indexOf(matchs[i]) > line.indexOf("{"))
-              script.enumerations[matchs[i]] = new Range(curindex, 0, curindex, line.length);
-        }
-        if(line.indexOf("}") == -1)
-          curindex += 1;
-        else
-          break;
-      }
-    }
-    // TODO: enumerations without name
-    // const unnamedEnums = text.match(/enum\s+\{.*\}/gm)
-
-
-    return script;
-  }
-
-  parseFile(path:string, ignoreIndentedVars:boolean = false): GDScript {
-    const self = this;
-    if(fs.existsSync(path) && fs.statSync(path).isFile()){
-      const content = fs.readFileSync(path, 'utf-8');
-      return this.parseContent(content, ignoreIndentedVars);
-    }
-    return null;
-  }
-
-}
-
-export default GDScriptSymbolParser;

+ 0 - 62
src/gdscript/symbolprovider.ts

@@ -1,62 +0,0 @@
-import {
-  DocumentSymbolProvider,
-  TextDocument,
-  SymbolInformation,
-  CancellationToken,
-  SymbolKind,
-  Range,
-  workspace
-} from 'vscode';
-
-import GDScriptSymbolParser from '../gdscript/symbolparser';
-import config from '../config';
-
-class GDScriptSymbolProvider implements DocumentSymbolProvider {
-  private parser: GDScriptSymbolParser = null;
-
-  constructor() {
-    this.parser = new GDScriptSymbolParser();
-  }
-
-  provideDocumentSymbols(document: TextDocument, token: CancellationToken): SymbolInformation[] | Thenable<SymbolInformation[]> {
-
-    const symbols: SymbolInformation[] = [];
-    var ignoreIndentedVars = false;
-    if(workspace)
-      ignoreIndentedVars = workspace.getConfiguration("GodotTools").get("ignoreIndentedVars", false);
-    const script = this.parser.parseContent(document.getText(), ignoreIndentedVars);
-    const signatures = script.signatures;
-    config.setSymbols(document.fileName, script);
-
-    const funcs = script.functions;
-    for (let key of Object.keys(funcs))
-      symbols.push(new SymbolInformation(key+signatures[key], SymbolKind.Function, funcs[key]));
-    
-    const signals = script.signals;
-    for (let key of Object.keys(signals))
-      symbols.push(new SymbolInformation(key+signatures[key], SymbolKind.Interface, signals[key]));
-
-    const vars = script.variables;
-    for (let key of Object.keys(vars))
-      symbols.push(new SymbolInformation(key, SymbolKind.Variable, vars[key]));
-    
-    const consts = script.constants;
-    for (let key of Object.keys(consts))
-      symbols.push(new SymbolInformation(key, SymbolKind.Constant, consts[key]));
-
-    const classes = script.classes;
-    for (let key of Object.keys(classes))
-      symbols.push(new SymbolInformation(key, SymbolKind.Class, classes[key]));
-    
-    if(script.enumerations) {
-      const enumerations = script.enumerations;
-      for (let key of Object.keys(enumerations))
-        symbols.push(new SymbolInformation(key, SymbolKind.Enum, enumerations[key]));
-    }
-
-    return symbols;
-  }
-
-}
-
-export default GDScriptSymbolProvider;

+ 0 - 41
src/gdscript/utils.ts

@@ -1,41 +0,0 @@
-import {TextDocument, Position} from 'vscode';
-
-export function isStr(content:string) {
-    return (content.startsWith("'") || content.startsWith('"') || content.startsWith('@"') ) && (content.endsWith("'") || content.endsWith('"'));
-}
-
-export function getSelectedContent(document: TextDocument, position: Position):string {
-    const line = document.lineAt(position);
-    const wordRange = document.getWordRangeAtPosition(position) ;
-    const machs = line.text.match(/[A-z_]+[A-z_0-9]*|".*?"|'.*?'|@".*?"/g)
-    let res = line.text.substring(wordRange.start.character, wordRange.end.character);
-    machs.map(m=>{
-        if(m) {
-            const startPos = line.text.indexOf(m);
-            const endPos = startPos + m.length;
-            if(isStr(m) && startPos != -1 && wordRange.start.character >= startPos && wordRange.end.character <= endPos){
-                res = m;
-                return;
-            }
-        }
-    });
-    return res;
-};
-
-export function getStrContent(rawstr: string):string {
-    let ss = rawstr;
-    if(isStr(ss)) {
-        ss = ss.replace(/"|'|@"|"""/g,"")
-    }
-    return ss;
-}
-
-export function countSubStr(str:string, sub:string): number {
-    let count = 0;
-    let pos = str.indexOf(sub);
-    while (pos !== -1) {
-        count++;
-        pos = str.indexOf(sub, pos + sub.length);
-    }
-    return count;
-}

+ 0 - 40
src/gdscript/workspace_symbol_provider.ts

@@ -1,40 +0,0 @@
-import * as vscode from 'vscode';
-import config from '../config';
-
-class GDScriptWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider {
-    public provideWorkspaceSymbols(query: string, token: vscode.CancellationToken): vscode.SymbolInformation[] {
-      const scripts = config.getAllSymbols();
-      const symbols: vscode.SymbolInformation[] = [];
-      for (let path of Object.keys(scripts)) {
-        const queryMembers = (query, members, kind: vscode.SymbolKind, path:string, extra=(text)=>text)=> {
-          for (let name of Object.keys(members)) {
-            const range: vscode.Range = members[name];
-            if(name.toLowerCase().indexOf(query.toLowerCase()) != -1) {
-              const symbol: vscode.SymbolInformation = {
-                name: extra(name),
-                kind,
-                containerName: "",
-                location: {
-                  uri: vscode.Uri.file(path),
-                  range
-                }
-              };
-              symbols.push(symbol);
-            }
-          }
-        }
-        const scrip = scripts[path];
-        const signatures = scrip.signatures;
-        queryMembers(query, scrip.functions, vscode.SymbolKind.Function, path, (name)=>(name+signatures[name]));
-        queryMembers(query, scrip.signals, vscode.SymbolKind.Interface, path, (name)=>(name+signatures[name]));
-        queryMembers(query, scrip.variables, vscode.SymbolKind.Variable, path);
-        queryMembers(query, scrip.constants, vscode.SymbolKind.Constant, path);
-        queryMembers(query, scrip.classes, vscode.SymbolKind.Class, path);
-        if(scrip.enumerations)
-          queryMembers(query, scrip.enumerations, vscode.SymbolKind.Enum, path);
-      }
-      return symbols;
-    }
-}
-
-export default GDScriptWorkspaceSymbolProvider;

+ 47 - 0
src/loggger.ts

@@ -0,0 +1,47 @@
+export class Logger {
+	protected buffer: string = "";
+	protected tag: string = '';
+	protected time: boolean = false;
+	
+	constructor(tag: string, time: boolean) {
+		this.tag = tag;
+		this.time = time;
+	}
+	
+	clear() {
+		this.buffer = "";
+	}
+	
+	log(...messages) {
+		
+		let line = '';
+		if (this.tag) {
+			line += `[${this.tag}]`;
+		}
+		if (this.time) {
+			line += `[${new Date().toISOString()}]`;
+		}
+		if (line) {
+			line += ' ';
+		}
+		
+		for (let index = 0; index < messages.length; index++) {
+			line += messages[index];
+			if (index < messages.length) {
+				line += " ";
+			} else {
+				line += "\n";
+			}
+		}
+		
+		this.buffer += line;
+		console.log(line);
+	}
+	
+	get_buffer(): string {
+		return this.buffer;
+	}
+}
+
+const logger = new Logger('godot-tools', true);
+export default logger;

+ 48 - 0
src/lsp/GDScriptLanguageClient.ts

@@ -0,0 +1,48 @@
+import { workspace } from "vscode";
+import * as websocket from "websocket-stream";
+import { LanguageClient, LanguageClientOptions, ServerOptions } from "vscode-languageclient";
+import { is_debug_mode, get_configuration } from "../utils";
+import logger from "../loggger";
+
+function getClientOptions(): LanguageClientOptions {
+	return {
+		// Register the server for plain text documents
+		documentSelector: [
+			{ scheme: "file", language: "gdscript" },
+			{ scheme: "untitled", language: "gdscript" },
+		],
+		synchronize: {
+			// Notify the server about file changes to '.gd files contain in the workspace
+			fileEvents: workspace.createFileSystemWatcher("**/*.gd"),
+		},
+	};
+}
+
+const serverOptions: ServerOptions = () => {
+	return new Promise((resolve, reject) => {
+		let port = get_configuration("gdscript_lsp_server_port", 6008);
+		const ws = websocket(`ws://localhost:${port}`);
+		if (is_debug_mode()) {
+			let text = '';
+			ws.on('data', (chunk)=>{
+				let message = chunk.toString();
+				text += message;
+				logger.log("[server]", message);
+			});
+			const origin_write = ws._write.bind(ws);
+			ws._write = (function (chunk: any, encoding: string, callback: (error?: Error | null) => void) {
+				let message = chunk.toString();
+				text += message;
+				origin_write(chunk, encoding, callback);
+				logger.log("[client]", message);
+			}).bind(ws);
+		}
+		resolve({reader: ws, writer: ws});
+	});
+};
+
+export default class GDScriptLanguageClient extends LanguageClient {
+	constructor() {
+		super(`GDScriptLanguageClient`, serverOptions, getClientOptions());
+	}
+};

+ 0 - 40
src/request.ts

@@ -1,40 +0,0 @@
-import * as http from 'http';
-import * as vscode from 'vscode';
-
-function requestGodot(body : Object) {
-    let postString = JSON.stringify(body);
-    const port = vscode.workspace.getConfiguration("GodotTools").get("editorServerPort", 6996);
-    const options = {
-        hostname: '127.0.0.1',
-        method: 'POST',
-        port,
-        body,
-        headers: {
-            "Accept": "application/json",
-            "Connection": "keep-alive",
-            "Content-Type": "application/json",
-            "Content-Length": Buffer.byteLength(postString)
-        }
-    };
-    let promise = new Promise((resolve, reject) => {
-        var req = http.request(options, (res) => {
-            let resultString = "";
-            res.setEncoding('utf8');
-            res.on('data', (chunk) => {
-                resultString += chunk;
-            });
-            res.on('end', () => {
-                resolve(JSON.parse(resultString));
-            });
-        });
-        req.on('error', (e) => {
-            reject(e);
-        });
-        req.write(postString);
-        req.end();
-
-    });
-    return promise;
-}
-
-export default requestGodot;

+ 0 - 283
src/tool_manager.ts

@@ -1,283 +0,0 @@
-import * as vscode from 'vscode';
-import godotRequest from './request';
-import GDScriptSymbolProvider from './gdscript/symbolprovider';
-import GDScriptWorkspaceSymbolProvider from './gdscript/workspace_symbol_provider';
-import GDScriptCompletionItemProvider from './gdscript/completion';
-import GDScriptDefinitionProivder from './gdscript/definitionprovider';
-import GDScriptHoverProvider from './gdscript/hoverprovider';
-import GDScriptDocumentContentProvider from './gdscript/docprovider';
-import GDScriptSignatureHelpProvider from './gdscript/signature_helper';
-var glob = require("glob")
-import config from './config';
-import * as path from 'path';
-import * as fs from 'fs';
-class ToolManager {
-
-  private workspaceDir: string = "";
-  private symbolprovider: GDScriptSymbolProvider = null;
-  private workspacesymbolprovider: GDScriptWorkspaceSymbolProvider = null;
-  private _disposable: vscode.Disposable;
-  private _context: vscode.ExtensionContext;
-  private _projectFile : string = "project.godot";
-  private _rootDir : string = "";
-  private _biuitinDocFile : string = "doc/classes-3.0.json";
-
-  constructor(context: vscode.ExtensionContext) {
-    this._context = context;
-    this.workspaceDir = vscode.workspace.rootPath;
-    let completionDollar = false;
-
-    if (vscode.workspace.getConfiguration("GodotTools").get("godotVersion", 3.0) < 3) {
-      this._projectFile = "engine.cfg";
-      this._biuitinDocFile = "doc/classes-2.1.json";
-      completionDollar = true;
-    }
-    this.loadClasses();
-
-    if (vscode.workspace && this.workspaceDir) {
-      vscode.workspace.registerTextDocumentContentProvider('godotdoc', new GDScriptDocumentContentProvider());
-      this.workspaceDir = this.workspaceDir.replace(/\\/g, "/");
-      this._rootDir = vscode.workspace.getConfiguration("GodotTools").get("godotProjectRoot", this.workspaceDir);
-      this._rootDir = this._rootDir.replace("${workspaceRoot}", this.workspaceDir);
-      this.loadWorkspaceSymbols();
-    }
-    
-    // documentation symbol provider
-    this.symbolprovider = new GDScriptSymbolProvider();
-    vscode.languages.registerDocumentSymbolProvider('gdscript', this.symbolprovider);
-    // workspace symbol provider
-    this.workspacesymbolprovider = new GDScriptWorkspaceSymbolProvider();
-    vscode.languages.registerWorkspaceSymbolProvider(this.workspacesymbolprovider);
-    // definition provider
-    vscode.languages.registerDefinitionProvider('gdscript', new GDScriptDefinitionProivder(this._rootDir));
-    // hover provider
-    vscode.languages.registerHoverProvider('gdscript', new GDScriptHoverProvider());
-    // code completion provider
-    if (completionDollar)
-      vscode.languages.registerCompletionItemProvider('gdscript', new GDScriptCompletionItemProvider(), '.', '"', "'", "$");
-    else
-      vscode.languages.registerCompletionItemProvider('gdscript', new GDScriptCompletionItemProvider(), '.', '"', "'");
-    // signature help provider
-    vscode.languages.registerSignatureHelpProvider('gdscript', new GDScriptSignatureHelpProvider(), '(', ',');
-    // Commands
-    this._disposable = vscode.Disposable.from(
-      vscode.commands.registerCommand('godot.updateWorkspaceSymbols', this.loadWorkspaceSymbols.bind(this)),
-      vscode.commands.registerCommand('godot.runWorkspace', () => { this.openWorkspaceWithEditor() }),
-      vscode.commands.registerCommand('godot.openWithEditor', () => { this.openWorkspaceWithEditor("-e") }),
-      vscode.commands.registerCommand('godot.runCurrentScene', this.runCurrentScene.bind(this)),
-    );
-  }
-
-  validate() {
-    const self = this;
-    godotRequest({
-      action: "editor",
-      command: "projectdir"
-    }).then((res: any) => {
-      let path = res.path;
-      if (path && path.length > 0 && path.endsWith("/"))
-        path = path.substring(0, path.length - 1)
-      if (path.toLowerCase() == self.workspaceDir.toLowerCase())
-        vscode.window.showInformationMessage("Connected to the Godot editor server");
-      else {
-        vscode.window.showWarningMessage("The opened project is not the same within the Godot editor");
-      }
-    }).catch(e => {
-      vscode.window.showErrorMessage("Failed connecting to the Godot editor server");
-    });
-  }
-
-  loadAllSymbols(): Promise < any > {
-    const self = this;
-    return new Promise((resolve, reject) => {
-      glob(self.workspaceDir + "/**/*.gd", (err, files) => {
-        if (!err) {
-          const symbols = {};
-          for (let i = 0; i < files.length; i++)
-            symbols[config.normalizePath(files[i])] = config.loadSymbolsFromFile(files[i]);
-          // load autoloads from engin.cfg
-          const engincfg = path.join(self.workspaceDir, this._projectFile);
-          if (fs.existsSync(engincfg) && fs.statSync(engincfg).isFile()) {
-            try {
-              const script = {
-                constants: {},
-                functions: {},
-                variables: {},
-                signals: {},
-                classes: {},
-                base: "Object",
-                native: "Object",
-                constpathes: {},
-                documents: {},
-                constvalues: {}
-              };
-              let content: string = fs.readFileSync(engincfg, 'utf-8');
-              if (content && content.indexOf("[autoload]") != -1) {
-                content = content.substring(content.indexOf("[autoload]") + "[autoload]".length, content.length);
-                content = content.substring(0, content.indexOf("["));
-                const lines = content.split(/\r?\n/);
-                lines.map((l) => {
-                  if (l.indexOf("=") != 0) {
-                    const name = l.substring(0, l.indexOf("="));
-
-                    let gdpath = l.substring(l.indexOf("res://") + "res://".length, l.indexOf(".gd") + ".gd".length);
-                    gdpath = path.join(this._rootDir, gdpath);
-                    let showgdpath = vscode.workspace.asRelativePath(gdpath);
-
-                    let doc = "Autoloaded instance of " + `[${showgdpath}](${vscode.Uri.file(gdpath).toString()})`;
-                    doc = doc.replace(/"/g, " ");
-
-                    script.constants[name] = new vscode.Range(0, 0, 0, 0);
-                    script.constvalues[name] = "autoload";
-                    script.documents[name] = doc;
-                    script.constpathes[name] = gdpath;
-                  }
-                });
-              }
-              symbols["autoload"] = script;
-            } catch (error) {
-              console.error(error);
-            }
-          }
-          resolve(symbols);
-        } else
-          reject(err);
-      });
-    });
-  }
-
-  private loadAllNodesInWorkspace() {
-    glob(this.workspaceDir + "/**/*.tscn", (err, files) => {
-      if (!err) {
-        const symbols = {};
-        for (let i = 0; i < files.length; i++)
-          config.loadScene(files[i]);
-      }
-    });
-  }
-
-  private loadWorkspaceSymbols() {
-    let handle = this.showProgress("Loading symbols");
-    if (vscode.workspace.getConfiguration("GodotTools").get("parseTextScene", false)) {
-      this.loadAllNodesInWorkspace();
-    }
-    this.loadAllSymbols().then(symbols => {
-      handle();
-      vscode.window.setStatusBarMessage("$(check) Workspace symbols", 5000);
-      config.setAllSymbols(symbols);
-    }).catch(e => {
-      handle();
-      vscode.window.setStatusBarMessage("$(x) Workspace symbols", 5000);
-    });
-  }
-
-  private openWorkspaceWithEditor(params = "") {
-    let workspaceValid = false
-    if (this.workspaceDir) {
-    let cfg = path.join(this._rootDir, this._projectFile);
-    console.log(cfg);
-    if (fs.existsSync(cfg) && fs.statSync(cfg).isFile())
-        workspaceValid = true;
-    }
-    if (workspaceValid) {
-      let pathFlag = "-path";
-      if (vscode.workspace.getConfiguration("GodotTools").get("godotVersion", 2.1) >= 3)
-        pathFlag = "--path";
-      this.runEditor(`${pathFlag} "${this._rootDir}" ${params}`);
-    }
-    else
-      vscode.window.showErrorMessage("Current workspace is not a Godot project");
-  }
-
-  private runEditor(params = "") {
-    let editorPath = vscode.workspace.getConfiguration("GodotTools").get("editorPath", "")
-    editorPath = editorPath.replace("${workspaceRoot}", this.workspaceDir);
-    console.log(editorPath);
-    if (!fs.existsSync(editorPath) || !fs.statSync(editorPath).isFile()) {
-      vscode.window.showErrorMessage("Invalid editor path to run the project");
-    } else {
-      let existingTerminal = vscode.window.terminals.find(t => t._name === "GodotTools")
-      if (existingTerminal) {
-        existingTerminal.dispose()
-      }
-      let terminal = vscode.window.createTerminal("GodotTools");
-      editorPath = this.escapeCmd(editorPath);
-      let cmmand = `${editorPath} ${params}`;
-      terminal.sendText(cmmand, true);
-      terminal.show();
-    }
-  }
-
-  private runCurrentScene() {
-    const absFilePath = vscode.window.activeTextEditor.document.uri.fsPath;
-    let scenePath = null
-    if (vscode.window.activeTextEditor) {
-      scenePath = path.relative(this._rootDir, absFilePath);
-      scenePath = scenePath.replace(/\\/g, "/");
-    }
-    // Run scripts directly which is inhired from SceneTree or MainLoop
-    if (scenePath.endsWith(".gd")) {
-      const scriptPath = scenePath;
-      scenePath = config.scriptSceneMap[config.normalizePath(scenePath)];
-      if (!scenePath) {
-        const script = config.loadSymbolsFromFile(absFilePath);
-        if (script) {
-          if(script.native == "SceneTree" || script.native == "MainLoop") {
-            this.runEditor(`-s "${absFilePath}"`);
-            return;
-          }
-        }
-      }
-    }
-    if (scenePath) {
-      if (scenePath.endsWith(".gd"))
-        scenePath = ` -s "res://${scenePath}" `;
-      else
-        scenePath = ` "res://${scenePath}" `;
-      this.openWorkspaceWithEditor(scenePath);
-    } else
-      vscode.window.showErrorMessage("Current document is not a scene file or MainLoop");
-  }
-
-  loadClasses() {
-    let done: boolean = false;
-    if (this.workspaceDir)
-      done = config.loadClasses(path.join(this.workspaceDir, ".vscode", "classes.json"));
-    if (!done)
-      done = config.loadClasses(path.join(this._context.extensionPath, this._biuitinDocFile));
-    if (!done)
-      vscode.window.showErrorMessage("Loading GDScript documentation failed");
-  }
-
-  dispose() {
-    this._disposable.dispose();
-  }
-
-  private showProgress(message: string) {
-    let r_resolve;
-    vscode.window.withProgress({ location: vscode.ProgressLocation.Window}, p => {
-      return new Promise((resolve, reject) => {
-          p.report({message}); 
-          r_resolve = resolve;
-      });
-    });
-    return r_resolve;
-  }
-
-  private escapeCmd(cmd: string) {
-      // Double quote command (should work in at least cmd.exe and bash)
-      let cmdEsc = `"${cmd}"`;
-
-      // Fetch Windows shell type
-      let shell = vscode.workspace.getConfiguration("terminal.integrated.shell").get("windows", "");
-
-      // For powershell we prepend an & to prevent the command being treated as a string
-      if (shell.endsWith("powershell.exe") && process.platform === "win32") {
-          cmdEsc = `&${cmdEsc}`;
-      }
-      return cmdEsc
-  }
-
-};
-
-export default ToolManager;

+ 9 - 0
src/utils.ts

@@ -0,0 +1,9 @@
+import { workspace } from "vscode";
+
+export function get_configuration(name: string, default_value: any = null) {
+	return workspace.getConfiguration("godot_tools").get(name, default_value);
+}
+
+export function is_debug_mode(): boolean {
+	return process.env.VSCODE_DEBUG_MODE === "true";
+}

+ 0 - 83
src/window_watcher.ts

@@ -1,83 +0,0 @@
-import * as vscode from 'vscode';
-import {Disposable, window} from 'vscode';
-import GDScriptDiagnosticSeverity from './gdscript/diagnostic';
-import GDScriptCompleter from './gdscript/completion';
-import config from './config';
-
-interface DocumentFlag {
-  path: string,
-  version: number
-}
-
-class WindowWatcher {
-  
-  private _disposable: Disposable;
-  private _diagnosticSeverity: GDScriptDiagnosticSeverity;
-  private _lastText: DocumentFlag;
-
-  constructor() {
-    let subscriptions: Disposable[] = [];
-    window.onDidChangeTextEditorSelection(this.onDidChangeTextEditorSelection.bind(this), this, subscriptions);
-    window.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor.bind(this), this, subscriptions);
-    window.onDidChangeTextEditorOptions(this.onDidChangeTextEditorOptions.bind(this), this, subscriptions);
-    window.onDidChangeTextEditorViewColumn(this.onDidChangeTextEditorViewColumn.bind(this), this, subscriptions);
-    
-    this._diagnosticSeverity = new GDScriptDiagnosticSeverity();
-    this._disposable = Disposable.from(...subscriptions, this._diagnosticSeverity);
-    this._lastText = {path: "-1", version: -1};
-  }
-
-  dispose() {
-      this._disposable.dispose();
-  }
-
-  /**
-   * Fires when the [active editor](#window.activeTextEditor)
-   * has changed. *Note* that the event also fires when the active editor changes
-   * to `undefined`.
-   */
-  private onDidChangeActiveTextEditor(event: any) {
-    // console.log("[GodotTools]:onDidChangeActiveTextEditor", event);
-    if(window.activeTextEditor != undefined) { 
-      const doc = window.activeTextEditor.document;
-      const script = config.loadSymbolsFromFile(doc.fileName);
-      if (vscode.workspace.getConfiguration("GodotTools").get("enableSyntaxChecking", true)) {
-        this._diagnosticSeverity.validateScript(doc, script).then(()=>{});
-      }
-      this._lastText = {path: doc.fileName, version: doc.version};
-    }
-  }
-
-  /**
-   * Fires when the selection in an editor has changed.
-   */
-  private onDidChangeTextEditorSelection(event: any) {
-    // console.log("[GodotTools]:onDidChangeTextEditorSelection");
-    const doc = window.activeTextEditor.document;
-    const curText: DocumentFlag= {path: doc.fileName, version: doc.version};
-    // Check content changed
-    if(this._lastText.path != curText.path || this._lastText.version != curText.version) {
-      const script = config.loadSymbolsFromFile(doc.fileName);
-      if (vscode.workspace.getConfiguration("GodotTools").get("enableSyntaxChecking", true)) {
-        this._diagnosticSeverity.validateScript(doc, script).then(()=>{});
-      }
-      this._lastText = curText;
-    }
-  }
-
-  /**
-   * Fires when the options of an editor have changed.
-   */
-  private onDidChangeTextEditorOptions(event: any) {
-    // console.log("[GodotTools]:onDidChangeTextEditorOptions", event);
-  }
-
-  /**
-   * Fires when the view column of an editor has changed.
-   */
-  private onDidChangeTextEditorViewColumn(event: any) {
-    // console.log("[GodotTools]:onDidChangeTextEditorViewColumn", event);
-  }
-}
-
-export default WindowWatcher;

+ 15 - 17
tsconfig.json

@@ -1,18 +1,16 @@
 {
-    "compilerOptions": {
-        "module": "commonjs",
-        "target": "es6",
-        "outDir": "out",
-        "lib": [
-            "es6"
-        ],
-        "sourceMap": true,
-        "rootDir": "."
-    },
-    "exclude": [
-        "node_modules",
-        ".vscode-test",
-        "src/gdscript/server",
-        "server"
-    ]
-}
+	"compilerOptions": {
+		"module": "commonjs",
+		"target": "es6",
+		"outDir": "out",
+		"lib": [
+			"es6"
+		],
+		"sourceMap": true,
+		"rootDir": "src",
+		"strict": false
+	},
+	"exclude": [
+		"node_modules",
+	]
+}

+ 14 - 0
tslint.json

@@ -0,0 +1,14 @@
+{
+	"rules": {
+		"no-string-throw": true,
+		"no-unused-expression": true,
+		"no-duplicate-variable": false,
+		"curly": true,
+		"class-name": true,
+		"semicolon": [
+			true,
+			"always"
+		],
+	},
+	"defaultSeverity": "warning"
+}

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů