Setup VSCode plugin

This commit is contained in:
Geequlim
2016-12-11 22:45:31 +08:00
commit 7285be21d2
21 changed files with 2685 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
out
node_modules
server
test

28
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,28 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.1.0",
"configurations": [
{
"name": "Launch Extension",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out/src",
"preLaunchTask": "npm"
},
{
"name": "Launch Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
"stopOnEntry": false,
"sourceMaps": true,
"outDir": "${workspaceRoot}/out/test",
"preLaunchTask": "npm"
}
]
}

10
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,10 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.exclude": {
"out": false // set this to true to hide the "out" folder with the compiled JS files
},
"search.exclude": {
"out": true // set this to false to include "out" folder in search results
},
"typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
}

30
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,30 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process
// A task runner that calls a custom npm script that compiles the extension.
{
"version": "0.1.0",
// we want to run npm
"command": "npm",
// the command is a shell script
"isShellCommand": true,
// show the output window only if unrecognized errors occur.
"showOutput": "silent",
// we run the custom script "compile" as defined in package.json
"args": ["run", "compile", "--loglevel", "silent"],
// The tsc compiler is started in watching mode
"isWatching": true,
// use the standard tsc in watch mode problem matcher to find compile problems in the output.
"problemMatcher": "$tsc-watch"
}

9
.vscodeignore Normal file
View File

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

56
package.json Normal file
View File

@@ -0,0 +1,56 @@
{
"name": "godot-tools",
"displayName": "godot-tools",
"description": "\"Tools for game development with godot game engine\"",
"version": "0.0.1",
"publisher": "GodotExplorer",
"engines": {
"vscode": "^1.5.0"
},
"categories": [
"Other"
],
"activationEvents": [
"onLanguage:gdscript",
"workspaceContains:engine.cfg"
],
"main": "./out/src/extension",
"contributes": {
"commands": [{
"command": "extension.sayHello",
"title": "Hello World"
}],
"configuration": {
"type": "object",
"title": "Godot tools configuration",
"properties": {
"GDScriptServer.editorServerPort": {
"type": "number",
"default": 6996,
"description": "The server port of your EditorServer"
},
"GDScriptServer.maxNumberOfProblems": {
"type": "number",
"default": 10,
"description": "Controls the maximum number of problems produced by the server."
}
}
}
},
"scripts": {
"vscode:prepublish": "tsc -p ./",
"compile": "tsc -watch -p ./",
"postinstall": "node ./node_modules/vscode/bin/install",
"test": "node ./node_modules/vscode/bin/test"
},
"devDependencies": {
"typescript": "^2.0.3",
"vscode": "^1.0.0",
"mocha": "^2.3.3",
"@types/node": "^6.0.40",
"@types/mocha": "^2.2.32"
},
"dependencies": {
"vscode-languageclient": "^2.6.3"
}
}

16
src/extension.ts Normal file
View File

@@ -0,0 +1,16 @@
'use strict';
import * as path from 'path';
import GDScriptClient from './gdscript/client';
import { workspace, Disposable, ExtensionContext } from 'vscode';
import { LanguageClient } from 'vscode-languageclient';
let gdscript_client = null;
export function activate(context: ExtensionContext) {
gdscript_client = new GDScriptClient(context);
// Create the language client and start the client.
let disposable = new LanguageClient('GDScriptLanguage', gdscript_client.server_options, gdscript_client.client_options).start();
context.subscriptions.push(disposable);
}

37
src/gdscript/client.ts Normal file
View File

