vscodeプラグインファーストフードのチュートリアル(7) - ゼロから完全なエンジニアリングLSPを書きます

vscodeプラグインファーストフードのチュートリアル(7) - ゼロから完全なエンジニアリングLSPを書きます

あなたには、いくつかの基本的な知識を持っていたら、私たちは、クライアントとサーバモードのLSPのプラグインを構築するために始めることができます。

ディレクトリサーバ

まず、サーバー側のコードを記述します。

package.json

マイクロソフトのSDKは私たちに詳細のほとんどは、実際には、限り、我々はそれにvscode-languageserverモジュールを参照して良いパッケージを支援してきましたので、まず、我々はpackage.jsonを記述します。

{
    "name": "lsp-demo-server",
    "description": "demo language server",
    "version": "1.0.0",
    "author": "Xulun",
    "license": "MIT",
    "engines": {
        "node": "*"
    },
    "repository": {
        "type": "git",
        "url": "[email protected]:lusinga/testlsp.git"
    },
    "dependencies": {
        "vscode-languageserver": "^4.1.3"
    },
    "scripts": {}
}

あなたはpackage.jsonを持っていたら、私たちは、installコマンドをNPM実行できるサーバーのディレクトリの下に付属のインストールによって異なります。
モジュールをインストールした後に来て以下で参照されます。

  • vscode-JSONRPC
  • vscode-languageserver
  • vscode-languageserverプロトコル
  • vscode-URI vscode-languageserver-種類

tsconfig.json

私たちが使用しているためtypescriptですが、サーバーを書くことですので、私たちは、活字体のオプションを設定するにはtsconfig.json:

{
    "compilerOptions": {
        "target": "es6",
        "module": "commonjs",
        "moduleResolution": "node",
        "sourceMap": true,
        "outDir": "out",
        "rootDir": "src",
        "lib": ["es6"]
    },
    "include": ["src"],
    "exclude": ["node_modules", ".vscode-test"]
}

server.ts

ここでは、導入によって異なりがでてくる最初の我々はとvscode-JSONRPC-languageserverをvscodeする必要があり、サーバ側のTSファイルを書き始めます。

import {
    createConnection,
    TextDocuments,
    TextDocument,
    Diagnostic,
    DiagnosticSeverity,
    ProposedFeatures,
    InitializeParams,
    DidChangeConfigurationNotification,
    CompletionItem,
    CompletionItemKind,
    TextDocumentPositionParams,
    SymbolInformation,
    WorkspaceSymbolParams,
    WorkspaceEdit,
    WorkspaceFolder
} from 'vscode-languageserver';
import { HandlerResult } from 'vscode-jsonrpc';

以下では、便利な印刷ログのために、私たちは、私が組み込まれ、その後、初期化され--saveモジュールをlog4js NPMによってlog4jsに印刷ログを使用します。

import { configure, getLogger } from "log4js";
configure({
    appenders: {
        lsp_demo: {
            type: "dateFile",
            filename: "/Users/ziyingliuziying/working/lsp_demo",
            pattern: "yyyy-MM-dd-hh.log",
            alwaysIncludePattern: true,
        },
    },
    categories: { default: { appenders: ["lsp_demo"], level: "debug" } }
});
const logger = getLogger("lsp_demo");

その後、我々は、接続を作成するためのcreateConnectionを呼び出すことができます。

let connection = createConnection(ProposedFeatures.all);

その後、我々はそれで、このような第6節で説明した処理の初期化イベントなどのイベントの数を扱うことができます。

connection.onInitialize((params: InitializeParams) => {
    let capabilities = params.capabilities;

    return {
        capabilities: {
            completionProvider: {
                resolveProvider: true
            }
        }
    };
});

3ウェイハンドシェイクの後、我々はvscodeにメッセージを表示することができます。

connection.onInitialized(() => {
    connection.window.showInformationMessage('Hello World! form server side');
});

最後に、我々は、追加するパートのコード補完のセクション5を学びました:

