├── .gitignore ├── icon.png ├── types └── crlf-helper │ └── index.d.ts ├── .vscodeignore ├── tsconfig.json ├── .vscode ├── settings.json ├── launch.json └── tasks.json ├── src ├── server │ ├── types.ts │ ├── Proxy.ts │ ├── Config.ts │ ├── server.ts │ ├── AstParser.ts │ └── Builder.ts └── client │ └── extension.ts ├── CHANGELOG.md ├── LICENSE ├── README.md ├── package.json ├── files ├── snippets.json └── lua5_1.lua └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules 3 | .history -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leitwolf/vscode-QuickXDev/HEAD/icon.png -------------------------------------------------------------------------------- /types/crlf-helper/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'crlf-helper' { 2 | export function setLineEnding(content: string, endingType: string): string; 3 | } 4 | 5 | -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | .vscode-test/** 3 | out/test/** 4 | test/** 5 | src/** 6 | **/*.map 7 | .gitignore 8 | tsconfig.json 9 | vsc-extension-quickstart.md 10 | yarn.lock 11 | types/** 12 | .histroy/** -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "removeComments": true, 6 | "outDir": "out", 7 | "lib": [ 8 | "es6" 9 | ], 10 | "sourceMap": true, 11 | "rootDir": ".", 12 | "typeRoots": [ 13 | ".types", 14 | "./node_modules/@types" 15 | ] 16 | }, 17 | "exclude": [ 18 | "node_modules", 19 | "typings" 20 | ] 21 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "**/.git": true, 5 | "**/.svn": true, 6 | "**/.hg": true, 7 | "**/CVS": true, 8 | "**/.DS_Store": true, 9 | "out": false, 10 | ".history": true 11 | }, 12 | "search.exclude": { 13 | "out": true // set this to false to include "out" folder in search results 14 | }, 15 | "explorerExclude.backup": null 16 | } -------------------------------------------------------------------------------- /src/server/types.ts: -------------------------------------------------------------------------------- 1 | import { CompletionItem } from "vscode-languageserver"; 2 | 3 | // 基础项 4 | export interface DocItem { 5 | name: string; 6 | completion: CompletionItem; 7 | items: DocItem[]; 8 | // 已在别的地方定义,一般是一个lua文件中引用别的地方的全局变量 9 | virtual:boolean; 10 | // 引用,c=cc Node=c.Node => c.refer=cc Node.refer=cc.Node 11 | // 得到一个DocItem时,要先检测这一项 12 | refer:DocItem; 13 | // 所在位置,lua只有两项[line,col],c++有三项[line,col,src] 14 | loc: any[]; 15 | } 16 | // 一个文档 17 | export interface FileDoc { 18 | uri: string; 19 | // 全局变量 20 | globals: DocItem[]; 21 | // 局部变量 22 | locals: DocItem[]; 23 | } 24 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that compiles the extension and then opens it inside a new window 2 | { 3 | "version": "0.1.0", 4 | "configurations": [ 5 | { 6 | "name": "Launch Extension", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], 11 | "stopOnEntry": false, 12 | "sourceMaps": true, 13 | "outFiles": [ "${workspaceRoot}/out/src/**/*.js" ], 14 | "preLaunchTask": "npm" 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [1.0.0] - 2020-08-28 2 | test 3 | 4 | # [0.1.0] - 2020-02-211 5 | - 部分适配Cocos2d-Lua-Community 4.0版本,目前新版的LuaGameRunner可用。 6 | - 绑定 F6 键到 "在Player中运行" 7 | 8 | # [0.0.7] - 2018-12-25 9 | - 修复一个可能引发crash的bug。 10 | 11 | # [0.0.6] - 2018-11-20 12 | - 添加for语句提示 13 | 14 | # [0.0.5] - 2018-11-03 15 | - 默认都是quick项目 16 | 17 | # [0.0.4] - 2018-09-07 18 | - 修复mac中"转到定义"c++部分路径错误的bug 19 | - 初始化项目时,让左下角的提示更明显一些 20 | 21 | # [0.0.3] - 2018-09-03 22 | - 修复"转到定义"的bug 23 | - 增加了几个功能的动图 24 | 25 | # [0.0.2] - 2018-09-02 26 | - 修复运行Player错误的问题 27 | 28 | # [0.0.1] - 2018-09-01 29 | vscode第一版,适配 Quick-Cocos2dx-Community 3.7.2版 30 | - cocos2dx c++端的代码提示 31 | - quick lua端的代码提示 32 | - lua 5.1系统代码提示 33 | - if,while,function等snippets 34 | - 转到定义功能 35 | - 在Player中运行 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 lonewolf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | // Available variables which can be used inside of strings. 2 | // ${workspaceRoot}: the root folder of the team 3 | // ${file}: the current opened file 4 | // ${fileBasename}: the current opened file's basename 5 | // ${fileDirname}: the current opened file's dirname 6 | // ${fileExtname}: the current opened file's extension 7 | // ${cwd}: the current working directory of the spawned process 8 | 9 | // A task runner that calls a custom npm script that compiles the extension. 10 | { 11 | "version": "0.1.0", 12 | 13 | 14 | // we want to run npm 15 | "command": "npm", 16 | 17 | // the command is a shell script 18 | "isShellCommand": true, 19 | 20 | // show the output window only if unrecognized errors occur. 21 | "showOutput": "silent", 22 | 23 | // we run the custom script "compile" as defined in package.json 24 | "args": ["run", "compile", "--loglevel", "silent"], 25 | 26 | // The tsc compiler is started in watching mode 27 | "isBackground": true, 28 | 29 | // use the standard tsc in watch mode problem matcher to find compile problems in the output. 30 | "problemMatcher": "$tsc-watch" 31 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vscode版QuickXDev 2 | 强大的quick-cocos2dx开发工具,目前适配 Quick-Cocos2dx-Community 3.7.x版及部分适配Cocos2d-Lua-Community 4.0版。 3 | 4 | QuickXDev交流群:625657444,欢迎进群提问,讨论问题。 5 | 6 | ## Cocos2d-Lua-Community 4.0 版本说明 7 | - 目前已部分适配该版本,其中LuaGameRunner(旧版中的Player)可用。这一特性的用法跟之前版本一样,都是右键 -> 在Player中运行,插件会根据引擎的目录结构自行判断是哪个版本。 8 | - 因为该版本已没有环境变量,也就无法从系统中获取引擎的根目录,所以要想使用4.0版本,用户必须主动设置插件quickxdev.root,即引擎的根目录。 9 | - 如果想同时开发3.7.x与4.0版本的项目,则在项目的工作目录中设置quickxdev.root,这样不同项目的设置就分隔开了,互不影响。 10 | 11 | ## 安装 12 | 在vscode扩展商店中搜索"QuickXDev"即可找到。 13 | 14 | ## 特性 15 | - cocos2dx c++端的代码提示 16 | - quick lua端的代码提示 17 | - lua 5.1系统代码提示 18 | - if,while,function等snippets 19 | - 转到定义功能 20 | - 在Player中运行功能 (F6) 21 | 22 | ## 配置 23 | - quickxdev.root quick引擎的目录,如果是正常安装quick(执行了setup_win.bat/setup_mac.sh),插件则自动获取该变量。如果是4.0版本则需要手动设置。 24 | 25 | ## 打开Player 26 | 项目中任意lua文件右键 -> 在Player中运行,或者按F6,即可运行该项目。 27 | 28 | ## 第三方库 29 | 本插件中使用 [luaparse](https://github.com/oxyc/luaparse) 作为lua代码解析库,在此向原作者表示感谢! 30 | 31 | ## 几个功能的gif 32 | - 自动完成 33 | ![completion](https://user-images.githubusercontent.com/1720546/44968155-c290b580-af78-11e8-8d58-4e5d43a31cd7.gif) 34 | - 转到定义 35 | ![godef](https://user-images.githubusercontent.com/1720546/44968156-c58ba600-af78-11e8-8a98-3f73c5a51b34.gif) 36 | - 运行Player 37 | ![runplayer](https://user-images.githubusercontent.com/1720546/44968157-c6243c80-af78-11e8-8490-920d2db74789.gif) 38 | -------------------------------------------------------------------------------- /src/server/Proxy.ts: -------------------------------------------------------------------------------- 1 | import { IConnection, MessageType, ShowMessageParams } from "vscode-languageserver"; 2 | import URI from "vscode-uri"; 3 | 4 | 5 | /** 6 | * 服务端功能集合,主要提供一些基础的功能 7 | */ 8 | class Proxy0 { 9 | 10 | private _connetion: IConnection; 11 | private _statusBar; 12 | 13 | constructor() { 14 | } 15 | 16 | /** 17 | * 初始化 18 | */ 19 | public init(conn: IConnection): void { 20 | this._connetion = conn; 21 | } 22 | 23 | // ===========显示消息========== 24 | /** 25 | * 显示消息 26 | * @param type 消息类型 27 | * @param message 消息实体 28 | */ 29 | public showMessage(type: MessageType, message: string) { 30 | let messageParams = { 31 | type: type, 32 | message: message 33 | }; 34 | this._connetion.sendNotification("window/showMessage", messageParams); 35 | } 36 | /** 37 | * 显示Info消息 38 | * @param message 消息 39 | */ 40 | public showMessageInfo(message: string) { 41 | this.showMessage(MessageType.Info, message); 42 | } 43 | /** 44 | * Log消息 45 | * @param message 消息 46 | */ 47 | public showMessageLog(message: string) { 48 | this.showMessage(MessageType.Log, message); 49 | } 50 | /** 51 | * 显示Warning消息 52 | * @param message 消息 53 | */ 54 | public showMessageWarning(message: string) { 55 | // this._connetion.window.showWarningMessage(message); 56 | this.showMessage(MessageType.Warning, message); 57 | } 58 | /** 59 | * 显示Error消息 60 | * @param message 消息 61 | */ 62 | public showMessageError(message: string) { 63 | this.showMessage(MessageType.Error, message); 64 | } 65 | // =================== 66 | 67 | // =========任务栏========== 68 | /** 69 | * 显示任务栏信息 70 | * @param text 71 | * @param color 72 | */ 73 | public showStatusBar(text: string, color: string = ""): void { 74 | this._connetion.sendRequest("showStatusBar", { text: text, color: color }); 75 | } 76 | /** 77 | * 隐藏任务栏 78 | */ 79 | public hideStatusBar(): void { 80 | this._connetion.sendRequest("hideStatusBar"); 81 | } 82 | // =================== 83 | 84 | /** 85 | * 发送信息到客户端,没有返回值 86 | * @param method 87 | * @param params 88 | */ 89 | public sendRequest(method: string, params: any): void { 90 | this._connetion.sendRequest(method, params); 91 | } 92 | 93 | /** 94 | * 与客户端的连接 95 | */ 96 | public get connection(): IConnection { 97 | return this._connetion; 98 | } 99 | } 100 | /** 101 | * 服务端代码,基础功能集合 102 | */ 103 | export const ServerProxy = new Proxy0(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vscode-quickxdev", 3 | "displayName": "QuickXDev", 4 | "description": "Quick-Cocos2dx develop for vscode", 5 | "version": "0.1.0", 6 | "publisher": "lonewolf", 7 | "engines": { 8 | "vscode": "^1.25.0" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/leitwolf/vscode-QuickXDev.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/leitwolf/vscode-QuickXDev/issues" 16 | }, 17 | "homepage": "https://github.com/leitwolf/vscode-QuickXDev/blob/master/README.md", 18 | "keywords": [ 19 | "lua", 20 | "quick cocos2dx" 21 | ], 22 | "icon": "icon.png", 23 | "categories": [ 24 | "Programming Languages", 25 | "Snippets" 26 | ], 27 | "activationEvents": [ 28 | "onLanguage:lua" 29 | ], 30 | "main": "./out/src/client/extension", 31 | "contributes": { 32 | "configuration": { 33 | "type": "Object", 34 | "title": "QuickXDev 配置", 35 | "properties": { 36 | "quickxdev.root": { 37 | "scope": "resource", 38 | "type": "string", 39 | "default": null, 40 | "description": "Quick-Cocos2dx 根目录,通常会自动获取" 41 | } 42 | } 43 | }, 44 | "menus": { 45 | "editor/context": [ 46 | { 47 | "command": "quickxdev.runPlayer", 48 | "when": "resourceLangId == lua", 49 | "group": "navigation" 50 | } 51 | ] 52 | }, 53 | "commands": [ 54 | { 55 | "title": "在 Player 中运行", 56 | "command": "quickxdev.runPlayer" 57 | } 58 | ], 59 | "snippets": [ 60 | { 61 | "language": "lua", 62 | "path": "./files/snippets.json" 63 | } 64 | ], 65 | "keybindings": [ 66 | { 67 | "command": "quickxdev.runPlayer", 68 | "key": "f6" 69 | } 70 | ] 71 | }, 72 | "scripts": { 73 | "vscode:prepublish": "tsc -p ./", 74 | "compile": "tsc -watch -p ./", 75 | "postinstall": "node ./node_modules/vscode/bin/install" 76 | }, 77 | "dependencies": { 78 | "luaparse": "^0.2.1", 79 | "rd": "^2.0.1", 80 | "crlf-helper": "^0.1.0", 81 | "vscode-languageclient": "^5.0.1", 82 | "vscode-languageserver": "^5.0.3" 83 | }, 84 | "devDependencies": { 85 | "@types/luaparse": "^0.0.29", 86 | "@types/mocha": "^5.2.5", 87 | "@types/node": "^10.7.1", 88 | "mocha": "^5.2.0", 89 | "typescript": "^3.0.1", 90 | "vscode": "^1.1.21" 91 | } 92 | } -------------------------------------------------------------------------------- /files/snippets.json: -------------------------------------------------------------------------------- 1 | { 2 | "comment": { 3 | "prefix": "comment", 4 | "body": [ 5 | "--[[", 6 | "\t$0", 7 | "--]]" 8 | ] 9 | }, 10 | "do_end": { 11 | "prefix": "do", 12 | "body": [ 13 | "do", 14 | "\t${0:--todo}", 15 | "end" 16 | ] 17 | }, 18 | "if": { 19 | "prefix": "if", 20 | "body": [ 21 | "if ${1:conditions} then", 22 | "\t${0:--todo}", 23 | "end" 24 | ] 25 | }, 26 | "if_else": { 27 | "prefix": "ife", 28 | "body": [ 29 | "if ${1:conditions} then", 30 | "\t${2:--todo}", 31 | "else", 32 | "\t${0:--todo}", 33 | "end" 34 | ] 35 | }, 36 | "if_elseif": { 37 | "prefix": "ifel", 38 | "body": [ 39 | "if ${1:conditions} then", 40 | "\t${2:--todo}", 41 | "elseif ${3:conditions} then", 42 | "\t${0:--todo}", 43 | "end" 44 | ] 45 | }, 46 | "if_elseif_else": { 47 | "prefix": "ifee", 48 | "body": [ 49 | "if ${1:conditions} then", 50 | "\t${2:--todo}", 51 | "elseif ${3:conditions} then", 52 | "\t${4:--todo}", 53 | "else", 54 | "\t${0:--todo}", 55 | "end" 56 | ] 57 | }, 58 | "else": { 59 | "prefix": "else", 60 | "body": [ 61 | "else", 62 | "\t${0:--todo}" 63 | ] 64 | }, 65 | "elseif": { 66 | "prefix": "elseif", 67 | "body": [ 68 | "elseif ${1:conditions} then", 69 | "\t${0:--todo}" 70 | ] 71 | }, 72 | "repeat_until": { 73 | "prefix": "repeat", 74 | "body": [ 75 | "repeat", 76 | "\t${1:--todo}", 77 | "until ${0:true}" 78 | ] 79 | }, 80 | "while": { 81 | "prefix": "while", 82 | "body": [ 83 | "while ${1:true} do", 84 | "\t${0:--todo}", 85 | "end" 86 | ] 87 | }, 88 | "function": { 89 | "prefix": "func", 90 | "body": [ 91 | "function ${1:name}(${2})", 92 | "\t$0", 93 | "end" 94 | ] 95 | }, 96 | "local": { 97 | "prefix": "local", 98 | "body": [ 99 | "local ${1:a} = $0" 100 | ] 101 | }, 102 | "for": { 103 | "prefix": "for", 104 | "body": [ 105 | "for ${1:i}=${2:1},${3:10} do", 106 | "\t${0:print(i)}", 107 | "end" 108 | ] 109 | }, 110 | "fori": { 111 | "prefix": "fori", 112 | "body": [ 113 | "for ${1:i},${2:v} in ipairs(${3:table}) do", 114 | "\t${0:print(i,v)}", 115 | "end" 116 | ] 117 | }, 118 | "forp": { 119 | "prefix": "forp", 120 | "body": [ 121 | "for ${1:k},${2:v} in pairs(${3:table}) do", 122 | "\t${0:print(k,v)}", 123 | "end" 124 | ] 125 | } 126 | } -------------------------------------------------------------------------------- /src/server/Config.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | import { URL } from 'url'; 4 | import { ServerProxy } from './Proxy'; 5 | import { Builder } from './Builder'; 6 | import URI from 'vscode-uri'; 7 | 8 | /** 9 | * 插件配置,定义于package.json文件中 10 | */ 11 | interface Settings { 12 | root: string; 13 | } 14 | // 当前插件配置选项,要跟client发送过来的一样 15 | interface MySettings { 16 | quickxdev: Settings; 17 | } 18 | 19 | class Config0 { 20 | 21 | // 设置 22 | private _settings: Settings; 23 | // 插件所在目录uri 24 | private _root: string; 25 | // 项目根目录uri 26 | private _workspaceRoot: string; 27 | // Quick目录uri 28 | private _quickRoot: string; 29 | // 是否是Quick-cocos2dx项目 30 | private _isQuickX: boolean = false; 31 | 32 | // 是否已初始化过Setting 33 | private _initSettinged: boolean = false; 34 | 35 | constructor() { 36 | } 37 | /** 38 | * 初始化 39 | */ 40 | public initWorkspace(workspaceRoot: string) { 41 | this._workspaceRoot = workspaceRoot; 42 | // let cocos2d = workspaceRoot + "/src/cocos/cocos2d"; 43 | // this._isQuickX = fs.existsSync(new URL(cocos2d)); 44 | // 默认都是quick项目 45 | this._isQuickX = true; 46 | 47 | // 插件所在目录 48 | let root = path.join(__dirname, "../../../"); 49 | root = path.resolve(root); 50 | this._root = URI.file(root).toString(); 51 | } 52 | /** 53 | * 初始化配置 54 | */ 55 | public changeSettings(settings: any) { 56 | let s = settings; 57 | this._settings = s.quickxdev; 58 | if (!this._settings.root) { 59 | // 没有设置root,则从系统环境变量中获取 60 | this._settings.root = process.env.QUICK_V3_ROOT; 61 | } 62 | // 转换为uri 63 | this._quickRoot = null; 64 | if (this._settings.root) { 65 | this._quickRoot = URI.file(this._settings.root).toString(); 66 | } 67 | console.log("QuickX root:", this._quickRoot); 68 | 69 | // 通知前端quick目录 70 | ServerProxy.sendRequest("quickRoot", this.quickRoot); 71 | 72 | if (this._isQuickX && !this.quickRoot) { 73 | ServerProxy.showMessageWarning("还没有设置Quick引擎目录!"); 74 | } 75 | 76 | if (!this._initSettinged) { 77 | // console.log("init setting"); 78 | // 开始初始化项目 79 | Builder.initWorkspace(); 80 | this._initSettinged = true; 81 | } 82 | } 83 | /** 84 | * 配置选项 85 | */ 86 | public get settings(): Settings { 87 | return this._settings; 88 | } 89 | /** 90 | * Quick-Cocos2dx 根目录 91 | */ 92 | public get quickRoot(): string { 93 | return this._quickRoot; 94 | } 95 | /** 96 | * 项目目录 97 | */ 98 | public get workspaceRoot(): string { 99 | return this._workspaceRoot; 100 | } 101 | /** 102 | * 插件目录 103 | */ 104 | public get root(): string { 105 | return this._root; 106 | } 107 | /** 108 | * 是否是quick-cocos2dx项目 109 | */ 110 | public get isQuickX(): boolean { 111 | return this._isQuickX; 112 | } 113 | } 114 | /** 115 | * 配置文件管理 116 | */ 117 | export const Config = new Config0(); -------------------------------------------------------------------------------- /src/server/server.ts: -------------------------------------------------------------------------------- 1 | /* -------------------------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Licensed under the MIT License. See License.txt in the project root for license information. 4 | * ------------------------------------------------------------------------------------------ */ 5 | 'use strict'; 6 | import { CompletionItem, createConnection, IConnection, InitializeResult, ProposedFeatures, TextDocumentPositionParams, TextDocumentSyncKind, DidChangeTextDocumentParams, Definition, InitializeParams, DidChangeConfigurationParams, DidChangeWatchedFilesParams, Location } from 'vscode-languageserver'; 7 | import { Builder } from './Builder'; 8 | import { Config } from './Config'; 9 | import { ServerProxy } from './Proxy'; 10 | import URI from 'vscode-uri'; 11 | 12 | 13 | // 建立连接 14 | let connection: IConnection = createConnection(ProposedFeatures.all); 15 | 16 | // 初始化 17 | connection.onInitialize((params: InitializeParams): InitializeResult => { 18 | console.log("Init project: ", params.rootUri); 19 | Config.initWorkspace(params.rootUri); 20 | ServerProxy.init(connection); 21 | return { 22 | // 返回服务端提供的功能 23 | capabilities: { 24 | // 文档内容同步类型,无|全部|增量 25 | textDocumentSync: TextDocumentSyncKind.Full, 26 | // 告诉客户端支持代码自动完成 27 | completionProvider: { 28 | resolveProvider: true, 29 | triggerCharacters: [".", ":"] 30 | }, 31 | definitionProvider: true 32 | } 33 | } 34 | }); 35 | 36 | // 回应客户端信息 37 | connection.onRequest("isQuickX", () => { 38 | return Config.isQuickX; 39 | }); 40 | 41 | /** 42 | * 配置初始化或内容改变时 43 | */ 44 | connection.onDidChangeConfiguration((params: DidChangeConfigurationParams) => { 45 | Config.changeSettings(params.settings); 46 | }); 47 | connection.onDidChangeWatchedFiles((params: DidChangeWatchedFilesParams) => { 48 | // Monitored files have change in VSCode 49 | console.log('We recevied an file change event'); 50 | }); 51 | 52 | /** 53 | * 自动完成 54 | */ 55 | connection.onCompletion(async (params: TextDocumentPositionParams): Promise => { 56 | let uri = params.textDocument.uri; 57 | let line = params.position.line; 58 | let character = params.position.character; 59 | let p = { filepath: URI.parse(uri).fsPath, line: line }; 60 | let lineData = await ServerProxy.connection.sendRequest("getDocLine", p); 61 | if (lineData.length < character) { 62 | return []; 63 | } 64 | let prevContent = lineData.substring(0, character); 65 | return Builder.handleComplete(uri, prevContent); 66 | }); 67 | 68 | // 当上下选中自动完成选项时要显示的更多信息 69 | connection.onCompletionResolve((item: CompletionItem): CompletionItem => { 70 | return item; 71 | }); 72 | 73 | /** 74 | * 内容改变时 75 | */ 76 | connection.onDidChangeTextDocument((params: DidChangeTextDocumentParams) => { 77 | // console.log("content",params.contentChanges.length); 78 | if (params.contentChanges.length > 0) { 79 | for (let i = 0; i < params.contentChanges.length; i++) { 80 | const data = params.contentChanges[i].text; 81 | Builder.parseCode(params.textDocument.uri, data); 82 | } 83 | } 84 | }); 85 | 86 | /** 87 | * 转到定义 88 | */ 89 | connection.onDefinition(async (params: TextDocumentPositionParams): Promise => { 90 | let uri = params.textDocument.uri; 91 | let line = params.position.line; 92 | let character = params.position.character; 93 | 94 | // console.log(line); 95 | let p = { filepath: URI.parse(uri).fsPath, line: line }; 96 | let lineData = await ServerProxy.connection.sendRequest("getDocLine", p); 97 | return Builder.handleDefinition(uri, lineData, character); 98 | }) 99 | 100 | 101 | // 开始监听 102 | connection.listen(); 103 | -------------------------------------------------------------------------------- /files/lua5_1.lua: -------------------------------------------------------------------------------- 1 | _G = "" 2 | _VERSION = "" 3 | function assert(v,message) 4 | end 5 | function collectgarbage(opt,arg) 6 | end 7 | function dofile(filename) 8 | end 9 | function error(message,level) 10 | end 11 | function getfenv(f) 12 | end 13 | function getmetatable(object) 14 | end 15 | function ipairs(t) 16 | end 17 | function load(func,chunkname) 18 | end 19 | function loadfile(filename) 20 | end 21 | function loadstring(string,chunkname) 22 | end 23 | function module(name,...) 24 | end 25 | function next(tablename,index) 26 | end 27 | function pairs(t) 28 | end 29 | function pcall(f,arg1,...) 30 | end 31 | function print(...) 32 | end 33 | function rawequal(v1,v2) 34 | end 35 | function rawget(tablename,index) 36 | end 37 | function rawset(tablename,index,value) 38 | end 39 | function require(modname) 40 | end 41 | function select(index,...) 42 | end 43 | function setfenv(f,tablename) 44 | end 45 | function setmetatable(tablename,metatable) 46 | end 47 | function tonumber(e,base) 48 | end 49 | function tostring(e) 50 | end 51 | function type(v) 52 | end 53 | function unpack(list,i,j) 54 | end 55 | function xpcall(f,err) 56 | end 57 | 58 | coroutine = {} 59 | function coroutine.create(f) 60 | end 61 | function coroutine.resume(co,val1,...) 62 | end 63 | function coroutine.running() 64 | end 65 | function coroutine.status(co) 66 | end 67 | function coroutine.wrap(f) 68 | end 69 | function coroutine.yield(...) 70 | end 71 | 72 | debug = {} 73 | function debug.debug() 74 | end 75 | function debug.getfenv(o) 76 | end 77 | function debug.gethook(thread) 78 | end 79 | function debug.getinfo(thread,funcname,what) 80 | end 81 | function debug.getlocal(thread,level,localname) 82 | end 83 | function debug.getmetatable(object) 84 | end 85 | function debug.getregistry() 86 | end 87 | function debug.getupvalue(func,up) 88 | end 89 | function debug.setfenv(object,tablename) 90 | end 91 | function debug.sethook(thread,hook,mask,count) 92 | end 93 | function debug.setlocal(thread,level,localname,value) 94 | end 95 | function debug.setmetatable(object,tablename) 96 | end 97 | function debug.setupvalue(func,up,value) 98 | end 99 | function debug.traceback(thread,message,level) 100 | end 101 | 102 | io = {} 103 | function io.close(file) 104 | end 105 | function io.flush() 106 | end 107 | function io.input(file) 108 | end 109 | function io.lines(filename) 110 | end 111 | function io.open(filename,mode) 112 | end 113 | function io.output(file) 114 | end 115 | function io.popen(prog,mode) 116 | end 117 | function io.read(...) 118 | end 119 | function io.tmpfile() 120 | end 121 | function io.type(obj) 122 | end 123 | function io.write(...) 124 | end 125 | 126 | math = {} 127 | function math.abs(x) 128 | end 129 | function math.acos(x) 130 | end 131 | function math.asin(x) 132 | end 133 | function math.atan(x) 134 | end 135 | function math.atan2(y,x) 136 | end 137 | function math.ceil(x) 138 | end 139 | function math.cos(x) 140 | end 141 | function math.cosh(x) 142 | end 143 | function math.deg(x) 144 | end 145 | function math.exp(x) 146 | end 147 | function math.floor(x) 148 | end 149 | function math.fmod(x,y) 150 | end 151 | function math.frexp(x) 152 | end 153 | math.huge = "" 154 | function math.ldexp(m,e) 155 | end 156 | function math.log(x) 157 | end 158 | function math.log10(x) 159 | end 160 | function math.max(x,...) 161 | end 162 | function math.min(x,...) 163 | end 164 | function math.modf(x) 165 | end 166 | math.pi = "" 167 | function math.pow(x,y) 168 | end 169 | function math.rad(x) 170 | end 171 | function math.random(m,n) 172 | end 173 | function math.randomseed(x) 174 | end 175 | function math.sin(x) 176 | end 177 | function math.sinh(x) 178 | end 179 | function math.sqrt(x) 180 | end 181 | function math.tan(x) 182 | end 183 | function math.tanh(x) 184 | end 185 | 186 | os = {} 187 | function os.clock() 188 | end 189 | function os.date(format,time) 190 | end 191 | function os.difftime(t2,t1) 192 | end 193 | function os.execute(command) 194 | end 195 | function os.exit(code) 196 | end 197 | function os.getenv(varname) 198 | end 199 | function os.remove(filename) 200 | end 201 | function os.rename(oldname,newname) 202 | end 203 | function os.setlocale(locale,category) 204 | end 205 | function os.time(table) 206 | end 207 | function os.tmpname() 208 | end 209 | 210 | package = {} 211 | package.cpath = "" 212 | package.loaded = "" 213 | package.loaders = "" 214 | function package.loadlib(libname,funcname) 215 | end 216 | package.path = "" 217 | package.preload = "" 218 | function package.seeall(module) 219 | end 220 | 221 | string = {} 222 | function string.byte(s,i,j) 223 | end 224 | function string.char(...) 225 | end 226 | function string.dump(funcname) 227 | end 228 | function string.find(s,pattern,init,plain) 229 | end 230 | function string.format(formatstring,...) 231 | end 232 | function string.gmatch(s,pattern) 233 | end 234 | function string.gsub(s,pattern,repl,n) 235 | end 236 | function string.len(s) 237 | end 238 | function string.lower(s) 239 | end 240 | function string.match(s,pattern,init) 241 | end 242 | function string.rep(s,n) 243 | end 244 | function string.reverse(s) 245 | end 246 | function string.sub(s,i,j) 247 | end 248 | function string.upper(s) 249 | end 250 | 251 | table = {} 252 | function table.concat(tablename,sep,i,j) 253 | end 254 | function table.insert(tablename,pos,value) 255 | end 256 | function table.maxn(tablename) 257 | end 258 | function table.remove(tablename,pos) 259 | end 260 | function table.sort(tablename,comp) 261 | end -------------------------------------------------------------------------------- /src/client/extension.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import * as path from "path"; 3 | import { ServerOptions, TransportKind, LanguageClientOptions, LanguageClient } from "vscode-languageclient"; 4 | import { OutputChannel, WorkspaceFolder, TextDocument, workspace, ExtensionContext, window, StatusBarItem, StatusBarAlignment, env, commands, Uri } from "vscode"; 5 | import { existsSync, readFileSync } from "fs"; 6 | import { URL } from "url"; 7 | import { execFile, ChildProcess } from "child_process"; 8 | import URI from "vscode-uri"; 9 | 10 | /** 11 | * 每个工作空间一个后端服务 12 | */ 13 | 14 | // 客户端列表,以路径为key 15 | let clients: Map = new Map(); 16 | 17 | // 服务器模块文件路径 18 | let serverModule: string; 19 | // 当前调试端口,每加一个则+1 20 | let debugPort = 6009; 21 | let outputChannel: OutputChannel; 22 | 23 | // 任务栏信息 24 | let statusBars: StatusBarItem[] = []; 25 | // Quick目录 26 | let quickRoot: string; 27 | let playerProcess: ChildProcess; 28 | 29 | /** 30 | * 建立一个客户端 31 | * @param folder 32 | */ 33 | function createClient(folder: WorkspaceFolder) { 34 | // 语言服务器调试参数 35 | debugPort++; 36 | let debugOptions = { execArgv: ["--nolazy", "--inspect=" + debugPort] }; 37 | let serverOptions: ServerOptions = { 38 | run: { module: serverModule, transport: TransportKind.ipc }, 39 | debug: { module: serverModule, transport: TransportKind.ipc, options: debugOptions } 40 | } 41 | let clientOptions: LanguageClientOptions = { 42 | // 语言服务器输出channel,console.log(...) 43 | outputChannel: outputChannel, 44 | // 服务端要处理的语言类型 45 | documentSelector: [{ scheme: 'file', language: 'lua' }], 46 | workspaceFolder: folder, 47 | // 需要同步的内容 48 | synchronize: { 49 | // 同步设置选项到语言服务器 50 | configurationSection: 'quickxdev', 51 | // Notify the server about file changes to '.clientrc files contain in the workspace 52 | fileEvents: workspace.createFileSystemWatcher('**/.clientrc') 53 | }, 54 | } 55 | let client = new LanguageClient('QuickXDev', 'QuickXDevServer', serverOptions, clientOptions); 56 | // 定义自定义事件 57 | client.onReady().then(() => { 58 | // 显示/隐藏任务栏 59 | client.onRequest("showStatusBar", (message: { text: string, color: string }) => { 60 | let statusBar = window.createStatusBarItem(StatusBarAlignment.Left, 0); 61 | if (message.color != "") { 62 | statusBar.color = message.color; 63 | } 64 | statusBar.text = message.text; 65 | statusBar.show(); 66 | statusBars.push(statusBar); 67 | }); 68 | client.onRequest("hideStatusBar", () => { 69 | for (let i = 0; i < statusBars.length; i++) { 70 | statusBars[i].dispose(); 71 | } 72 | statusBars = []; 73 | }); 74 | // 后端发送Quick目录 75 | client.onRequest("quickRoot", (text: string) => { 76 | quickRoot = text; 77 | }); 78 | // 后端请求当前文档指定行数信息,当前文档的uri与参数相符 79 | client.onRequest("getDocLine", (params: { filepath: string, line: number }): string => { 80 | let activeDoc = window.activeTextEditor.document; 81 | if (activeDoc.fileName != params.filepath || activeDoc.lineCount < params.line) { 82 | return ""; 83 | } 84 | return activeDoc.lineAt(params.line).text; 85 | }); 86 | }); 87 | client.start(); 88 | clients.set(folder.uri.toString(), client); 89 | } 90 | 91 | /** 92 | * 打开一个文档时调用 93 | * @param document 94 | */ 95 | function didOpenTextDocument(document: TextDocument) { 96 | // 只处理lua文件 97 | if (document.languageId !== "lua" || document.uri.scheme !== "file") { 98 | return; 99 | } 100 | let folder = workspace.getWorkspaceFolder(document.uri); 101 | if (!folder) { 102 | return; 103 | } 104 | if (!clients.get(folder.uri.toString())) { 105 | // 还没有建立该工作目录对应的客户端 106 | createClient(folder); 107 | } 108 | } 109 | 110 | /** 111 | * 运行Player 112 | */ 113 | function runPlayer() { 114 | // 先关闭之前的 115 | if (playerProcess) { 116 | playerProcess.kill(); 117 | playerProcess = null; 118 | } 119 | if (!quickRoot) { 120 | window.showErrorMessage("没有设置QuickX目录"); 121 | return; 122 | } 123 | 124 | let activeFile = window.activeTextEditor.document.fileName; 125 | let workDirUri = workspace.getWorkspaceFolder(URI.file(activeFile)).uri; 126 | let client = clients.get(workDirUri.toString()); 127 | // 不在当前打开的项目中 128 | if (!client) { 129 | return; 130 | } 131 | 132 | // 检测是否是4.0版本 133 | let isVersion4 = false; 134 | let gameRunnerFolder = quickRoot + "/tools/runner/"; 135 | if (existsSync(new URL(gameRunnerFolder))) { 136 | isVersion4 = true; 137 | } 138 | 139 | client.sendRequest("isQuickX").then((isQuickX: boolean) => { 140 | if (!isQuickX) { 141 | let msg = "非 quick 项目下不能运行 Player!"; 142 | if (isVersion4) { 143 | msg = "非 quick 项目下不能运行 LuaGameRunner!"; 144 | } 145 | window.showErrorMessage(msg); 146 | return; 147 | } 148 | if (!isVersion4) { 149 | doRunPlayer(workDirUri); 150 | } 151 | else { 152 | doRunGameRunner(workDirUri); 153 | } 154 | }); 155 | } 156 | 157 | // 运行3.7版的Player 158 | function doRunPlayer(workDirUri: Uri) { 159 | let playerPath = quickRoot + "/quick/player/"; 160 | if (process.platform == "win32") { 161 | playerPath += "win32/player3.exe"; 162 | } 163 | else if (process.platform == "darwin") { 164 | playerPath += "player3.app/Contents/MacOS/player3"; 165 | } 166 | else { 167 | window.showErrorMessage("抱歉,不支持当前制作系统!"); 168 | return; 169 | } 170 | 171 | if (!existsSync(new URL(playerPath))) { 172 | window.showErrorMessage("Player不存在"); 173 | return; 174 | } 175 | 176 | let playerFsPath = URI.parse(playerPath).fsPath; 177 | // 加上参数 178 | let args: string[] = []; 179 | args.push("-workdir"); 180 | args.push(workDirUri.fsPath); 181 | let configPath = workDirUri.toString() + "/src/config.lua"; 182 | let config = getQuickConfig(configPath); 183 | if (config) { 184 | let debug = config.debug; 185 | if (debug == 0) { 186 | args.push("-disable-write-debug-log"); 187 | args.push("-disable-console"); 188 | } 189 | else if (debug == 1) { 190 | args.push("-disable-write-debug-log"); 191 | args.push("-console"); 192 | } 193 | else if (debug == 2) { 194 | args.push("-write-debug-log"); 195 | args.push("-console"); 196 | } 197 | args.push("-size"); 198 | args.push(config.width + "x" + config.height); 199 | } 200 | 201 | // 运行 202 | playerProcess = execFile(playerFsPath, args); 203 | 204 | } 205 | 206 | // 运行4.0版的LuaGameRunner 207 | function doRunGameRunner(workDirUri: Uri) { 208 | let runnerPath = quickRoot + "/tools/runner/bin/"; 209 | if (process.platform == "win32") { 210 | runnerPath += "win32/LuaGameRunner.exe"; 211 | } 212 | else if (process.platform == "darwin") { 213 | runnerPath += "LuaGameRunner.app/Contents/MacOS/LuaGameRunner"; 214 | } 215 | else { 216 | window.showErrorMessage("抱歉,不支持当前制作系统!"); 217 | return; 218 | } 219 | 220 | if (!existsSync(new URL(runnerPath))) { 221 | window.showErrorMessage("LuaGameRunner不存在"); 222 | return; 223 | } 224 | 225 | let runnerFsPath = URI.parse(runnerPath).fsPath; 226 | // 加上参数 227 | let args: string[] = []; 228 | args.push("--gamedir"); 229 | args.push(workDirUri.fsPath); 230 | args.push("--writedir"); 231 | args.push(workDirUri.fsPath); 232 | let configPath = workDirUri.toString() + "/src/config.lua"; 233 | let config = getQuickConfig(configPath); 234 | if (config) { 235 | let debug = config.debug; 236 | if (debug > 0) { 237 | args.push("--log"); 238 | } 239 | args.push("--width"); 240 | args.push(config.width + ""); 241 | args.push("--height"); 242 | args.push(config.height + ""); 243 | } 244 | 245 | // 运行 246 | playerProcess = execFile(runnerFsPath, args); 247 | } 248 | 249 | // 获取Quick项目配置信息 250 | function getQuickConfig(configPath: string): { debug: number, width: number, height: number } { 251 | if (!existsSync(new URL(configPath))) { 252 | return null; 253 | } 254 | let re = { debug: 1, width: 640, height: 480 }; 255 | let data: string = readFileSync(new URL(configPath), "utf-8"); 256 | let lines = data.split("\n"); 257 | for (let i = 0; i < lines.length; i++) { 258 | const line = lines[i]; 259 | if (line.startsWith("--")) { 260 | continue; 261 | } 262 | let arr = line.split("="); 263 | if (arr.length == 2) { 264 | let key = arr[0].trim(); 265 | let value = arr[1].trim(); 266 | if (key == "DEBUG") { 267 | re.debug = parseInt(value); 268 | } else if (key == "CONFIG_SCREEN_WIDTH") { 269 | re.width = parseInt(value); 270 | } else if (key == "CONFIG_SCREEN_HEIGHT") { 271 | re.height = parseInt(value); 272 | } 273 | } 274 | } 275 | return re; 276 | } 277 | 278 | // 激活插件 279 | export function activate(context: ExtensionContext) { 280 | serverModule = context.asAbsolutePath(path.join("out", "src", "server", "server.js")); 281 | outputChannel = window.createOutputChannel("QuickXDev"); 282 | 283 | workspace.onDidOpenTextDocument(didOpenTextDocument); 284 | // 已打开文件的调用 285 | workspace.textDocuments.forEach(didOpenTextDocument); 286 | // 关闭时删除对应的客户端 287 | workspace.onDidChangeWorkspaceFolders((event) => { 288 | for (const folder of event.removed) { 289 | let client = clients.get(folder.uri.toString()); 290 | if (client) { 291 | clients.delete(folder.uri.toString()); 292 | client.stop(); 293 | } 294 | } 295 | }); 296 | 297 | // 注册命令 298 | let openPlayerCmd = commands.registerCommand("quickxdev.runPlayer", runPlayer); 299 | context.subscriptions.push(openPlayerCmd); 300 | } 301 | 302 | // 插件停止激活时调用 303 | export function deactivate(): Thenable { 304 | let promises: Thenable[] = []; 305 | for (const client of clients.values()) { 306 | promises.push(client.stop()); 307 | } 308 | return Promise.all(promises).then(() => undefined); 309 | } -------------------------------------------------------------------------------- /src/server/AstParser.ts: -------------------------------------------------------------------------------- 1 | import { DocItem, FileDoc } from "./types"; 2 | import { CompletionItem, CompletionItemKind } from "vscode-languageserver"; 3 | 4 | const enum AstType { 5 | // 最终单词 6 | Identifier = "Identifier", 7 | // cc.aa.bb 8 | MemberExpression = "MemberExpression", 9 | VarargLiteral = "VarargLiteral" 10 | } 11 | /** 12 | * 工具类 13 | * 分析ast结构,生成文档类 14 | */ 15 | class AstParser0 { 16 | 17 | // 全局和局部 18 | private _globals: DocItem[]; 19 | private _locals: DocItem[]; 20 | // 别称的情况,如local a=aa a.bb=1,那么aa.bb=1,最后的时候再汇总 21 | // name:[aa,bb] alias:a isLocal是指name的情况 22 | private _alias: { name: string[], alias: string, isLocal: boolean }[] = []; 23 | 24 | constructor() { 25 | } 26 | /** 27 | * 沿路径查找,如没有则建立一个项 28 | * @param names 29 | * @param list 30 | * @param isNewVirtual 是否是新建的是virtual 31 | */ 32 | private findOrCreateItem(names: string[], list: DocItem[], isNewVirtual: boolean = false): DocItem { 33 | if (names.length == 0) { 34 | return null; 35 | } 36 | // 最后的DocItem,生成或已存在的 37 | let lastItem: DocItem; 38 | for (let i = 0; i < names.length; i++) { 39 | const name = names[i]; 40 | let has = false; 41 | // console.log(list); 42 | for (let j = 0; j < list.length; j++) { 43 | let item = list[j]; 44 | if (item.name == name) { 45 | if (item.refer) { 46 | item = item.refer; 47 | } 48 | if (!item.items) { 49 | item.items = []; 50 | } 51 | list = item.items; 52 | lastItem = item; 53 | has = true; 54 | break; 55 | } 56 | } 57 | if (!has) { 58 | let completion = {}; 59 | completion.label = name; 60 | completion.kind = CompletionItemKind.Variable; 61 | let newItem = {}; 62 | newItem.name = name; 63 | newItem.completion = completion; 64 | newItem.items = []; 65 | if (isNewVirtual) { 66 | newItem.virtual = true; 67 | } 68 | list.push(newItem); 69 | list = newItem.items; 70 | lastItem = newItem; 71 | } 72 | } 73 | return lastItem; 74 | } 75 | private getTopList(isLocal: boolean): DocItem[] { 76 | if (isLocal) { 77 | return this._locals; 78 | } 79 | return this._globals; 80 | } 81 | /** 82 | * 加入到一个父项,连同加入到其refer中 83 | * @param item 84 | * @param base 85 | */ 86 | private add2DocItem(item: DocItem, base: DocItem): void { 87 | if (!base) { 88 | return; 89 | } 90 | if (base.refer) { 91 | base = base.refer; 92 | } 93 | this.add2List(item, base.items); 94 | } 95 | /** 96 | * 加入到列表中,已有则替换 97 | * @param item 98 | * @param list 99 | */ 100 | private add2List(item: DocItem, list: DocItem[]): void { 101 | for (let i = 0; i < list.length; i++) { 102 | const element = list[i]; 103 | if (element.name == item.name) { 104 | element.completion = item.completion; 105 | element.refer = item.refer; 106 | return; 107 | } 108 | } 109 | // 新加入 110 | list.push(item); 111 | } 112 | /** 113 | * 赋值或定义 114 | * cc.VAR or local abc=1 115 | * 116 | * @param data 117 | */ 118 | private genVar(data: Object, refer: { names: string[], isLocal: boolean }): void { 119 | let identifier = this.getChain(data, []); 120 | var names = identifier.names; 121 | if (names.length == 0) { 122 | // 错误的名称 123 | return; 124 | } 125 | // console.log("var", identifier); 126 | // 之后names就是父类的路径了 127 | let name = names.pop(); 128 | 129 | let completion = {}; 130 | completion.label = name; 131 | completion.kind = CompletionItemKind.Variable; 132 | completion.detail = name; 133 | 134 | let docItem = {}; 135 | docItem.name = name; 136 | docItem.loc = this.p_loc(data["loc"]); 137 | docItem.completion = completion; 138 | // 找出refer 139 | if (refer.names.length == 1 && names.length == 1 && refer.names[0] == name) { 140 | // 引用其它地方 cc = cc or {} 141 | docItem.virtual = true; 142 | } 143 | else { 144 | docItem.refer = this.findOrCreateItem(refer.names, this.getTopList(refer.isLocal), true); 145 | } 146 | 147 | // 查找docItem的父类 148 | let list = this.getTopList(identifier.isLocal); 149 | let base = this.findOrCreateItem(names, list, true); 150 | if (base) { 151 | docItem.completion.detail = "(" + base.name + ") " + docItem.completion.detail; 152 | this.add2DocItem(docItem, base); 153 | } 154 | else { 155 | this.add2List(docItem, list); 156 | } 157 | } 158 | /** 159 | * 生成函数的自动完成 160 | * @param data 161 | */ 162 | private genFunc(data: Object): void { 163 | let identifier = this.getChain(data["identifier"], []); 164 | var names = identifier.names; 165 | if (names.length == 0) { 166 | // 错误的名称 167 | return; 168 | } 169 | let name = names.pop(); 170 | let params = this.getFuncParams(data["parameters"]); 171 | let params2 = ""; 172 | let params3 = ""; 173 | for (let i = 0; i < params.length; i++) { 174 | const p = params[i]; 175 | if (i != 0) { 176 | params2 += ", "; 177 | params3 += ", "; 178 | } 179 | params2 += "${" + (i + 1) + ":" + p + "}"; 180 | params3 += p; 181 | } 182 | 183 | let completion = {}; 184 | completion.label = name; 185 | completion.kind = CompletionItemKind.Function; 186 | completion.insertTextFormat = 2; 187 | completion.insertText = name + "(" + params2 + ")"; 188 | completion.detail = name + "(" + params3 + ")"; 189 | 190 | let docItem = {}; 191 | docItem.name = name; 192 | docItem.loc = this.p_loc(data["loc"]); 193 | docItem.completion = completion; 194 | 195 | // 查找docItem的父类 196 | let list = this.getTopList(identifier.isLocal); 197 | let base = this.findOrCreateItem(names, list, true); 198 | if (base) { 199 | docItem.completion.detail = "(" + base.name + ") " + docItem.completion.detail; 200 | this.add2DocItem(docItem, base); 201 | } 202 | else { 203 | this.add2List(docItem, list); 204 | } 205 | 206 | // 处理方法体 207 | this.parseList(data["body"]); 208 | } 209 | /** 210 | * 获取链式的变量,如aa.bb:dd 211 | * @param data 212 | */ 213 | private getChain(data: Object, names: string[]): { names: string[], isLocal: boolean } { 214 | var reObj = { names: [], isLocal: true }; 215 | // 有可能是匿名函数 216 | if (!data) { 217 | return reObj; 218 | } 219 | let type: string = data["type"]; 220 | if (type == AstType.Identifier) { 221 | names.unshift(data["name"]); 222 | reObj.names = names; 223 | reObj.isLocal = data["isLocal"]; 224 | } 225 | else if (type == AstType.MemberExpression) { 226 | names.unshift(data["identifier"]["name"]); 227 | return this.getChain(data["base"], names); 228 | } 229 | return reObj; 230 | } 231 | /** 232 | * 函数参数列表 233 | * @param params 234 | */ 235 | private getFuncParams(params: Object[]): string[] { 236 | let ps: string[] = []; 237 | for (let i = 0; i < params.length; i++) { 238 | const p = params[i]; 239 | let type: string = p["type"]; 240 | if (type == "Identifier") { 241 | ps.push(p["name"]); 242 | } 243 | else if (type == AstType.VarargLiteral) { 244 | ps.push("..."); 245 | } 246 | } 247 | return ps; 248 | } 249 | /** 250 | * 检测是全局变量 251 | * cc.VAR=1 如果cc是全局的则cc.VAR是全局的 252 | * @param data 253 | */ 254 | private checkGlobalAssign(data: Object): boolean { 255 | let type: string = data["type"]; 256 | let isLocal: boolean = data["isLocal"]; 257 | if (type == AstType.Identifier) { 258 | return !isLocal; 259 | } 260 | else if (type == AstType.MemberExpression) { 261 | return this.checkGlobalAssign(data["base"]); 262 | } 263 | return false; 264 | } 265 | /** 266 | * 解析一个文档,返回解析结果 267 | * @param data 268 | */ 269 | public parseDoc(data: Object): FileDoc { 270 | this._globals = []; 271 | this._locals = []; 272 | this._alias = []; 273 | this.parseNode(data); 274 | let file = {}; 275 | file.globals = this._globals; 276 | file.locals = this._locals; 277 | return file; 278 | } 279 | /** 280 | * 检测节点,根据节点类型选择相应的方法 281 | * @param data 282 | */ 283 | public parseNode(data: Object): void { 284 | let type: string = data["type"]; 285 | // 找到相应的方法 286 | if (this["p_" + type] != null) { 287 | this["p_" + type](data); 288 | } 289 | else { 290 | // 没有相应的方法 291 | console.log("Unkown type: " + type); 292 | // console.log(data); 293 | } 294 | } 295 | private parseList(list: Object[]): void { 296 | for (let i = 0; i < list.length; i++) { 297 | this.parseNode(list[i]); 298 | } 299 | } 300 | private p_loc(data: Object): number[] { 301 | return [data["start"]["line"], data["start"]["column"]]; 302 | } 303 | private p_Identifier(data: Object): void { 304 | // let obj = this.init(data, EntryType.Identifier); 305 | // obj["name"] = data["name"]; 306 | // obj["isLocal"] = data["isLocal"] ? data["isLocal"] : true; 307 | // return obj; 308 | } 309 | private p_NumericLiteral(data: Object): void { 310 | } 311 | private p_StringLiteral(data: Object): void { 312 | } 313 | private p_NilLiteral(data: Object): void { 314 | } 315 | private p_BooleanLiteral(data: Object): void { 316 | } 317 | private p_VarargLiteral(data: Object): void { 318 | } 319 | private p_UnaryExpression(data: Object): void { 320 | this.parseNode(data["argument"]); 321 | } 322 | private p_BinaryExpression(data: Object): void { 323 | this.parseNode(data["left"]); 324 | this.parseNode(data["right"]); 325 | } 326 | private p_LogicalExpression(data: Object): void { 327 | this.p_BinaryExpression(data); 328 | } 329 | private p_CallExpression(data: Object): void { 330 | this.parseNode(data["base"]); 331 | this.parseList(data["arguments"]); 332 | } 333 | private p_MemberExpression(data: Object): void { 334 | } 335 | private p_StringCallExpression(data: Object): void { 336 | } 337 | private p_TableCallExpression(data: Object): void { 338 | } 339 | private p_TableConstructorExpression(data: Object): void { 340 | } 341 | private p_TableValue(data: Object): void { 342 | } 343 | private p_TableKeyString(data: Object): void { 344 | } 345 | private p_TableKey(data: Object): void { 346 | } 347 | private p_IndexExpression(data: Object): void { 348 | } 349 | private p_LocalStatement(data: Object): void { 350 | if (this.isFuncDeclare(data)) { 351 | return; 352 | } 353 | let vars: Object[] = data["variables"]; 354 | let inits: Object[] = data["init"]; 355 | // 普通变量 356 | for (let i = 0; i < vars.length; i++) { 357 | let var1 = vars[i]; 358 | var refer: { names: string[], isLocal: boolean } = { names: [], isLocal: true }; 359 | if (i < inits.length) { 360 | // 引用的情况 361 | let value = inits[i]; 362 | if (var1["type"] == AstType.Identifier) { 363 | if (value["type"] == AstType.Identifier || value["type"] == AstType.MemberExpression) { 364 | refer = this.getChain(value, []); 365 | } 366 | else if (value["type"] == "LogicalExpression") { 367 | // cc = cc or {} 368 | refer = this.getChain(value["left"], []); 369 | } 370 | else if (value["type"] == "CallExpression" && value["base"]["name"] == "require") { 371 | // 声明模块 device = require(cc.PACKAGE_NAME .. ".device") 372 | continue 373 | } 374 | // console.log(refer); 375 | } 376 | } 377 | this.genVar(var1, refer); 378 | } 379 | } 380 | // 是否是函数定义 381 | private isFuncDeclare(data): boolean { 382 | let vars: Object[] = data["variables"]; 383 | let inits: Object[] = data["init"]; 384 | if (vars.length == 1 && inits.length == 1 && inits[0]["type"] == "FunctionDeclaration") { 385 | // 函数定义在后面的情况,local func=function ... end 386 | let funcObj = inits[0]; 387 | funcObj["identifier"] = vars[0]; 388 | this.genFunc(funcObj); 389 | return true; 390 | } 391 | return false; 392 | } 393 | private p_AssignmentStatement(data: Object): void { 394 | this.p_LocalStatement(data); 395 | // if (this.isFuncDeclare(data)) { 396 | // return; 397 | // } 398 | // // 如果var是global或者value是变量或函数的时候记录 399 | // let vars: Object[] = data["variables"]; 400 | // let inits: Object[] = data["init"]; 401 | // for (let i = 0; i < vars.length; i++) { 402 | // let var1 = vars[i]; 403 | // let isLocal: boolean = var1["isLocal"]; 404 | // var refer: { names: string[], isLocal: boolean } = { names: [], isLocal: true }; 405 | // if (i < inits.length) { 406 | // // 引用的情况 407 | // let value = inits[i]; 408 | // if (var1["type"] == AstType.Identifier && (value["type"] == AstType.Identifier || value["type"] == AstType.MemberExpression)) { 409 | // refer = this.getChain(value, []); 410 | // } 411 | // } 412 | // if (!isLocal || refer.names.length > 0) { 413 | // this.genVar(var1, refer); 414 | // } 415 | // } 416 | } 417 | private p_IfStatement(data: Object): void { 418 | this.parseList(data["clauses"]); 419 | } 420 | private p_IfClause(data: Object): void { 421 | this.parseList(data["body"]); 422 | } 423 | private p_ElseifClause(data: Object): void { 424 | this.parseList(data["body"]); 425 | } 426 | private p_ElseClause(data: Object): void { 427 | this.parseList(data["body"]); 428 | } 429 | private p_DoStatement(data: Object): void { 430 | this.parseList(data["body"]); 431 | } 432 | private p_WhileStatement(data: Object): void { 433 | this.parseList(data["body"]); 434 | } 435 | private p_RepeatStatement(data: Object): void { 436 | this.parseList(data["body"]); 437 | } 438 | private p_ForNumericStatement(data: Object): void { 439 | this.parseList(data["body"]); 440 | } 441 | private p_ForGenericStatement(data: Object): void { 442 | this.parseList(data["body"]); 443 | } 444 | private p_BreakStatement(data: Object): void { 445 | } 446 | private p_ReturnStatement(data: Object): void { 447 | } 448 | private p_CallStatement(data: Object): void { 449 | return this.parseNode(data["expression"]); 450 | } 451 | private p_FunctionDeclaration(data: Object): void { 452 | this.genFunc(data); 453 | this.parseList(data["body"]); 454 | } 455 | private p_Comment(data: Object): void { 456 | } 457 | private p_Chunk(data: Object): void { 458 | this.parseList(data["body"]); 459 | // 最后一个是return语句则是一个模块 460 | let list: Object[] = data["body"]; 461 | if (list.length > 0) { 462 | let last = list[list.length - 1]; 463 | let type: string = last["type"]; 464 | if (type == "ReturnStatement") { 465 | let vars: Object[] = last["arguments"]; 466 | if (vars.length == 1 && vars[0]["type"] == AstType.Identifier) { 467 | let name = vars[0]["name"]; 468 | // 找出local中对应的模块 469 | for (let i = 0; i < this._locals.length; i++) { 470 | const item = this._locals[i]; 471 | if (item.name == name) { 472 | item.completion.kind = CompletionItemKind.Module; 473 | this._locals.splice(i, 1); 474 | // 放入到globals中 475 | this._globals.push(item); 476 | break; 477 | } 478 | } 479 | } 480 | } 481 | } 482 | } 483 | } 484 | /** 485 | * 解析文档 486 | * @param data 487 | */ 488 | export function parseDoc(data: Object): FileDoc { 489 | let parser = new AstParser0(); 490 | return parser.parseDoc(data); 491 | } 492 | -------------------------------------------------------------------------------- /src/server/Builder.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as luaparse from "luaparse"; 3 | import * as rd from 'rd'; 4 | import { URL } from 'url'; 5 | import { CompletionItem, CompletionItemKind, InsertTextFormat, Definition, Location } from "vscode-languageserver"; 6 | import URI from 'vscode-uri'; 7 | import { parseDoc } from './AstParser'; 8 | import { Config } from './Config'; 9 | import { DocItem, FileDoc } from './types'; 10 | import { ServerProxy } from './Proxy'; 11 | import { setLineEnding } from 'crlf-helper'; 12 | 13 | // luaparse解析参数 14 | interface ParseOption { 15 | comments: boolean; 16 | scope: boolean; 17 | locations: boolean; 18 | ranges: boolean; 19 | luaVersion: string; 20 | } 21 | 22 | /** 23 | * 生成自动列表 24 | */ 25 | class Builder0 { 26 | 27 | // 解析参数 28 | private _option: ParseOption; 29 | 30 | // c++预加载列表 31 | private _cppList: DocItem[]; 32 | // 关键字列表 33 | private _keyList: CompletionItem[]; 34 | // 文档列表,包括系统函数 35 | private _fileList: FileDoc[]; 36 | 37 | // 客户端最后发送的文字,自动完成时不用重复加载 38 | private _lastText: string = ""; 39 | 40 | // 是否已初始化了,解析完项目内所有的lua文件 41 | private _inited: boolean = false; 42 | private _total: number; 43 | private _count: number; 44 | 45 | constructor() { 46 | this._option = {}; 47 | this._option.comments = false; 48 | this._option.scope = true; 49 | this._option.locations = true; 50 | this._option.ranges = false; 51 | this._option.luaVersion = '5.1'; 52 | 53 | this._cppList = []; 54 | this._fileList = []; 55 | this._keyList = []; 56 | this.initKeys(); 57 | } 58 | /** 59 | * 关键字 60 | */ 61 | private initKeys(): void { 62 | var strs = ["and", "break", "if", "else", "elseif", "end", "false", "function", "local", "in", "nil", "not", "or", "return", "then", "true", "while"]; 63 | for (let i = 0; i < strs.length; i++) { 64 | const str = strs[i]; 65 | let item = {}; 66 | item.label = str; 67 | item.kind = CompletionItemKind.Keyword; 68 | this._keyList.push(item); 69 | } 70 | } 71 | /** 72 | * 初始化整个工作区,解析所有的lua代码文件 73 | */ 74 | public initWorkspace(): void { 75 | // 在任务栏显示提示 76 | let statusText = "初始化 Quickx 项目..."; 77 | if (!Config.isQuickX) { 78 | statusText = "初始化 lua 项目..."; 79 | } 80 | ServerProxy.showStatusBar("$(zap)", "#00ff00"); 81 | ServerProxy.showStatusBar(statusText); 82 | 83 | // 延时 84 | setTimeout(() => { 85 | this.initWorkspace2(); 86 | }, 150); 87 | } 88 | private initWorkspace2(): void { 89 | if (Config.isQuickX) { 90 | this.initCpp(); 91 | } 92 | this.initLuaSystem(); 93 | 94 | let rootPath = URI.parse(Config.workspaceRoot).fsPath; 95 | rd.readFileFilter(rootPath, /\.lua$/, (err: Error, paths: string[]) => { 96 | this._total = paths.length; 97 | this._count = 0; 98 | for (let i = 0; i < paths.length; i++) { 99 | const p = paths[i]; 100 | fs.readFile(p, "utf-8", (err1: NodeJS.ErrnoException, data: string) => { 101 | // console.log("read", p); 102 | this._count++; 103 | let fileuri = URI.file(p).toString(); 104 | this.parse(fileuri, data); 105 | if (this._count >= this._total) { 106 | this._inited = true; 107 | ServerProxy.hideStatusBar(); 108 | // console.log("inited"); 109 | // this.initedTest(); 110 | } 111 | }) 112 | } 113 | }) 114 | } 115 | /** 116 | * 初始化lua系统变量及函数 117 | */ 118 | private initLuaSystem(): void { 119 | let path = Config.root + "/files/lua5_1.lua"; 120 | path = URI.parse(path).fsPath; 121 | fs.readFile(path, "utf-8", (err1: NodeJS.ErrnoException, data: string) => { 122 | // console.log("read", path); 123 | let fileuri = URI.file(path).toString(); 124 | this.parse(fileuri, data); 125 | 126 | // 第一个为模块 127 | for (let i = 0; i < this._fileList.length; i++) { 128 | const file = this._fileList[i]; 129 | if (file.uri == fileuri) { 130 | for (let j = 0; j < file.globals.length; j++) { 131 | const docItem = file.globals[j]; 132 | if (docItem.items && docItem.items.length > 0) { 133 | docItem.completion.kind = CompletionItemKind.Module; 134 | } 135 | } 136 | } 137 | } 138 | }); 139 | } 140 | private initedTest(): void { 141 | for (let i = 0; i < this._fileList.length; i++) { 142 | const fileDoc = this._fileList[i]; 143 | for (let j = 0; j < fileDoc.globals.length; j++) { 144 | const item = fileDoc.globals[j]; 145 | if (item.name == "CONFIG_SCREEN_HEIGHT") { 146 | console.log(item.virtual, fileDoc.uri, item.loc); 147 | } 148 | } 149 | } 150 | } 151 | /** 152 | * 建立cpp列表 153 | */ 154 | private initCpp(): void { 155 | this._cppList = []; 156 | let cppPath = Config.root + "/files/cpp.json"; 157 | let data = fs.readFileSync(new URL(cppPath), "utf-8"); 158 | let jsonData = JSON.parse(data); 159 | for (let i = 0; i < jsonData.length; i++) { 160 | const moduleItem = jsonData[i]; 161 | let loc = this.getCppLoc(moduleItem["loc"]); 162 | let moduleDocItem = this.createVarDocItem(moduleItem["name"], null, true, loc); 163 | moduleDocItem.items = []; 164 | this._cppList.push(moduleDocItem); 165 | let classes: Object[] = moduleItem["classes"]; 166 | if (classes && classes.length > 0) { 167 | for (let j = 0; j < classes.length; j++) { 168 | const classItem = classes[j]; 169 | let loc = this.getCppLoc(classItem["loc"]); 170 | let classDocItem = this.createVarDocItem(classItem["name"], moduleDocItem.name, false, loc); 171 | classDocItem.items = []; 172 | moduleDocItem.items.push(classDocItem); 173 | let funcs: Object[] = classItem["functions"]; 174 | if (funcs && funcs.length > 0) { 175 | for (let k = 0; k < funcs.length; k++) { 176 | const funcItem = funcs[k]; 177 | let loc = this.getCppLoc(funcItem["loc"]); 178 | let funcDocItem = this.createFuncDocItem(funcItem["name"], classDocItem.name, funcItem["params"], loc); 179 | classDocItem.items.push(funcDocItem); 180 | } 181 | } 182 | } 183 | } 184 | } 185 | } 186 | private createVarDocItem(name: string, base: string, isModule: boolean, loc: any[]): DocItem { 187 | var docItem = {}; 188 | docItem.name = name; 189 | let completion = {}; 190 | completion.label = name; 191 | if (isModule) { 192 | completion.kind = CompletionItemKind.Module; 193 | } 194 | else { 195 | completion.kind = CompletionItemKind.Variable; 196 | } 197 | var detail = name; 198 | if (base) { 199 | detail = "(" + base + ") " + detail; 200 | } 201 | completion.detail = detail; 202 | docItem.completion = completion; 203 | docItem.loc = loc; 204 | return docItem; 205 | } 206 | private createFuncDocItem(name: string, base: string, params: string[], loc: any[]): DocItem { 207 | let params2 = ""; 208 | let params3 = ""; 209 | for (let i = 0; i < params.length; i++) { 210 | const p = params[i]; 211 | if (i != 0) { 212 | params2 += ", "; 213 | params3 += ", "; 214 | } 215 | params2 += "${" + (i + 1) + ":" + p + "}"; 216 | params3 += p; 217 | } 218 | let completion = {}; 219 | completion.label = name; 220 | completion.kind = CompletionItemKind.Function; 221 | completion.insertTextFormat = InsertTextFormat.Snippet; 222 | completion.insertText = name + "(" + params2 + ")"; 223 | let detail = name + "(" + params3 + ")"; 224 | if (base) { 225 | detail = "(" + base + ") " + detail; 226 | } 227 | completion.detail = detail; 228 | 229 | let funcDocItem = {}; 230 | funcDocItem.name = name; 231 | funcDocItem.loc = loc; 232 | funcDocItem.completion = completion; 233 | 234 | return funcDocItem; 235 | } 236 | /** 237 | * 生成cpp类的Loc 238 | * @param data 239 | */ 240 | private getCppLoc(data: Object): any[] { 241 | let loc = []; 242 | if (data && Config.quickRoot) { 243 | let root = Config.quickRoot; 244 | if (!root.endsWith("/")) { 245 | root += "/"; 246 | } 247 | loc = [data["line"], data["char"], root + data["src"]]; 248 | } 249 | return loc; 250 | } 251 | /** 252 | * 真正解析 253 | * @param uri 254 | * @param data 255 | */ 256 | private parse(uri: string, data: string) { 257 | if (!data) { 258 | return; 259 | } 260 | // 要转成crlf结尾,不然解析的时候行号不对 261 | data = setLineEnding(data, "CRLF"); 262 | try { 263 | let ast = luaparse.parse(data, this._option); 264 | 265 | // test 266 | // let p = new URL(Config.workspaceRoot + "/p.json"); 267 | // fs.writeFileSync(p, JSON.stringify(ast)); 268 | 269 | let file = parseDoc(ast); 270 | file.uri = uri; 271 | 272 | // if (uri.includes("display")) { 273 | // console.log(file); 274 | // } 275 | 276 | // test 277 | // p = new URL(Config.workspaceRoot + "/a2.json"); 278 | // fs.writeFileSync(p, JSON.stringify(file)); 279 | 280 | // 先删除之前的 281 | for (let i = 0; i < this._fileList.length; i++) { 282 | const f = this._fileList[i]; 283 | if (f.uri == uri) { 284 | this._fileList.splice(i, 1); 285 | break; 286 | } 287 | } 288 | this._fileList.push(file); 289 | } catch (error) { 290 | // console.log(error); 291 | } 292 | } 293 | /** 294 | * 解析代码内容,一般是内容改变时 295 | */ 296 | public parseCode(uri: string, code: string) { 297 | if (this._inited) { 298 | this._lastText = code; 299 | this.parse(uri, code); 300 | } 301 | } 302 | /** 303 | * 处理转到定义 304 | * @param lineData 305 | * @param character 306 | */ 307 | public handleDefinition(uri: string, lineData: string, character: number): Definition { 308 | let prevContent = lineData.substring(0, character); 309 | let afterContent = lineData.substring(character); 310 | let arr = prevContent.split(/[^\w+|\.|\:]/); 311 | let prev = arr[arr.length - 1]; 312 | if (prev.startsWith(".") || prev.startsWith(":")) { 313 | // :align的情况 314 | prev = prev.substr(1); 315 | } 316 | // 后面的不需要.或:之后的字符 317 | arr = afterContent.split(/[^\w+]/); 318 | let after = arr[0]; 319 | let str = prev + after; 320 | // console.log("def", str, prev, after); 321 | 322 | let paths = str.split(/\.|\:/); 323 | if (paths.length == 0) { 324 | return []; 325 | } 326 | let locations: Location[] = []; 327 | this.findLocation(paths, this._cppList, null, locations); 328 | for (let i = 0; i < this._fileList.length; i++) { 329 | const file = this._fileList[i]; 330 | if (file.uri == uri) { 331 | this.findLocation(paths, file.locals, file.uri, locations); 332 | } 333 | this.findLocation(paths, file.globals, file.uri, locations); 334 | } 335 | if (locations.length == 0) { 336 | // 如果找不到,则只检测最后一项 337 | let name = paths[paths.length - 1]; 338 | this.addAllDefinition(name, this._cppList, null, locations); 339 | for (let i = 0; i < this._fileList.length; i++) { 340 | const file = this._fileList[i]; 341 | if (file.uri == uri) { 342 | this.addAllDefinition(name, file.locals, file.uri, locations); 343 | } 344 | this.addAllDefinition(name, file.globals, file.uri, locations); 345 | } 346 | } 347 | // console.log("---"); 348 | return locations; 349 | } 350 | /** 351 | * 找到定义,并加入列表 352 | * @param paths 353 | * @param list 354 | * @param locations 355 | */ 356 | private findLocation(paths: string[], list: DocItem[], fileUri: string, locations: Location[]): void { 357 | let item = this.findDocItem(paths, list); 358 | if (item) { 359 | this.add2Definition(item, fileUri, locations); 360 | } 361 | } 362 | /** 363 | * 添加所有附合的到定义列表,当路径只有一个的时候 364 | * @param name 365 | * @param fileUri 366 | * @param locations 367 | */ 368 | private addAllDefinition(name: string, list: DocItem[], fileUri: string, locations: Location[]): void { 369 | for (let i = 0; i < list.length; i++) { 370 | const item1 = list[i]; 371 | if (item1.name == name) { 372 | this.add2Definition(item1, fileUri, locations); 373 | } 374 | if (item1.items && item1.items.length > 0) { 375 | this.addAllDefinition(name, item1.items, fileUri, locations); 376 | } 377 | } 378 | } 379 | /** 380 | * 添加DocItem到定义列表中 381 | * @param item 382 | * @param fileUri 383 | * @param locations 384 | */ 385 | private add2Definition(item: DocItem, fileUri: string, locations: Location[]): void { 386 | // console.log("find", item); 387 | if (!item.loc) { 388 | return; 389 | } 390 | // 路径在loc中 391 | if (!fileUri && item.loc.length == 3) { 392 | fileUri = item.loc[2]; 393 | } 394 | if (!fileUri || item.loc.length < 2) { 395 | return; 396 | } 397 | let line: number = item.loc[0] - 1; 398 | let character: number = item.loc[1]; 399 | // console.log("loc", line, character, fileUri); 400 | let location = Location.create(fileUri, { 401 | start: { line: line, character: character }, 402 | end: { line: line, character: character } 403 | }); 404 | locations.push(location); 405 | } 406 | 407 | /** 408 | * 处理生成自动完成列表 409 | * @param uri 410 | * @param prevContent 光标之前的字符串 411 | */ 412 | public handleComplete(uri: string, prevContent: string): CompletionItem[] { 413 | prevContent.trim(); 414 | let arr = prevContent.split(/[^\w+|\.|\:]/); 415 | prevContent = arr[arr.length - 1]; 416 | // console.log("prevContent", prevContent); 417 | // 是否含有单词字符,没有单词字符则不是 418 | let index = prevContent.search(/\w+/); 419 | if (index >= 0) { 420 | return this.handleCompleteText(uri, prevContent); 421 | } 422 | return []; 423 | } 424 | /** 425 | * 对一段文字进行补全 426 | * @param uri 427 | * @param str 428 | */ 429 | private handleCompleteText(uri: string, str: string): CompletionItem[] { 430 | let completions: CompletionItem[] = []; 431 | // 对str进行分析,取父路径的列表,如aa.bb.cc取aa.bb下的items 432 | let paths = str.split(/\.|\:/); 433 | // 最后一个不算,不管是空还是有文字的 434 | paths.pop(); 435 | // console.log("paths",arr); 436 | 437 | this.findCompletions(paths, this._cppList, completions); 438 | let curFile: FileDoc; 439 | for (let i = 0; i < this._fileList.length; i++) { 440 | const f = this._fileList[i]; 441 | this.findCompletions(paths, f.globals, completions); 442 | if (f.uri == uri) { 443 | curFile = f; 444 | } 445 | } 446 | 447 | if (completions.length == 0) { 448 | // 如果是局部变量,则加上所有的定义 449 | this.pickAllGlobal(completions); 450 | if (curFile) { 451 | this.pickItems(curFile.locals, completions, true); 452 | } 453 | } else if (curFile) { 454 | this.findCompletions(paths, curFile.locals, completions); 455 | } 456 | // console.log(completions); 457 | // if (curFile) { 458 | // this.findCompletions(paths, curFile.locals, completions); 459 | // } 460 | // 加上关键字 461 | if (paths.length == 0) { 462 | completions = completions.concat(this._keyList); 463 | } 464 | 465 | return completions; 466 | } 467 | /** 468 | * 加上所有全局 469 | * @param completions 470 | */ 471 | private pickAllGlobal(completions: CompletionItem[]): void { 472 | this.pickItems(this._cppList, completions, true); 473 | for (let i = 0; i < this._fileList.length; i++) { 474 | const f = this._fileList[i]; 475 | this.pickItems(f.globals, completions, true); 476 | } 477 | } 478 | /** 479 | * 从列表中找到对应路径的Completion 480 | * @param paths 481 | * @param list 482 | * @param completions 483 | */ 484 | private findCompletions(paths: string[], list: DocItem[], completions: CompletionItem[]) { 485 | if (!paths || paths.length == 0) { 486 | // 没有则选择第一个 487 | this.pickItems(list, completions, false); 488 | return; 489 | } 490 | // 找到的最后点 491 | let lastItem: DocItem; 492 | for (let i = 0; i < paths.length; i++) { 493 | const p = paths[i]; 494 | // 是否有相关节点 495 | let has = false; 496 | for (let j = 0; j < list.length; j++) { 497 | let item = list[j]; 498 | if (item.name == p) { 499 | if (item.refer) { 500 | item = item.refer; 501 | } 502 | if (item.items && item.items.length > 0) { 503 | list = item.items; 504 | lastItem = item; 505 | has = true; 506 | break; 507 | } 508 | else { 509 | // 当前路径节点下没有子项,则无可加入的Completion 510 | return; 511 | } 512 | } 513 | } 514 | if (!has) { 515 | // 没有当前节点,不符合,pass 516 | return; 517 | } 518 | } 519 | // 有这一路径的节点 520 | if (lastItem) { 521 | if (lastItem.refer) { 522 | lastItem = lastItem.refer; 523 | } 524 | if (lastItem.items && lastItem.items.length > 0) { 525 | this.pickItems(lastItem.items, completions, false); 526 | } 527 | } 528 | } 529 | /** 530 | * 查找paths列表对应的节点 531 | * @param paths 532 | * @param list 533 | */ 534 | private findDocItem(paths: string[], list: DocItem[]): DocItem { 535 | if (!paths || paths.length == 0) { 536 | return null; 537 | } 538 | let findList = list; 539 | for (let i = 0; i < paths.length; i++) { 540 | const p = paths[i]; 541 | // 当前节点 542 | let curItem: DocItem; 543 | for (let j = 0; j < findList.length; j++) { 544 | let item = findList[j]; 545 | if (item.name == p) { 546 | curItem = item; 547 | break; 548 | } 549 | } 550 | if (!curItem) { 551 | // 没有当前节点,不符合,pass 552 | return null; 553 | } 554 | if (i == paths.length - 1) { 555 | // 已经找完整个路径了,已找到 556 | return curItem; 557 | } 558 | if (curItem.refer) { 559 | curItem = curItem.refer; 560 | } 561 | // 路径没找完,继续向下找 562 | if (curItem.items && curItem.items.length > 0) { 563 | findList = curItem.items; 564 | } 565 | else { 566 | // 当前路径节点下没有子项 567 | return null; 568 | } 569 | } 570 | // 都没找到 571 | return null; 572 | } 573 | /** 574 | * 多个DocItem放入列表中 575 | * @param items 576 | * @param completions 577 | * @param pickChildren 578 | */ 579 | private pickItems(items: DocItem[], completions: CompletionItem[], pickChildren: boolean) { 580 | for (let i = 0; i < items.length; i++) { 581 | this.pickItem(items[i], completions, pickChildren); 582 | } 583 | } 584 | /** 585 | * 把一个DocItem放置到列表中 586 | * @param item 587 | * @param completions 588 | * @param pickChildren 是否添加子项 589 | */ 590 | private pickItem(item: DocItem, completions: CompletionItem[], pickChildren: boolean): void { 591 | if (!item.virtual) { 592 | completions.push(item.completion); 593 | } 594 | if (item.refer) { 595 | return; 596 | } 597 | if (pickChildren && item.items && item.items.length > 0) { 598 | this.pickItems(item.items, completions, true); 599 | } 600 | } 601 | } 602 | /** 603 | * 解析器,导出单例 604 | */ 605 | export const Builder = new Builder0(); -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/luaparse@^0.0.29": 6 | version "0.0.29" 7 | resolved "http://registry.npm.taobao.org/@types/luaparse/download/@types/luaparse-0.0.29.tgz#a72b1eb08ca7193e17aca0c7474d4984b8c6282e" 8 | 9 | "@types/mocha@^5.2.5": 10 | version "5.2.5" 11 | resolved "http://registry.npm.taobao.org/@types/mocha/download/@types/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073" 12 | 13 | "@types/node@^10.3.6", "@types/node@^10.7.1": 14 | version "10.9.4" 15 | resolved "http://registry.npm.taobao.org/@types/node/download/@types/node-10.9.4.tgz#0f4cb2dc7c1de6096055357f70179043c33e9897" 16 | 17 | ajv@^5.3.0: 18 | version "5.5.2" 19 | resolved "http://registry.npm.taobao.org/ajv/download/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" 20 | dependencies: 21 | co "^4.6.0" 22 | fast-deep-equal "^1.0.0" 23 | fast-json-stable-stringify "^2.0.0" 24 | json-schema-traverse "^0.3.0" 25 | 26 | ansi-cyan@^0.1.1: 27 | version "0.1.1" 28 | resolved "http://registry.npm.taobao.org/ansi-cyan/download/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" 29 | dependencies: 30 | ansi-wrap "0.1.0" 31 | 32 | ansi-red@^0.1.1: 33 | version "0.1.1" 34 | resolved "http://registry.npm.taobao.org/ansi-red/download/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" 35 | dependencies: 36 | ansi-wrap "0.1.0" 37 | 38 | ansi-wrap@0.1.0: 39 | version "0.1.0" 40 | resolved "http://registry.npm.taobao.org/ansi-wrap/download/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" 41 | 42 | arr-diff@^1.0.1: 43 | version "1.1.0" 44 | resolved "http://registry.npm.taobao.org/arr-diff/download/arr-diff-1.1.0.tgz#687c32758163588fef7de7b36fabe495eb1a399a" 45 | dependencies: 46 | arr-flatten "^1.0.1" 47 | array-slice "^0.2.3" 48 | 49 | arr-diff@^2.0.0: 50 | version "2.0.0" 51 | resolved "http://registry.npm.taobao.org/arr-diff/download/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" 52 | dependencies: 53 | arr-flatten "^1.0.1" 54 | 55 | arr-flatten@^1.0.1: 56 | version "1.1.0" 57 | resolved "http://registry.npm.taobao.org/arr-flatten/download/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" 58 | 59 | arr-union@^2.0.1: 60 | version "2.1.0" 61 | resolved "http://registry.npm.taobao.org/arr-union/download/arr-union-2.1.0.tgz#20f9eab5ec70f5c7d215b1077b1c39161d292c7d" 62 | 63 | array-differ@^1.0.0: 64 | version "1.0.0" 65 | resolved "http://registry.npm.taobao.org/array-differ/download/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" 66 | 67 | array-slice@^0.2.3: 68 | version "0.2.3" 69 | resolved "http://registry.npm.taobao.org/array-slice/download/array-slice-0.2.3.tgz#dd3cfb80ed7973a75117cdac69b0b99ec86186f5" 70 | 71 | array-union@^1.0.1: 72 | version "1.0.2" 73 | resolved "http://registry.npm.taobao.org/array-union/download/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" 74 | dependencies: 75 | array-uniq "^1.0.1" 76 | 77 | array-uniq@^1.0.1: 78 | version "1.0.3" 79 | resolved "http://registry.npm.taobao.org/array-uniq/download/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" 80 | 81 | array-unique@^0.2.1: 82 | version "0.2.1" 83 | resolved "http://registry.npm.taobao.org/array-unique/download/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" 84 | 85 | arrify@^1.0.0: 86 | version "1.0.1" 87 | resolved "http://registry.npm.taobao.org/arrify/download/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" 88 | 89 | asn1@~0.2.3: 90 | version "0.2.4" 91 | resolved "http://registry.npm.taobao.org/asn1/download/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" 92 | dependencies: 93 | safer-buffer "~2.1.0" 94 | 95 | assert-plus@1.0.0, assert-plus@^1.0.0: 96 | version "1.0.0" 97 | resolved "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 98 | 99 | asynckit@^0.4.0: 100 | version "0.4.0" 101 | resolved "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 102 | 103 | aws-sign2@~0.7.0: 104 | version "0.7.0" 105 | resolved "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" 106 | 107 | aws4@^1.8.0: 108 | version "1.8.0" 109 | resolved "http://registry.npm.taobao.org/aws4/download/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" 110 | 111 | balanced-match@^1.0.0: 112 | version "1.0.0" 113 | resolved "http://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 114 | 115 | bcrypt-pbkdf@^1.0.0: 116 | version "1.0.2" 117 | resolved "http://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" 118 | dependencies: 119 | tweetnacl "^0.14.3" 120 | 121 | block-stream@*: 122 | version "0.0.9" 123 | resolved "http://registry.npm.taobao.org/block-stream/download/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" 124 | dependencies: 125 | inherits "~2.0.0" 126 | 127 | brace-expansion@^1.1.7: 128 | version "1.1.11" 129 | resolved "http://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 130 | dependencies: 131 | balanced-match "^1.0.0" 132 | concat-map "0.0.1" 133 | 134 | braces@^1.8.2: 135 | version "1.8.5" 136 | resolved "http://registry.npm.taobao.org/braces/download/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" 137 | dependencies: 138 | expand-range "^1.8.1" 139 | preserve "^0.2.0" 140 | repeat-element "^1.1.2" 141 | 142 | browser-stdout@1.3.0: 143 | version "1.3.0" 144 | resolved "http://registry.npm.taobao.org/browser-stdout/download/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" 145 | 146 | browser-stdout@1.3.1: 147 | version "1.3.1" 148 | resolved "http://registry.npm.taobao.org/browser-stdout/download/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" 149 | 150 | buffer-crc32@~0.2.3: 151 | version "0.2.13" 152 | resolved "http://registry.npm.taobao.org/buffer-crc32/download/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" 153 | 154 | buffer-from@^1.0.0: 155 | version "1.1.1" 156 | resolved "http://registry.npm.taobao.org/buffer-from/download/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" 157 | 158 | caseless@~0.12.0: 159 | version "0.12.0" 160 | resolved "http://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 161 | 162 | clone-buffer@^1.0.0: 163 | version "1.0.0" 164 | resolved "http://registry.npm.taobao.org/clone-buffer/download/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" 165 | 166 | clone-stats@^0.0.1: 167 | version "0.0.1" 168 | resolved "http://registry.npm.taobao.org/clone-stats/download/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" 169 | 170 | clone-stats@^1.0.0: 171 | version "1.0.0" 172 | resolved "http://registry.npm.taobao.org/clone-stats/download/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" 173 | 174 | clone@^0.2.0: 175 | version "0.2.0" 176 | resolved "http://registry.npm.taobao.org/clone/download/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" 177 | 178 | clone@^1.0.0: 179 | version "1.0.4" 180 | resolved "http://registry.npm.taobao.org/clone/download/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" 181 | 182 | clone@^2.1.1: 183 | version "2.1.2" 184 | resolved "http://registry.npm.taobao.org/clone/download/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" 185 | 186 | cloneable-readable@^1.0.0: 187 | version "1.1.2" 188 | resolved "http://registry.npm.taobao.org/cloneable-readable/download/cloneable-readable-1.1.2.tgz#d591dee4a8f8bc15da43ce97dceeba13d43e2a65" 189 | dependencies: 190 | inherits "^2.0.1" 191 | process-nextick-args "^2.0.0" 192 | readable-stream "^2.3.5" 193 | 194 | co@^4.6.0: 195 | version "4.6.0" 196 | resolved "http://registry.npm.taobao.org/co/download/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" 197 | 198 | combined-stream@1.0.6, combined-stream@~1.0.6: 199 | version "1.0.6" 200 | resolved "http://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" 201 | dependencies: 202 | delayed-stream "~1.0.0" 203 | 204 | commander@2.11.0: 205 | version "2.11.0" 206 | resolved "http://registry.npm.taobao.org/commander/download/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" 207 | 208 | commander@2.15.1: 209 | version "2.15.1" 210 | resolved "http://registry.npm.taobao.org/commander/download/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" 211 | 212 | concat-map@0.0.1: 213 | version "0.0.1" 214 | resolved "http://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 215 | 216 | convert-source-map@^1.1.1: 217 | version "1.5.1" 218 | resolved "http://registry.npm.taobao.org/convert-source-map/download/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5" 219 | 220 | core-util-is@1.0.2, core-util-is@~1.0.0: 221 | version "1.0.2" 222 | resolved "http://registry.npm.taobao.org/core-util-is/download/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 223 | 224 | crlf-helper@^0.1.0: 225 | version "0.1.0" 226 | resolved "http://registry.npm.taobao.org/crlf-helper/download/crlf-helper-0.1.0.tgz#bc1cd29be5462a6a1010e62deeb0fba1c1b076cc" 227 | 228 | dashdash@^1.12.0: 229 | version "1.14.1" 230 | resolved "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 231 | dependencies: 232 | assert-plus "^1.0.0" 233 | 234 | debug@3.1.0: 235 | version "3.1.0" 236 | resolved "http://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 237 | dependencies: 238 | ms "2.0.0" 239 | 240 | deep-assign@^1.0.0: 241 | version "1.0.0" 242 | resolved "http://registry.npm.taobao.org/deep-assign/download/deep-assign-1.0.0.tgz#b092743be8427dc621ea0067cdec7e70dd19f37b" 243 | dependencies: 244 | is-obj "^1.0.0" 245 | 246 | delayed-stream@~1.0.0: 247 | version "1.0.0" 248 | resolved "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 249 | 250 | diff@3.3.1: 251 | version "3.3.1" 252 | resolved "http://registry.npm.taobao.org/diff/download/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" 253 | 254 | diff@3.5.0: 255 | version "3.5.0" 256 | resolved "http://registry.npm.taobao.org/diff/download/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" 257 | 258 | duplexer@~0.1.1: 259 | version "0.1.1" 260 | resolved "http://registry.npm.taobao.org/duplexer/download/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" 261 | 262 | duplexify@^3.2.0: 263 | version "3.6.0" 264 | resolved "http://registry.npm.taobao.org/duplexify/download/duplexify-3.6.0.tgz#592903f5d80b38d037220541264d69a198fb3410" 265 | dependencies: 266 | end-of-stream "^1.0.0" 267 | inherits "^2.0.1" 268 | readable-stream "^2.0.0" 269 | stream-shift "^1.0.0" 270 | 271 | ecc-jsbn@~0.1.1: 272 | version "0.1.2" 273 | resolved "http://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" 274 | dependencies: 275 | jsbn "~0.1.0" 276 | safer-buffer "^2.1.0" 277 | 278 | end-of-stream@^1.0.0: 279 | version "1.4.1" 280 | resolved "http://registry.npm.taobao.org/end-of-stream/download/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" 281 | dependencies: 282 | once "^1.4.0" 283 | 284 | escape-string-regexp@1.0.5: 285 | version "1.0.5" 286 | resolved "http://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 287 | 288 | event-stream@^3.3.1, event-stream@^3.3.4, event-stream@~3.3.4: 289 | version "3.3.4" 290 | resolved "http://registry.npm.taobao.org/event-stream/download/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571" 291 | dependencies: 292 | duplexer "~0.1.1" 293 | from "~0" 294 | map-stream "~0.1.0" 295 | pause-stream "0.0.11" 296 | split "0.3" 297 | stream-combiner "~0.0.4" 298 | through "~2.3.1" 299 | 300 | expand-brackets@^0.1.4: 301 | version "0.1.5" 302 | resolved "http://registry.npm.taobao.org/expand-brackets/download/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" 303 | dependencies: 304 | is-posix-bracket "^0.1.0" 305 | 306 | expand-range@^1.8.1: 307 | version "1.8.2" 308 | resolved "http://registry.npm.taobao.org/expand-range/download/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" 309 | dependencies: 310 | fill-range "^2.1.0" 311 | 312 | extend-shallow@^1.1.2: 313 | version "1.1.4" 314 | resolved "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" 315 | dependencies: 316 | kind-of "^1.1.0" 317 | 318 | extend-shallow@^2.0.1: 319 | version "2.0.1" 320 | resolved "http://registry.npm.taobao.org/extend-shallow/download/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" 321 | dependencies: 322 | is-extendable "^0.1.0" 323 | 324 | extend@^3.0.0, extend@~3.0.2: 325 | version "3.0.2" 326 | resolved "http://registry.npm.taobao.org/extend/download/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 327 | 328 | extglob@^0.3.1: 329 | version "0.3.2" 330 | resolved "http://registry.npm.taobao.org/extglob/download/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" 331 | dependencies: 332 | is-extglob "^1.0.0" 333 | 334 | extsprintf@1.3.0: 335 | version "1.3.0" 336 | resolved "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 337 | 338 | extsprintf@^1.2.0: 339 | version "1.4.0" 340 | resolved "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 341 | 342 | fast-deep-equal@^1.0.0: 343 | version "1.1.0" 344 | resolved "http://registry.npm.taobao.org/fast-deep-equal/download/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" 345 | 346 | fast-json-stable-stringify@^2.0.0: 347 | version "2.0.0" 348 | resolved "http://registry.npm.taobao.org/fast-json-stable-stringify/download/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" 349 | 350 | fd-slicer@~1.1.0: 351 | version "1.1.0" 352 | resolved "http://registry.npm.taobao.org/fd-slicer/download/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" 353 | dependencies: 354 | pend "~1.2.0" 355 | 356 | filename-regex@^2.0.0: 357 | version "2.0.1" 358 | resolved "http://registry.npm.taobao.org/filename-regex/download/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" 359 | 360 | fill-range@^2.1.0: 361 | version "2.2.4" 362 | resolved "http://registry.npm.taobao.org/fill-range/download/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" 363 | dependencies: 364 | is-number "^2.1.0" 365 | isobject "^2.0.0" 366 | randomatic "^3.0.0" 367 | repeat-element "^1.1.2" 368 | repeat-string "^1.5.2" 369 | 370 | first-chunk-stream@^1.0.0: 371 | version "1.0.0" 372 | resolved "http://registry.npm.taobao.org/first-chunk-stream/download/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" 373 | 374 | for-in@^1.0.1: 375 | version "1.0.2" 376 | resolved "http://registry.npm.taobao.org/for-in/download/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" 377 | 378 | for-own@^0.1.4: 379 | version "0.1.5" 380 | resolved "http://registry.npm.taobao.org/for-own/download/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" 381 | dependencies: 382 | for-in "^1.0.1" 383 | 384 | forever-agent@~0.6.1: 385 | version "0.6.1" 386 | resolved "http://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 387 | 388 | form-data@~2.3.2: 389 | version "2.3.2" 390 | resolved "http://registry.npm.taobao.org/form-data/download/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" 391 | dependencies: 392 | asynckit "^0.4.0" 393 | combined-stream "1.0.6" 394 | mime-types "^2.1.12" 395 | 396 | from@~0: 397 | version "0.1.7" 398 | resolved "http://registry.npm.taobao.org/from/download/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" 399 | 400 | fs.realpath@^1.0.0: 401 | version "1.0.0" 402 | resolved "http://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 403 | 404 | fstream@^1.0.2: 405 | version "1.0.11" 406 | resolved "http://registry.npm.taobao.org/fstream/download/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" 407 | dependencies: 408 | graceful-fs "^4.1.2" 409 | inherits "~2.0.0" 410 | mkdirp ">=0.5 0" 411 | rimraf "2" 412 | 413 | getpass@^0.1.1: 414 | version "0.1.7" 415 | resolved "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 416 | dependencies: 417 | assert-plus "^1.0.0" 418 | 419 | glob-base@^0.3.0: 420 | version "0.3.0" 421 | resolved "http://registry.npm.taobao.org/glob-base/download/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" 422 | dependencies: 423 | glob-parent "^2.0.0" 424 | is-glob "^2.0.0" 425 | 426 | glob-parent@^2.0.0: 427 | version "2.0.0" 428 | resolved "http://registry.npm.taobao.org/glob-parent/download/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" 429 | dependencies: 430 | is-glob "^2.0.0" 431 | 432 | glob-parent@^3.0.0: 433 | version "3.1.0" 434 | resolved "http://registry.npm.taobao.org/glob-parent/download/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" 435 | dependencies: 436 | is-glob "^3.1.0" 437 | path-dirname "^1.0.0" 438 | 439 | glob-stream@^5.3.2: 440 | version "5.3.5" 441 | resolved "http://registry.npm.taobao.org/glob-stream/download/glob-stream-5.3.5.tgz#a55665a9a8ccdc41915a87c701e32d4e016fad22" 442 | dependencies: 443 | extend "^3.0.0" 444 | glob "^5.0.3" 445 | glob-parent "^3.0.0" 446 | micromatch "^2.3.7" 447 | ordered-read-streams "^0.3.0" 448 | through2 "^0.6.0" 449 | to-absolute-glob "^0.1.1" 450 | unique-stream "^2.0.2" 451 | 452 | glob@7.1.2: 453 | version "7.1.2" 454 | resolved "http://registry.npm.taobao.org/glob/download/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 455 | dependencies: 456 | fs.realpath "^1.0.0" 457 | inflight "^1.0.4" 458 | inherits "2" 459 | minimatch "^3.0.4" 460 | once "^1.3.0" 461 | path-is-absolute "^1.0.0" 462 | 463 | glob@^5.0.3: 464 | version "5.0.15" 465 | resolved "http://registry.npm.taobao.org/glob/download/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" 466 | dependencies: 467 | inflight "^1.0.4" 468 | inherits "2" 469 | minimatch "2 || 3" 470 | once "^1.3.0" 471 | path-is-absolute "^1.0.0" 472 | 473 | glob@^7.0.5, glob@^7.1.2: 474 | version "7.1.3" 475 | resolved "http://registry.npm.taobao.org/glob/download/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" 476 | dependencies: 477 | fs.realpath "^1.0.0" 478 | inflight "^1.0.4" 479 | inherits "2" 480 | minimatch "^3.0.4" 481 | once "^1.3.0" 482 | path-is-absolute "^1.0.0" 483 | 484 | graceful-fs@^4.0.0, graceful-fs@^4.1.2: 485 | version "4.1.11" 486 | resolved "http://registry.npm.taobao.org/graceful-fs/download/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 487 | 488 | growl@1.10.3: 489 | version "1.10.3" 490 | resolved "http://registry.npm.taobao.org/growl/download/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" 491 | 492 | growl@1.10.5: 493 | version "1.10.5" 494 | resolved "http://registry.npm.taobao.org/growl/download/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" 495 | 496 | gulp-chmod@^2.0.0: 497 | version "2.0.0" 498 | resolved "http://registry.npm.taobao.org/gulp-chmod/download/gulp-chmod-2.0.0.tgz#00c390b928a0799b251accf631aa09e01cc6299c" 499 | dependencies: 500 | deep-assign "^1.0.0" 501 | stat-mode "^0.2.0" 502 | through2 "^2.0.0" 503 | 504 | gulp-filter@^5.0.1: 505 | version "5.1.0" 506 | resolved "http://registry.npm.taobao.org/gulp-filter/download/gulp-filter-5.1.0.tgz#a05e11affb07cf7dcf41a7de1cb7b63ac3783e73" 507 | dependencies: 508 | multimatch "^2.0.0" 509 | plugin-error "^0.1.2" 510 | streamfilter "^1.0.5" 511 | 512 | gulp-gunzip@1.0.0: 513 | version "1.0.0" 514 | resolved "http://registry.npm.taobao.org/gulp-gunzip/download/gulp-gunzip-1.0.0.tgz#15b741145e83a9c6f50886241b57cc5871f151a9" 515 | dependencies: 516 | through2 "~0.6.5" 517 | vinyl "~0.4.6" 518 | 519 | gulp-remote-src-vscode@^0.5.0: 520 | version "0.5.0" 521 | resolved "http://registry.npm.taobao.org/gulp-remote-src-vscode/download/gulp-remote-src-vscode-0.5.0.tgz#71785553bc491880088ad971f90910c4b2d80a99" 522 | dependencies: 523 | event-stream "^3.3.4" 524 | node.extend "^1.1.2" 525 | request "^2.79.0" 526 | through2 "^2.0.3" 527 | vinyl "^2.0.1" 528 | 529 | gulp-sourcemaps@1.6.0: 530 | version "1.6.0" 531 | resolved "http://registry.npm.taobao.org/gulp-sourcemaps/download/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" 532 | dependencies: 533 | convert-source-map "^1.1.1" 534 | graceful-fs "^4.1.2" 535 | strip-bom "^2.0.0" 536 | through2 "^2.0.0" 537 | vinyl "^1.0.0" 538 | 539 | gulp-symdest@^1.1.0: 540 | version "1.1.0" 541 | resolved "http://registry.npm.taobao.org/gulp-symdest/download/gulp-symdest-1.1.0.tgz#c165320732d192ce56fd94271ffa123234bf2ae0" 542 | dependencies: 543 | event-stream "^3.3.1" 544 | mkdirp "^0.5.1" 545 | queue "^3.1.0" 546 | vinyl-fs "^2.4.3" 547 | 548 | gulp-untar@^0.0.7: 549 | version "0.0.7" 550 | resolved "http://registry.npm.taobao.org/gulp-untar/download/gulp-untar-0.0.7.tgz#92067d79e0fa1e92d60562a100233a44a5aa08b4" 551 | dependencies: 552 | event-stream "~3.3.4" 553 | streamifier "~0.1.1" 554 | tar "^2.2.1" 555 | through2 "~2.0.3" 556 | vinyl "^1.2.0" 557 | 558 | gulp-vinyl-zip@^2.1.0: 559 | version "2.1.0" 560 | resolved "http://registry.npm.taobao.org/gulp-vinyl-zip/download/gulp-vinyl-zip-2.1.0.tgz#24e40685dc05b7149995245099e0590263be8dad" 561 | dependencies: 562 | event-stream "^3.3.1" 563 | queue "^4.2.1" 564 | through2 "^2.0.3" 565 | vinyl "^2.0.2" 566 | vinyl-fs "^2.0.0" 567 | yauzl "^2.2.1" 568 | yazl "^2.2.1" 569 | 570 | har-schema@^2.0.0: 571 | version "2.0.0" 572 | resolved "http://registry.npm.taobao.org/har-schema/download/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" 573 | 574 | har-validator@~5.1.0: 575 | version "5.1.0" 576 | resolved "http://registry.npm.taobao.org/har-validator/download/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" 577 | dependencies: 578 | ajv "^5.3.0" 579 | har-schema "^2.0.0" 580 | 581 | has-flag@^2.0.0: 582 | version "2.0.0" 583 | resolved "http://registry.npm.taobao.org/has-flag/download/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" 584 | 585 | has-flag@^3.0.0: 586 | version "3.0.0" 587 | resolved "http://registry.npm.taobao.org/has-flag/download/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 588 | 589 | he@1.1.1: 590 | version "1.1.1" 591 | resolved "http://registry.npm.taobao.org/he/download/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" 592 | 593 | http-signature@~1.2.0: 594 | version "1.2.0" 595 | resolved "http://registry.npm.taobao.org/http-signature/download/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" 596 | dependencies: 597 | assert-plus "^1.0.0" 598 | jsprim "^1.2.2" 599 | sshpk "^1.7.0" 600 | 601 | inflight@^1.0.4: 602 | version "1.0.6" 603 | resolved "http://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 604 | dependencies: 605 | once "^1.3.0" 606 | wrappy "1" 607 | 608 | inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: 609 | version "2.0.3" 610 | resolved "http://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 611 | 612 | is-buffer@^1.1.5: 613 | version "1.1.6" 614 | resolved "http://registry.npm.taobao.org/is-buffer/download/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" 615 | 616 | is-dotfile@^1.0.0: 617 | version "1.0.3" 618 | resolved "http://registry.npm.taobao.org/is-dotfile/download/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" 619 | 620 | is-equal-shallow@^0.1.3: 621 | version "0.1.3" 622 | resolved "http://registry.npm.taobao.org/is-equal-shallow/download/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" 623 | dependencies: 624 | is-primitive "^2.0.0" 625 | 626 | is-extendable@^0.1.0, is-extendable@^0.1.1: 627 | version "0.1.1" 628 | resolved "http://registry.npm.taobao.org/is-extendable/download/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" 629 | 630 | is-extglob@^1.0.0: 631 | version "1.0.0" 632 | resolved "http://registry.npm.taobao.org/is-extglob/download/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" 633 | 634 | is-extglob@^2.1.0: 635 | version "2.1.1" 636 | resolved "http://registry.npm.taobao.org/is-extglob/download/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 637 | 638 | is-glob@^2.0.0, is-glob@^2.0.1: 639 | version "2.0.1" 640 | resolved "http://registry.npm.taobao.org/is-glob/download/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" 641 | dependencies: 642 | is-extglob "^1.0.0" 643 | 644 | is-glob@^3.1.0: 645 | version "3.1.0" 646 | resolved "http://registry.npm.taobao.org/is-glob/download/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" 647 | dependencies: 648 | is-extglob "^2.1.0" 649 | 650 | is-number@^2.1.0: 651 | version "2.1.0" 652 | resolved "http://registry.npm.taobao.org/is-number/download/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" 653 | dependencies: 654 | kind-of "^3.0.2" 655 | 656 | is-number@^4.0.0: 657 | version "4.0.0" 658 | resolved "http://registry.npm.taobao.org/is-number/download/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" 659 | 660 | is-obj@^1.0.0: 661 | version "1.0.1" 662 | resolved "http://registry.npm.taobao.org/is-obj/download/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" 663 | 664 | is-posix-bracket@^0.1.0: 665 | version "0.1.1" 666 | resolved "http://registry.npm.taobao.org/is-posix-bracket/download/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" 667 | 668 | is-primitive@^2.0.0: 669 | version "2.0.0" 670 | resolved "http://registry.npm.taobao.org/is-primitive/download/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" 671 | 672 | is-stream@^1.0.1: 673 | version "1.1.0" 674 | resolved "http://registry.npm.taobao.org/is-stream/download/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 675 | 676 | is-typedarray@~1.0.0: 677 | version "1.0.0" 678 | resolved "http://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 679 | 680 | is-utf8@^0.2.0: 681 | version "0.2.1" 682 | resolved "http://registry.npm.taobao.org/is-utf8/download/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" 683 | 684 | is-valid-glob@^0.3.0: 685 | version "0.3.0" 686 | resolved "http://registry.npm.taobao.org/is-valid-glob/download/is-valid-glob-0.3.0.tgz#d4b55c69f51886f9b65c70d6c2622d37e29f48fe" 687 | 688 | is@^3.1.0: 689 | version "3.2.1" 690 | resolved "http://registry.npm.taobao.org/is/download/is-3.2.1.tgz#d0ac2ad55eb7b0bec926a5266f6c662aaa83dca5" 691 | 692 | isarray@0.0.1: 693 | version "0.0.1" 694 | resolved "http://registry.npm.taobao.org/isarray/download/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" 695 | 696 | isarray@1.0.0, isarray@~1.0.0: 697 | version "1.0.0" 698 | resolved "http://registry.npm.taobao.org/isarray/download/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 699 | 700 | isobject@^2.0.0: 701 | version "2.1.0" 702 | resolved "http://registry.npm.taobao.org/isobject/download/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" 703 | dependencies: 704 | isarray "1.0.0" 705 | 706 | isstream@~0.1.2: 707 | version "0.1.2" 708 | resolved "http://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 709 | 710 | jsbn@~0.1.0: 711 | version "0.1.1" 712 | resolved "http://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 713 | 714 | json-schema-traverse@^0.3.0: 715 | version "0.3.1" 716 | resolved "http://registry.npm.taobao.org/json-schema-traverse/download/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" 717 | 718 | json-schema@0.2.3: 719 | version "0.2.3" 720 | resolved "http://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 721 | 722 | json-stable-stringify@^1.0.0: 723 | version "1.0.1" 724 | resolved "http://registry.npm.taobao.org/json-stable-stringify/download/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" 725 | dependencies: 726 | jsonify "~0.0.0" 727 | 728 | json-stringify-safe@~5.0.1: 729 | version "5.0.1" 730 | resolved "http://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 731 | 732 | jsonify@~0.0.0: 733 | version "0.0.0" 734 | resolved "http://registry.npm.taobao.org/jsonify/download/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" 735 | 736 | jsprim@^1.2.2: 737 | version "1.4.1" 738 | resolved "http://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 739 | dependencies: 740 | assert-plus "1.0.0" 741 | extsprintf "1.3.0" 742 | json-schema "0.2.3" 743 | verror "1.10.0" 744 | 745 | kind-of@^1.1.0: 746 | version "1.1.0" 747 | resolved "http://registry.npm.taobao.org/kind-of/download/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" 748 | 749 | kind-of@^3.0.2: 750 | version "3.2.2" 751 | resolved "http://registry.npm.taobao.org/kind-of/download/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" 752 | dependencies: 753 | is-buffer "^1.1.5" 754 | 755 | kind-of@^6.0.0: 756 | version "6.0.2" 757 | resolved "http://registry.npm.taobao.org/kind-of/download/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" 758 | 759 | lazystream@^1.0.0: 760 | version "1.0.0" 761 | resolved "http://registry.npm.taobao.org/lazystream/download/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" 762 | dependencies: 763 | readable-stream "^2.0.5" 764 | 765 | lodash.isequal@^4.0.0: 766 | version "4.5.0" 767 | resolved "http://registry.npm.taobao.org/lodash.isequal/download/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" 768 | 769 | luaparse@^0.2.1: 770 | version "0.2.1" 771 | resolved "http://registry.npm.taobao.org/luaparse/download/luaparse-0.2.1.tgz#aa8f56132b0de97d37f3c991a9df42e0e17f656c" 772 | 773 | map-stream@~0.1.0: 774 | version "0.1.0" 775 | resolved "http://registry.npm.taobao.org/map-stream/download/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194" 776 | 777 | math-random@^1.0.1: 778 | version "1.0.1" 779 | resolved "http://registry.npm.taobao.org/math-random/download/math-random-1.0.1.tgz#8b3aac588b8a66e4975e3cdea67f7bb329601fac" 780 | 781 | merge-stream@^1.0.0: 782 | version "1.0.1" 783 | resolved "http://registry.npm.taobao.org/merge-stream/download/merge-stream-1.0.1.tgz#4041202d508a342ba00174008df0c251b8c135e1" 784 | dependencies: 785 | readable-stream "^2.0.1" 786 | 787 | micromatch@^2.3.7: 788 | version "2.3.11" 789 | resolved "http://registry.npm.taobao.org/micromatch/download/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" 790 | dependencies: 791 | arr-diff "^2.0.0" 792 | array-unique "^0.2.1" 793 | braces "^1.8.2" 794 | expand-brackets "^0.1.4" 795 | extglob "^0.3.1" 796 | filename-regex "^2.0.0" 797 | is-extglob "^1.0.0" 798 | is-glob "^2.0.1" 799 | kind-of "^3.0.2" 800 | normalize-path "^2.0.1" 801 | object.omit "^2.0.0" 802 | parse-glob "^3.0.4" 803 | regex-cache "^0.4.2" 804 | 805 | mime-db@~1.36.0: 806 | version "1.36.0" 807 | resolved "http://registry.npm.taobao.org/mime-db/download/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" 808 | 809 | mime-types@^2.1.12, mime-types@~2.1.19: 810 | version "2.1.20" 811 | resolved "http://registry.npm.taobao.org/mime-types/download/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" 812 | dependencies: 813 | mime-db "~1.36.0" 814 | 815 | "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.4: 816 | version "3.0.4" 817 | resolved "http://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 818 | dependencies: 819 | brace-expansion "^1.1.7" 820 | 821 | minimist@0.0.8: 822 | version "0.0.8" 823 | resolved "http://registry.npm.taobao.org/minimist/download/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 824 | 825 | mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: 826 | version "0.5.1" 827 | resolved "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 828 | dependencies: 829 | minimist "0.0.8" 830 | 831 | mocha@^4.0.1: 832 | version "4.1.0" 833 | resolved "http://registry.npm.taobao.org/mocha/download/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" 834 | dependencies: 835 | browser-stdout "1.3.0" 836 | commander "2.11.0" 837 | debug "3.1.0" 838 | diff "3.3.1" 839 | escape-string-regexp "1.0.5" 840 | glob "7.1.2" 841 | growl "1.10.3" 842 | he "1.1.1" 843 | mkdirp "0.5.1" 844 | supports-color "4.4.0" 845 | 846 | mocha@^5.2.0: 847 | version "5.2.0" 848 | resolved "http://registry.npm.taobao.org/mocha/download/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" 849 | dependencies: 850 | browser-stdout "1.3.1" 851 | commander "2.15.1" 852 | debug "3.1.0" 853 | diff "3.5.0" 854 | escape-string-regexp "1.0.5" 855 | glob "7.1.2" 856 | growl "1.10.5" 857 | he "1.1.1" 858 | minimatch "3.0.4" 859 | mkdirp "0.5.1" 860 | supports-color "5.4.0" 861 | 862 | ms@2.0.0: 863 | version "2.0.0" 864 | resolved "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 865 | 866 | multimatch@^2.0.0: 867 | version "2.1.0" 868 | resolved "http://registry.npm.taobao.org/multimatch/download/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" 869 | dependencies: 870 | array-differ "^1.0.0" 871 | array-union "^1.0.1" 872 | arrify "^1.0.0" 873 | minimatch "^3.0.0" 874 | 875 | node.extend@^1.1.2: 876 | version "1.1.6" 877 | resolved "http://registry.npm.taobao.org/node.extend/download/node.extend-1.1.6.tgz#a7b882c82d6c93a4863a5504bd5de8ec86258b96" 878 | dependencies: 879 | is "^3.1.0" 880 | 881 | normalize-path@^2.0.1: 882 | version "2.1.1" 883 | resolved "http://registry.npm.taobao.org/normalize-path/download/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" 884 | dependencies: 885 | remove-trailing-separator "^1.0.1" 886 | 887 | oauth-sign@~0.9.0: 888 | version "0.9.0" 889 | resolved "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" 890 | 891 | object-assign@^4.0.0: 892 | version "4.1.1" 893 | resolved "http://registry.npm.taobao.org/object-assign/download/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 894 | 895 | object.omit@^2.0.0: 896 | version "2.0.1" 897 | resolved "http://registry.npm.taobao.org/object.omit/download/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" 898 | dependencies: 899 | for-own "^0.1.4" 900 | is-extendable "^0.1.1" 901 | 902 | once@^1.3.0, once@^1.4.0: 903 | version "1.4.0" 904 | resolved "http://registry.npm.taobao.org/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 905 | dependencies: 906 | wrappy "1" 907 | 908 | ordered-read-streams@^0.3.0: 909 | version "0.3.0" 910 | resolved "http://registry.npm.taobao.org/ordered-read-streams/download/ordered-read-streams-0.3.0.tgz#7137e69b3298bb342247a1bbee3881c80e2fd78b" 911 | dependencies: 912 | is-stream "^1.0.1" 913 | readable-stream "^2.0.1" 914 | 915 | parse-glob@^3.0.4: 916 | version "3.0.4" 917 | resolved "http://registry.npm.taobao.org/parse-glob/download/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" 918 | dependencies: 919 | glob-base "^0.3.0" 920 | is-dotfile "^1.0.0" 921 | is-extglob "^1.0.0" 922 | is-glob "^2.0.0" 923 | 924 | path-dirname@^1.0.0: 925 | version "1.0.2" 926 | resolved "http://registry.npm.taobao.org/path-dirname/download/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" 927 | 928 | path-is-absolute@^1.0.0: 929 | version "1.0.1" 930 | resolved "http://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 931 | 932 | pause-stream@0.0.11: 933 | version "0.0.11" 934 | resolved "http://registry.npm.taobao.org/pause-stream/download/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" 935 | dependencies: 936 | through "~2.3" 937 | 938 | pend@~1.2.0: 939 | version "1.2.0" 940 | resolved "http://registry.npm.taobao.org/pend/download/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" 941 | 942 | performance-now@^2.1.0: 943 | version "2.1.0" 944 | resolved "http://registry.npm.taobao.org/performance-now/download/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 945 | 946 | plugin-error@^0.1.2: 947 | version "0.1.2" 948 | resolved "http://registry.npm.taobao.org/plugin-error/download/plugin-error-0.1.2.tgz#3b9bb3335ccf00f425e07437e19276967da47ace" 949 | dependencies: 950 | ansi-cyan "^0.1.1" 951 | ansi-red "^0.1.1" 952 | arr-diff "^1.0.1" 953 | arr-union "^2.0.1" 954 | extend-shallow "^1.1.2" 955 | 956 | preserve@^0.2.0: 957 | version "0.2.0" 958 | resolved "http://registry.npm.taobao.org/preserve/download/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" 959 | 960 | process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: 961 | version "2.0.0" 962 | resolved "http://registry.npm.taobao.org/process-nextick-args/download/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" 963 | 964 | psl@^1.1.24: 965 | version "1.1.29" 966 | resolved "http://registry.npm.taobao.org/psl/download/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" 967 | 968 | punycode@^1.4.1: 969 | version "1.4.1" 970 | resolved "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" 971 | 972 | qs@~6.5.2: 973 | version "6.5.2" 974 | resolved "http://registry.npm.taobao.org/qs/download/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" 975 | 976 | querystringify@^2.0.0: 977 | version "2.0.0" 978 | resolved "http://registry.npm.taobao.org/querystringify/download/querystringify-2.0.0.tgz#fa3ed6e68eb15159457c89b37bc6472833195755" 979 | 980 | queue@^3.1.0: 981 | version "3.1.0" 982 | resolved "http://registry.npm.taobao.org/queue/download/queue-3.1.0.tgz#6c49d01f009e2256788789f2bffac6b8b9990585" 983 | dependencies: 984 | inherits "~2.0.0" 985 | 986 | queue@^4.2.1: 987 | version "4.5.0" 988 | resolved "http://registry.npm.taobao.org/queue/download/queue-4.5.0.tgz#0f125191a983e3c38fcc0c0c75087d358d0857f4" 989 | dependencies: 990 | inherits "~2.0.0" 991 | 992 | randomatic@^3.0.0: 993 | version "3.1.0" 994 | resolved "http://registry.npm.taobao.org/randomatic/download/randomatic-3.1.0.tgz#36f2ca708e9e567f5ed2ec01949026d50aa10116" 995 | dependencies: 996 | is-number "^4.0.0" 997 | kind-of "^6.0.0" 998 | math-random "^1.0.1" 999 | 1000 | rd@^2.0.1: 1001 | version "2.0.1" 1002 | resolved "http://registry.npm.taobao.org/rd/download/rd-2.0.1.tgz#e18a8af5b2f7440c0db1523ca04c6e0f9660003f" 1003 | dependencies: 1004 | "@types/node" "^10.3.6" 1005 | 1006 | "readable-stream@>=1.0.33-1 <1.1.0-0": 1007 | version "1.0.34" 1008 | resolved "http://registry.npm.taobao.org/readable-stream/download/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" 1009 | dependencies: 1010 | core-util-is "~1.0.0" 1011 | inherits "~2.0.1" 1012 | isarray "0.0.1" 1013 | string_decoder "~0.10.x" 1014 | 1015 | readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.3.5: 1016 | version "2.3.6" 1017 | resolved "http://registry.npm.taobao.org/readable-stream/download/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" 1018 | dependencies: 1019 | core-util-is "~1.0.0" 1020 | inherits "~2.0.3" 1021 | isarray "~1.0.0" 1022 | process-nextick-args "~2.0.0" 1023 | safe-buffer "~5.1.1" 1024 | string_decoder "~1.1.1" 1025 | util-deprecate "~1.0.1" 1026 | 1027 | regex-cache@^0.4.2: 1028 | version "0.4.4" 1029 | resolved "http://registry.npm.taobao.org/regex-cache/download/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" 1030 | dependencies: 1031 | is-equal-shallow "^0.1.3" 1032 | 1033 | remove-trailing-separator@^1.0.1: 1034 | version "1.1.0" 1035 | resolved "http://registry.npm.taobao.org/remove-trailing-separator/download/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" 1036 | 1037 | repeat-element@^1.1.2: 1038 | version "1.1.3" 1039 | resolved "http://registry.npm.taobao.org/repeat-element/download/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" 1040 | 1041 | repeat-string@^1.5.2: 1042 | version "1.6.1" 1043 | resolved "http://registry.npm.taobao.org/repeat-string/download/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" 1044 | 1045 | replace-ext@0.0.1: 1046 | version "0.0.1" 1047 | resolved "http://registry.npm.taobao.org/replace-ext/download/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" 1048 | 1049 | replace-ext@^1.0.0: 1050 | version "1.0.0" 1051 | resolved "http://registry.npm.taobao.org/replace-ext/download/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" 1052 | 1053 | request@^2.79.0, request@^2.83.0: 1054 | version "2.88.0" 1055 | resolved "http://registry.npm.taobao.org/request/download/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" 1056 | dependencies: 1057 | aws-sign2 "~0.7.0" 1058 | aws4 "^1.8.0" 1059 | caseless "~0.12.0" 1060 | combined-stream "~1.0.6" 1061 | extend "~3.0.2" 1062 | forever-agent "~0.6.1" 1063 | form-data "~2.3.2" 1064 | har-validator "~5.1.0" 1065 | http-signature "~1.2.0" 1066 | is-typedarray "~1.0.0" 1067 | isstream "~0.1.2" 1068 | json-stringify-safe "~5.0.1" 1069 | mime-types "~2.1.19" 1070 | oauth-sign "~0.9.0" 1071 | performance-now "^2.1.0" 1072 | qs "~6.5.2" 1073 | safe-buffer "^5.1.2" 1074 | tough-cookie "~2.4.3" 1075 | tunnel-agent "^0.6.0" 1076 | uuid "^3.3.2" 1077 | 1078 | requires-port@^1.0.0: 1079 | version "1.0.0" 1080 | resolved "http://registry.npm.taobao.org/requires-port/download/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" 1081 | 1082 | rimraf@2: 1083 | version "2.6.2" 1084 | resolved "http://registry.npm.taobao.org/rimraf/download/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" 1085 | dependencies: 1086 | glob "^7.0.5" 1087 | 1088 | safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 1089 | version "5.1.2" 1090 | resolved "http://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 1091 | 1092 | safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: 1093 | version "2.1.2" 1094 | resolved "http://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 1095 | 1096 | semver@^5.4.1, semver@^5.5.0: 1097 | version "5.5.1" 1098 | resolved "http://registry.npm.taobao.org/semver/download/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" 1099 | 1100 | source-map-support@^0.5.0: 1101 | version "0.5.9" 1102 | resolved "http://registry.npm.taobao.org/source-map-support/download/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f" 1103 | dependencies: 1104 | buffer-from "^1.0.0" 1105 | source-map "^0.6.0" 1106 | 1107 | source-map@^0.6.0: 1108 | version "0.6.1" 1109 | resolved "http://registry.npm.taobao.org/source-map/download/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" 1110 | 1111 | split@0.3: 1112 | version "0.3.3" 1113 | resolved "http://registry.npm.taobao.org/split/download/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f" 1114 | dependencies: 1115 | through "2" 1116 | 1117 | sshpk@^1.7.0: 1118 | version "1.14.2" 1119 | resolved "http://registry.npm.taobao.org/sshpk/download/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" 1120 | dependencies: 1121 | asn1 "~0.2.3" 1122 | assert-plus "^1.0.0" 1123 | dashdash "^1.12.0" 1124 | getpass "^0.1.1" 1125 | safer-buffer "^2.0.2" 1126 | optionalDependencies: 1127 | bcrypt-pbkdf "^1.0.0" 1128 | ecc-jsbn "~0.1.1" 1129 | jsbn "~0.1.0" 1130 | tweetnacl "~0.14.0" 1131 | 1132 | stat-mode@^0.2.0: 1133 | version "0.2.2" 1134 | resolved "http://registry.npm.taobao.org/stat-mode/download/stat-mode-0.2.2.tgz#e6c80b623123d7d80cf132ce538f346289072502" 1135 | 1136 | stream-combiner@~0.0.4: 1137 | version "0.0.4" 1138 | resolved "http://registry.npm.taobao.org/stream-combiner/download/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14" 1139 | dependencies: 1140 | duplexer "~0.1.1" 1141 | 1142 | stream-shift@^1.0.0: 1143 | version "1.0.0" 1144 | resolved "http://registry.npm.taobao.org/stream-shift/download/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" 1145 | 1146 | streamfilter@^1.0.5: 1147 | version "1.0.7" 1148 | resolved "http://registry.npm.taobao.org/streamfilter/download/streamfilter-1.0.7.tgz#ae3e64522aa5a35c061fd17f67620c7653c643c9" 1149 | dependencies: 1150 | readable-stream "^2.0.2" 1151 | 1152 | streamifier@~0.1.1: 1153 | version "0.1.1" 1154 | resolved "http://registry.npm.taobao.org/streamifier/download/streamifier-0.1.1.tgz#97e98d8fa4d105d62a2691d1dc07e820db8dfc4f" 1155 | 1156 | string_decoder@~0.10.x: 1157 | version "0.10.31" 1158 | resolved "http://registry.npm.taobao.org/string_decoder/download/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" 1159 | 1160 | string_decoder@~1.1.1: 1161 | version "1.1.1" 1162 | resolved "http://registry.npm.taobao.org/string_decoder/download/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 1163 | dependencies: 1164 | safe-buffer "~5.1.0" 1165 | 1166 | strip-bom-stream@^1.0.0: 1167 | version "1.0.0" 1168 | resolved "http://registry.npm.taobao.org/strip-bom-stream/download/strip-bom-stream-1.0.0.tgz#e7144398577d51a6bed0fa1994fa05f43fd988ee" 1169 | dependencies: 1170 | first-chunk-stream "^1.0.0" 1171 | strip-bom "^2.0.0" 1172 | 1173 | strip-bom@^2.0.0: 1174 | version "2.0.0" 1175 | resolved "http://registry.npm.taobao.org/strip-bom/download/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" 1176 | dependencies: 1177 | is-utf8 "^0.2.0" 1178 | 1179 | supports-color@4.4.0: 1180 | version "4.4.0" 1181 | resolved "http://registry.npm.taobao.org/supports-color/download/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" 1182 | dependencies: 1183 | has-flag "^2.0.0" 1184 | 1185 | supports-color@5.4.0: 1186 | version "5.4.0" 1187 | resolved "http://registry.npm.taobao.org/supports-color/download/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" 1188 | dependencies: 1189 | has-flag "^3.0.0" 1190 | 1191 | tar@^2.2.1: 1192 | version "2.2.1" 1193 | resolved "http://registry.npm.taobao.org/tar/download/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" 1194 | dependencies: 1195 | block-stream "*" 1196 | fstream "^1.0.2" 1197 | inherits "2" 1198 | 1199 | through2-filter@^2.0.0: 1200 | version "2.0.0" 1201 | resolved "http://registry.npm.taobao.org/through2-filter/download/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" 1202 | dependencies: 1203 | through2 "~2.0.0" 1204 | xtend "~4.0.0" 1205 | 1206 | through2@^0.6.0, through2@~0.6.5: 1207 | version "0.6.5" 1208 | resolved "http://registry.npm.taobao.org/through2/download/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" 1209 | dependencies: 1210 | readable-stream ">=1.0.33-1 <1.1.0-0" 1211 | xtend ">=4.0.0 <4.1.0-0" 1212 | 1213 | through2@^2.0.0, through2@^2.0.3, through2@~2.0.0, through2@~2.0.3: 1214 | version "2.0.3" 1215 | resolved "http://registry.npm.taobao.org/through2/download/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" 1216 | dependencies: 1217 | readable-stream "^2.1.5" 1218 | xtend "~4.0.1" 1219 | 1220 | through@2, through@~2.3, through@~2.3.1: 1221 | version "2.3.8" 1222 | resolved "http://registry.npm.taobao.org/through/download/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" 1223 | 1224 | to-absolute-glob@^0.1.1: 1225 | version "0.1.1" 1226 | resolved "http://registry.npm.taobao.org/to-absolute-glob/download/to-absolute-glob-0.1.1.tgz#1cdfa472a9ef50c239ee66999b662ca0eb39937f" 1227 | dependencies: 1228 | extend-shallow "^2.0.1" 1229 | 1230 | tough-cookie@~2.4.3: 1231 | version "2.4.3" 1232 | resolved "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" 1233 | dependencies: 1234 | psl "^1.1.24" 1235 | punycode "^1.4.1" 1236 | 1237 | tunnel-agent@^0.6.0: 1238 | version "0.6.0" 1239 | resolved "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 1240 | dependencies: 1241 | safe-buffer "^5.0.1" 1242 | 1243 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 1244 | version "0.14.5" 1245 | resolved "http://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 1246 | 1247 | typescript@^3.0.1: 1248 | version "3.0.3" 1249 | resolved "http://registry.npm.taobao.org/typescript/download/typescript-3.0.3.tgz#4853b3e275ecdaa27f78fda46dc273a7eb7fc1c8" 1250 | 1251 | unique-stream@^2.0.2: 1252 | version "2.2.1" 1253 | resolved "http://registry.npm.taobao.org/unique-stream/download/unique-stream-2.2.1.tgz#5aa003cfbe94c5ff866c4e7d668bb1c4dbadb369" 1254 | dependencies: 1255 | json-stable-stringify "^1.0.0" 1256 | through2-filter "^2.0.0" 1257 | 1258 | url-parse@^1.4.3: 1259 | version "1.4.3" 1260 | resolved "http://registry.npm.taobao.org/url-parse/download/url-parse-1.4.3.tgz#bfaee455c889023219d757e045fa6a684ec36c15" 1261 | dependencies: 1262 | querystringify "^2.0.0" 1263 | requires-port "^1.0.0" 1264 | 1265 | util-deprecate@~1.0.1: 1266 | version "1.0.2" 1267 | resolved "http://registry.npm.taobao.org/util-deprecate/download/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1268 | 1269 | uuid@^3.3.2: 1270 | version "3.3.2" 1271 | resolved "http://registry.npm.taobao.org/uuid/download/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" 1272 | 1273 | vali-date@^1.0.0: 1274 | version "1.0.0" 1275 | resolved "http://registry.npm.taobao.org/vali-date/download/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6" 1276 | 1277 | verror@1.10.0: 1278 | version "1.10.0" 1279 | resolved "http://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 1280 | dependencies: 1281 | assert-plus "^1.0.0" 1282 | core-util-is "1.0.2" 1283 | extsprintf "^1.2.0" 1284 | 1285 | vinyl-fs@^2.0.0, vinyl-fs@^2.4.3: 1286 | version "2.4.4" 1287 | resolved "http://registry.npm.taobao.org/vinyl-fs/download/vinyl-fs-2.4.4.tgz#be6ff3270cb55dfd7d3063640de81f25d7532239" 1288 | dependencies: 1289 | duplexify "^3.2.0" 1290 | glob-stream "^5.3.2" 1291 | graceful-fs "^4.0.0" 1292 | gulp-sourcemaps "1.6.0" 1293 | is-valid-glob "^0.3.0" 1294 | lazystream "^1.0.0" 1295 | lodash.isequal "^4.0.0" 1296 | merge-stream "^1.0.0" 1297 | mkdirp "^0.5.0" 1298 | object-assign "^4.0.0" 1299 | readable-stream "^2.0.4" 1300 | strip-bom "^2.0.0" 1301 | strip-bom-stream "^1.0.0" 1302 | through2 "^2.0.0" 1303 | through2-filter "^2.0.0" 1304 | vali-date "^1.0.0" 1305 | vinyl "^1.0.0" 1306 | 1307 | vinyl-source-stream@^1.1.0: 1308 | version "1.1.2" 1309 | resolved "http://registry.npm.taobao.org/vinyl-source-stream/download/vinyl-source-stream-1.1.2.tgz#62b53a135610a896e98ca96bee3a87f008a8e780" 1310 | dependencies: 1311 | through2 "^2.0.3" 1312 | vinyl "^0.4.3" 1313 | 1314 | vinyl@^0.4.3, vinyl@~0.4.6: 1315 | version "0.4.6" 1316 | resolved "http://registry.npm.taobao.org/vinyl/download/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" 1317 | dependencies: 1318 | clone "^0.2.0" 1319 | clone-stats "^0.0.1" 1320 | 1321 | vinyl@^1.0.0, vinyl@^1.2.0: 1322 | version "1.2.0" 1323 | resolved "http://registry.npm.taobao.org/vinyl/download/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" 1324 | dependencies: 1325 | clone "^1.0.0" 1326 | clone-stats "^0.0.1" 1327 | replace-ext "0.0.1" 1328 | 1329 | vinyl@^2.0.1, vinyl@^2.0.2: 1330 | version "2.2.0" 1331 | resolved "http://registry.npm.taobao.org/vinyl/download/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" 1332 | dependencies: 1333 | clone "^2.1.1" 1334 | clone-buffer "^1.0.0" 1335 | clone-stats "^1.0.0" 1336 | cloneable-readable "^1.0.0" 1337 | remove-trailing-separator "^1.0.1" 1338 | replace-ext "^1.0.0" 1339 | 1340 | vscode-jsonrpc@^3.6.2: 1341 | version "3.6.2" 1342 | resolved "http://registry.npm.taobao.org/vscode-jsonrpc/download/vscode-jsonrpc-3.6.2.tgz#3b5eef691159a15556ecc500e9a8a0dd143470c8" 1343 | 1344 | vscode-languageclient@^5.0.1: 1345 | version "5.0.1" 1346 | resolved "http://registry.npm.taobao.org/vscode-languageclient/download/vscode-languageclient-5.0.1.tgz#492dc57cecef598457ae4107ed1dccbaa27382ed" 1347 | dependencies: 1348 | semver "^5.5.0" 1349 | vscode-languageserver-protocol "^3.10.3" 1350 | 1351 | vscode-languageserver-protocol@^3.10.3: 1352 | version "3.12.0" 1353 | resolved "http://registry.npm.taobao.org/vscode-languageserver-protocol/download/vscode-languageserver-protocol-3.12.0.tgz#5b23501292abad88f0463b01e83ff98e64a37652" 1354 | dependencies: 1355 | vscode-jsonrpc "^3.6.2" 1356 | vscode-languageserver-types "^3.12.0" 1357 | 1358 | vscode-languageserver-types@^3.12.0: 1359 | version "3.12.0" 1360 | resolved "http://registry.npm.taobao.org/vscode-languageserver-types/download/vscode-languageserver-types-3.12.0.tgz#f96051381b6a050b7175b37d6cb5d2f2eb64b944" 1361 | 1362 | vscode-languageserver@^5.0.3: 1363 | version "5.0.3" 1364 | resolved "http://registry.npm.taobao.org/vscode-languageserver/download/vscode-languageserver-5.0.3.tgz#29a4655348868223d9b3b6e385a50e77c6f4992e" 1365 | dependencies: 1366 | vscode-languageserver-protocol "^3.10.3" 1367 | vscode-uri "^1.0.5" 1368 | 1369 | vscode-uri@^1.0.5: 1370 | version "1.0.6" 1371 | resolved "http://registry.npm.taobao.org/vscode-uri/download/vscode-uri-1.0.6.tgz#6b8f141b0bbc44ad7b07e94f82f168ac7608ad4d" 1372 | 1373 | vscode@^1.1.21: 1374 | version "1.1.21" 1375 | resolved "http://registry.npm.taobao.org/vscode/download/vscode-1.1.21.tgz#1c8253d6238aefb4112d6e58cf975ad25313dafc" 1376 | dependencies: 1377 | glob "^7.1.2" 1378 | gulp-chmod "^2.0.0" 1379 | gulp-filter "^5.0.1" 1380 | gulp-gunzip "1.0.0" 1381 | gulp-remote-src-vscode "^0.5.0" 1382 | gulp-symdest "^1.1.0" 1383 | gulp-untar "^0.0.7" 1384 | gulp-vinyl-zip "^2.1.0" 1385 | mocha "^4.0.1" 1386 | request "^2.83.0" 1387 | semver "^5.4.1" 1388 | source-map-support "^0.5.0" 1389 | url-parse "^1.4.3" 1390 | vinyl-source-stream "^1.1.0" 1391 | 1392 | wrappy@1: 1393 | version "1.0.2" 1394 | resolved "http://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1395 | 1396 | "xtend@>=4.0.0 <4.1.0-0", xtend@~4.0.0, xtend@~4.0.1: 1397 | version "4.0.1" 1398 | resolved "http://registry.npm.taobao.org/xtend/download/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" 1399 | 1400 | yauzl@^2.2.1: 1401 | version "2.10.0" 1402 | resolved "http://registry.npm.taobao.org/yauzl/download/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" 1403 | dependencies: 1404 | buffer-crc32 "~0.2.3" 1405 | fd-slicer "~1.1.0" 1406 | 1407 | yazl@^2.2.1: 1408 | version "2.4.3" 1409 | resolved "http://registry.npm.taobao.org/yazl/download/yazl-2.4.3.tgz#ec26e5cc87d5601b9df8432dbdd3cd2e5173a071" 1410 | dependencies: 1411 | buffer-crc32 "~0.2.3" 1412 | --------------------------------------------------------------------------------