@@ -0,0 +1,37 @@
import * as path from 'path';
import * as LanguageClient from 'vscode-languageclient';
import { workspace , ExtensionContext } from 'vscode';
/**
* GDScriptClient
*/
class GDScriptClient {
public client_options: LanguageClient.LanguageClientOptions;
public server_options: LanguageClient.ServerOptions;
constructor(context: ExtensionContext) {
this.client_options = {
// Register the server for gdscript documents
documentSelector: ['gdscript'],
synchronize: {
// Synchronize the setting section 'languageServerExample' to the server
configurationSection: 'GDScriptServer',
// Notify the server about file changes to *.gd files contain in the workspace
fileEvents: workspace.createFileSystemWatcher('*.gd')
}
};
// The server is implemented in node
let serverModule = context.asAbsolutePath(path.join('server', 'server.js'));
// The debug options for the server
let debugOptions = { execArgv: ["--nolazy", "--debug=6980"] };
this.server_options = {
run : { module: serverModule, transport: LanguageClient.TransportKind.ipc },
debug: { module: serverModule, transport: LanguageClient.TransportKind.ipc, options: debugOptions }
};
}
}
export default GDScriptClient;

2
src/gdscript/server/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
out
node_modules

14
src/gdscript/server/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,14 @@
{
"version": "0.1.0",
// List of configurations. Add new configurations or edit existing ones.
"configurations": [
{
"name": "Attach",
"type": "node",
"request": "attach",
"port": 6980,
"sourceMaps": true,
"outDir": "${workspaceRoot}/../../../server"
}
]
}

View File

@@ -0,0 +1,9 @@
{
"version": "0.1.0",
"command": "npm",
"isShellCommand": true,
"showOutput": "silent",
"args": ["run", "watch"],
"isWatching": true,
"problemMatcher": "$tsc-watch"
}

View File

@@ -0,0 +1,11 @@
Copyright (c) Microsoft Corporation
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,3 @@
#README
This is a language server sample implementation in node

View File