connection.onCompletion(
    (_textDocumentPosition: TextDocumentPositionParams): CompletionItem[] => {

        return [
            {
                label: 'TextView' + _textDocumentPosition.position.character,
                kind: CompletionItemKind.Text,
                data: 1
            },
            {
                label: 'Button' + _textDocumentPosition.position.line,
                kind: CompletionItemKind.Text,
                data: 2
            },
            {
                label: 'ListView',
                kind: CompletionItemKind.Text,
                data: 3
            }
        ];
    }
);

connection.onCompletionResolve(
    (item: CompletionItem): CompletionItem => {
        if (item.data === 1) {
            item.detail = 'TextView';
            item.documentation = 'TextView documentation';
        } else if (item.data === 2) {
            item.detail = 'Button';
            item.documentation = 'JavaScript documentation';
        } else if (item.data === 3) {
            item.detail = 'ListView';
            item.documentation = 'ListView documentation';
        }
        return item;
    }
);

クライアントのディレクトリ

これは、ここで私たちは、クライアントを開発する必要があり、サーバーの準備ができている場合でも、開発しました。

package.json

まず、package.jsonを書くvscode-languageclient、カザフスタンと混同サーバーでないライブラリvscode-languageserverに依存しています。

{
    "name": "lspdemo-client",
    "description": "demo language server client",
    "author": "Xulun",
    "license": "MIT",
    "version": "0.0.1",
    "publisher": "Xulun",
    "repository": {
        "type": "git",
        "url": "[email protected]:lusinga/testlsp.git"
    },
    "engines": {
        "vscode": "^1.33.1"
    },
    "scripts": {
        "update-vscode": "vscode-install",
        "postinstall": "vscode-install"
    },
    "dependencies": {
        "path": "^0.12.7",
        "vscode-languageclient": "^4.1.4"
    },
    "devDependencies": {
        "vscode": "^1.1.30"
    }
}

tsconfig.json

とにかく、TSは、クライアントとサーバーの比率は特に、その後、コピー何増加しませんでした。

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "outDir": "out",
        "rootDir": "src",
        "lib": ["es6"],
        "sourceMap": true
    },
    "include": ["src"],
    "exclude": ["node_modules", ".vscode-test"]
}

extension.ts

さんはextension.tsを書いてみましょう。

実際には、クライアントがサーバー未満を行う必要があり、本質的には、同様にサーバーを起動します。

    // Create the language client and start the client.
    client = new LanguageClient(
        'DemoLanguageServer',
        'Demo Language Server',
        serverOptions,
        clientOptions
    );

    // Start the client. This will also launch the server
    client.start();

以下のように定義されているサーバへのserverOptions設定パラメータ:

export type ServerOptions = 
Executable | 
{ run: Executable; debug: Executable; } | 
{ run: NodeModule; debug: NodeModule } | 
NodeModule | 
(() => Thenable<ChildProcess | StreamInfo | MessageTransports | ChildProcessInfo>);

ダイアグラムの種類に関連する次のとおりです。
ServerOptions

のは、設定を見てみましょう:

    // 服务端配置
    let serverModule = context.asAbsolutePath(
        path.join('server', 'out', 'server.js')
    );

    let serverOptions: ServerOptions = {
        module: serverModule, transport: TransportKind.ipc
    };

    // 客户端配置
    let clientOptions: LanguageClientOptions = {
        // js代码触发事情
        documentSelector: [{ scheme: 'file', language: 'js' }],
    };

Extension.ts完全なコードは次のとおりです。

import * as path from 'path';
import { workspace, ExtensionContext } from 'vscode';

import {
    LanguageClient,
    LanguageClientOptions,
    ServerOptions,
    TransportKind
} from 'vscode-languageclient';

let client: LanguageClient;

export function activate(context: ExtensionContext) {
    // 服务端配置
    let serverModule = context.asAbsolutePath(
        path.join('server', 'out', 'server.js')
    );

    let serverOptions: ServerOptions = {
        module: serverModule, transport: TransportKind.ipc
    };

    // 客户端配置
    let clientOptions: LanguageClientOptions = {
        // js代码触发事情
        documentSelector: [{ scheme: 'file', language: 'js' }],
    };

    client = new LanguageClient(
        'DemoLanguageServer',
        'Demo Language Server',
        serverOptions,
        clientOptions
    );

    // 启动客户端,同时启动语言服务器
    client.start();
}