@@ -0,0 +1,31 @@
THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
For Microsoft vscode-languageserver-node-example
This project incorporates material from the project(s) listed below (collectively, “Third Party Code”).
Microsoft is not the original author of the Third Party Code. The original copyright notice and license
under which Microsoft received such Third Party Code are set out below. This Third Party Code is licensed
to you under their original license terms set forth below. Microsoft reserves all other rights not expressly
granted, whether by implication, estoppel or otherwise.
1. DefinitelyTyped version 0.0.1 (https://github.com/borisyankov/DefinitelyTyped)
This project is licensed under the MIT license.
Copyrights are respective of each contributor listed at the beginning of each definition file.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,20 @@
{
"name": "language-server-example",
"description": "Example implementation of a language server in node.",
"version": "0.0.1",
"author": "Microsoft Corporation",
"license": "MIT",
"engines": {
"node": "*"
},
"dependencies": {
"vscode-languageserver": "^2.2.0"
},
"devDependencies": {
"typescript": "^1.8.9"
},
"scripts": {
"compile": "installServerIntoExtension ../../../ ./package.json ./tsconfig.json && tsc -p .",
"watch": "installServerIntoExtension ../../../ ./package.json ./tsconfig.json && tsc --watch -p ."
}
}

View File

@@ -0,0 +1,151 @@
'use strict';
import {
IPCMessageReader, IPCMessageWriter,
createConnection, IConnection, TextDocumentSyncKind,
TextDocuments, TextDocument, Diagnostic, DiagnosticSeverity,
InitializeParams, InitializeResult, TextDocumentPositionParams,
CompletionItem, CompletionItemKind
} from 'vscode-languageserver';
// Create a connection for the server. The connection uses Node's IPC as a transport
let connection: IConnection = createConnection(new IPCMessageReader(process), new IPCMessageWriter(process));
// Create a simple text document manager. The text document manager supports full document sync only
let documents: TextDocuments = new TextDocuments();
// Make the text document manager listen on the connection for open, change and close text document events
documents.listen(connection);
// After the server has started the client sends an initilize request. The server receives
// in the passed params the rootPath of the workspace plus the client capabilites.
let workspaceRoot: string;
connection.onInitialize((params): InitializeResult => {
workspaceRoot = params.rootPath;
return {
capabilities: {
// Tell the client that the server works in FULL text document sync mode
textDocumentSync: documents.syncKind,
// Tell the client that the server support code complete
completionProvider: {
resolveProvider: true
}
}
}
});
// The content of a text document has changed. This event is emitted
// when the text document first opened or when its content has changed.
documents.onDidChangeContent((change) => {
validateTextDocument(change.document);
});
// The settings interface describe the server relevant settings part
interface Settings {
GDScriptServer: ExampleSettings;
}
// These are the example settings we defined in the client's package.json
// file
interface ExampleSettings {
maxNumberOfProblems: number;
}
// hold the maxNumberOfProblems setting
let maxNumberOfProblems: number;
// The settings have changed. Is send on server activation
// as well.
connection.onDidChangeConfiguration((change) => {
let settings = <Settings>change.settings;
maxNumberOfProblems = settings.GDScriptServer.maxNumberOfProblems || 10;
// Revalidate any open text documents
documents.all().forEach(validateTextDocument);
});
function validateTextDocument(textDocument: TextDocument): void {
console.log(textDocument.uri);
let diagnostics: Diagnostic[] = [];
let lines = textDocument.getText().split(/\r?\n/g);
let problems = 0;
for (var i = 0; i < lines.length && problems < maxNumberOfProblems; i++) {
let line = lines[i];
let index = line.indexOf('typescript');
if (index >= 0) {
problems++;
diagnostics.push({
severity: DiagnosticSeverity.Warning,
range: {
start: { line: i, character: index},
end: { line: i, character: index + 10 }
},
message: `${line.substr(index, 10)} should be spelled TypeScript`,
source: 'ex'
});
}
}
// Send the computed diagnostics to VSCode.
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
}
connection.onDidChangeWatchedFiles((change) => {
// Monitored files have change in VSCode
connection.console.log('We recevied an file change event');
});
// This handler provides the initial list of the completion items.
connection.onCompletion((textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {
// The pass parameter contains the position of the text document in
// which code complete got requested. For the example we ignore this
// info and always provide the same completion items.
return [
{
label: 'TypeScript',
kind: CompletionItemKind.Text,
data: 1
},
{
label: 'JavaScript',
kind: CompletionItemKind.Text,
data: 2
}
]
});
// This handler resolve additional information for the item selected in
// the completion list.
connection.onCompletionResolve((item: CompletionItem): CompletionItem => {
if (item.data === 1) {
item.detail = 'TypeScript details',
item.documentation = 'TypeScript documentation'
} else if (item.data === 2) {
item.detail = 'JavaScript details',
item.documentation = 'JavaScript documentation'
}
return item;
});
/*
connection.onDidOpenTextDocument((params) => {
// A text document got opened in VSCode.
// params.uri uniquely identifies the document. For documents store on disk this is a file URI.
// params.text the initial full content of the document.
connection.console.log(`${params.uri} opened.`);
});
connection.onDidChangeTextDocument((params) => {
// The content of a text document did change in VSCode.
// params.uri uniquely identifies the document.
// params.contentChanges describe the content changes to the document.
connection.console.log(`${params.uri} changed: ${JSON.stringify(params.contentChanges)}`);
});
connection.onDidCloseTextDocument((params) => {
// A text document got closed in VSCode.
// params.uri uniquely identifies the document.
connection.console.log(`${params.uri} closed.`);
});
*/
// Listen on the connection
connection.listen();

View File

@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "../../../server"
},
"exclude": [
"node_modules"
]
}

2079
src/gdscript/server/typings/node/node.d.ts vendored Normal file

File diff suppressed because it is too large Load Diff

112
src/gdscript/server/typings/promise.d.ts vendored Normal file
View File

@@ -0,0 +1,112 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/**
* The Thenable (E.g. PromiseLike) and Promise declarions are taken from TypeScript's
* lib.core.es6.d.ts file. See above Copyright notice.
*/
/**
* Thenable is a common denominator between ES6 promises, Q, jquery.Deferred, WinJS.Promise,
* and others. This API makes no assumption about what promise libary is being used which
* enables reusing existing code without migrating to a specific promise implementation. Still,
* we recommand the use of native promises which are available in VS Code.
*/
interface Thenable<R> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled?: (value: R) => TResult | Thenable<TResult>, onrejected?: (reason: any) => TResult | Thenable<TResult>): Thenable<TResult>;
then<TResult>(onfulfilled?: (value: R) => TResult | Thenable<TResult>, onrejected?: (reason: any) => void): Thenable<TResult>;
}
/**
* Represents the completion of an asynchronous operation
*/
interface Promise<T> extends Thenable<T> {
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of which ever callback is executed.
*/
then<TResult>(onfulfilled?: (value: T) => TResult | Thenable<TResult>, onrejected?: (reason: any) => TResult | Thenable<TResult>): Promise<TResult>;
then<TResult>(onfulfilled?: (value: T) => TResult | Thenable<TResult>, onrejected?: (reason: any) => void): Promise<TResult>;
/**
* Attaches a callback for only the rejection of the Promise.
* @param onrejected The callback to execute when the Promise is rejected.
* @returns A Promise for the completion of the callback.
*/
catch(onrejected?: (reason: any) => T | Thenable<T>): Promise<T>;
}
interface PromiseConstructor {
/**
* Creates a new Promise.
* @param executor A callback used to initialize the promise. This callback is passed two arguments:
* a resolve callback used resolve the promise with a value or the result of another promise,
* and a reject callback used to reject the promise with a provided reason or error.
*/
new <T>(executor: (resolve: (value?: T | Thenable<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T>(values: Array<T | Thenable<T>>): Promise<T[]>;
/**
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
* or rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
race<T>(values: Array<T | Thenable<T>>): Promise<T>;
/**
* Creates a new rejected promise for the provided reason.
* @param reason The reason the promise was rejected.
* @returns A new rejected Promise.
*/
reject(reason: any): Promise<void>;
/**
* Creates a new rejected promise for the provided reason.
* @param reason The reason the promise was rejected.
* @returns A new rejected Promise.
*/
reject<T>(reason: any): Promise<T>;
/**
* Creates a new resolved promise for the provided value.
* @param value A promise.
* @returns A promise whose internal state matches the provided promise.
*/
resolve<T>(value: T | Thenable<T>): Promise<T>;
/**
* Creates a new resolved promise .
* @returns A resolved promise.
*/
resolve(): Promise<void>;
}
declare var Promise: PromiseConstructor;

18
tsconfig.json Normal file
View File

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

View File

@@ -0,0 +1,33 @@
# Welcome to your first VS Code Extension
## What's in the folder
* This folder contains all of the files necessary for your extension
* `package.json` - this is the manifest file in which you declare your extension and command.
The sample plugin registers a command and defines its title and command name. With this information
VS Code can show the command in the command palette. It doesnt yet need to load the plugin.
* `src/extension.ts` - this is the main file where you will provide the implementation of your command.
The file exports one function, `activate`, which is called the very first time your extension is
activated (in this case by executing the command). Inside the `activate` function we call `registerCommand`.
We pass the function containing the implementation of the command as the second parameter to
`registerCommand`.
## Get up and running straight away
* press `F5` to open a new window with your extension loaded
* run your command from the command palette by pressing (`Ctrl+Shift+P` or `Cmd+Shift+P` on Mac) and typing `Hello World`
* set breakpoints in your code inside `src/extension.ts` to debug your extension
* find output from your extension in the debug console
## Make changes
* you can relaunch the extension from the debug toolbar after changing code in `src/extension.ts`
* you can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes
## Explore the API
* you can open the full set of our API when you open the file `node_modules/vscode/vscode.d.ts`
## Run tests
* open the debug viewlet (`Ctrl+Shift+D` or `Cmd+Shift+D` on Mac) and from the launch configuration dropdown pick `Launch Tests`
* press `F5` to run the tests in a new window with your extension loaded
* see the output of the test result in the debug console
* make changes to `test/extension.test.ts` or create new test files inside the `test` folder
* by convention, the test runner will only consider files matching the name pattern `**.test.ts`
* you can create folders inside the `test` folder to structure your tests any way you want