export function deactivate(): Thenable<void> | undefined {
    if (!client) {
        return undefined;
    }
    return client.stop();
}

組立作業

すべてが強いだけのパッケージは、クライアントとサーバについての上部アセンブリを聞かせて、準備ができています。

プラグインの設定 - package.jsonを

私たちの主な関心事は、エントリポイント関数とトリガイベントであります:

    "activationEvents": [
        "onLanguage:javascript"
    ],
    "main": "./client/out/extension",

次のようにpackage.json完了します。

{
    "name": "lsp_demo_server",
    "description": "A demo language server",
    "author": "Xulun",
    "license": "MIT",
    "version": "1.0.0",
    "repository": {
        "type": "git",
        "url": "[email protected]:lusinga/testlsp.git"
    },
    "publisher": "Xulun",
    "categories": [],
    "keywords": [],
    "engines": {
        "vscode": "^1.33.1"
    },
    "activationEvents": [
        "onLanguage:javascript"
    ],
    "main": "./client/out/extension",
    "contributes": {},
    "scripts": {
        "vscode:prepublish": "cd client && npm run update-vscode && cd .. && npm run compile",
        "compile": "tsc -b",
        "watch": "tsc -b -w",
        "postinstall": "cd client && npm install && cd ../server && npm install && cd ..",
        "test": "sh ./scripts/e2e.sh"
    },
    "devDependencies": {
        "@types/mocha": "^5.2.0",
        "@types/node": "^8.0.0",
        "tslint": "^5.11.0",
        "typescript": "^3.1.3"
    }
}

アセンブリtsconfig.json

また、tsconfig.jsonの合計、参照クライアントとサーバの2つのディレクトリを必要とします:

{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "outDir": "out",
        "rootDir": "src",
        "lib": [ "es6" ],
        "sourceMap": true
    },
    "include": [
        "src"
    ],
    "exclude": [
        "node_modules",
        ".vscode-test"
    ],
    "references": [
        { "path": "./client" },
        { "path": "./server" }
    ]
}

設定vscode

以上、私たちは、クライアント、サーバ、およびすべてが完成し、そのコードを統合します。
我々はより簡単にデバッグおよび実行できるように、私たちは、.vscodeディレクトリ2つのプロファイルを作成してみましょう。

.vscode / launch.json

このドキュメントの後で、我々は実行コンフィギュレーションを持っている、それはF5によって開始することができます。

// A launch configuration that compiles the extension and then opens it inside a new window
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "extensionHost",
            "request": "launch",
            "name": "Launch Client",
            "runtimeExecutable": "${execPath}",
            "args": ["--extensionDevelopmentPath=${workspaceRoot}"],
            "outFiles": ["${workspaceRoot}/client/out/**/*.js"],
            "preLaunchTask": {
                "type": "npm",
                "script": "watch"
            }
        },
        {
            "type": "node",
            "request": "attach",
            "name": "Attach to Server",
            "port": 6009,
            "restart": true,
            "outFiles": ["${workspaceRoot}/server/out/**/*.js"]
        },
    ],
    "compounds": [
        {
            "name": "Client + Server",
            "configurations": ["Launch Client", "Attach to Server"]
        }
    ]
}

.vscode / tasks.json

NPMのコンパイルとNPMを設定すると、2つのスクリプトを見て。

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "npm",
            "script": "compile",
            "group": "build",
            "presentation": {
                "panel": "dedicated",
                "reveal": "never"
            },
            "problemMatcher": [
                "$tsc"
            ]
        },
        {
            "type": "npm",
            "script": "watch",
            "isBackground": true,
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "presentation": {
                "panel": "dedicated",
                "reveal": "never"
            },
            "problemMatcher": [
                "$tsc-watch"
            ]
        }
    ]
}

すべての準備が整った後、NPMルートディレクトリで実行するプラグインをインストールします。
Vscodeは、ビルドコマンドを実行して、このようなMAC CMD-シフト-bがあるので、彼が構築され、jsのうち、ディレクトリサーバとクライアントで生成されたマップ。
今、あなたは、F5キーを介して実行することができます。

code.aliyun.com:lusinga/testlsp.gitにおけるソースコードの本実施例。

おすすめ

転載: yq.aliyun.com/articles/704465