mirror of
https://github.com/jlengrand/elm-language-client-vscode.git
synced 2026-03-10 00:01:23 +00:00
Initial commit
This commit is contained in:
3
.gitattributes
vendored
Normal file
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
* text=auto
|
||||
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
out
|
||||
node_modules
|
||||
client/server
|
||||
.vscode-test
|
||||
58
.vscode/launch.json
vendored
Normal file
58
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// 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}"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/client/out/**/*.js"
|
||||
],
|
||||
"preLaunchTask": "npm: watch:client"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"name": "Attach to Server",
|
||||
"address": "localhost",
|
||||
"protocol": "inspector",
|
||||
"port": 6009,
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/server/out/**/*.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Language Server E2E Test",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--extensionDevelopmentPath=${workspaceRoot}",
|
||||
"--extensionTestsPath=${workspaceRoot}/client/out/test",
|
||||
"${workspaceRoot}/client/testFixture"
|
||||
],
|
||||
"stopOnEntry": false,
|
||||
"sourceMaps": true,
|
||||
"outFiles": [
|
||||
"${workspaceRoot}/client/out/test/**/*.js"
|
||||
]
|
||||
}
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Client + Server",
|
||||
"configurations": [
|
||||
"Launch Client",
|
||||
"Attach to Server"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
12
.vscode/settings.json
vendored
Normal file
12
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"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",
|
||||
"typescript.tsc.autoDetect": "off",
|
||||
"npm.exclude": ["**/client", "**/server"],
|
||||
"npm.enableScriptExplorer": true
|
||||
}
|
||||
75
.vscode/tasks.json
vendored
Normal file
75
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "compile",
|
||||
"dependsOn": [
|
||||
"compile:client",
|
||||
"compile:server"
|
||||
],
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "compile:client",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
"reveal": "never"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "compile:server",
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
"reveal": "never"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"dependsOn": [
|
||||
"npm: watch:client",
|
||||
"npm: watch:server"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch:client",
|
||||
"isBackground": true,
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
"reveal": "never"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "npm",
|
||||
"script": "watch:server",
|
||||
"isBackground": true,
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"panel": "dedicated",
|
||||
"reveal": "never"
|
||||
},
|
||||
"problemMatcher": [
|
||||
"$tsc-watch"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
13
.vscodeignore
Normal file
13
.vscodeignore
Normal file
@@ -0,0 +1,13 @@
|
||||
.vscode/**
|
||||
**/*.ts
|
||||
**/*.map
|
||||
.gitignore
|
||||
**/tsconfig.json
|
||||
**/tsconfig.base.json
|
||||
contributing.md
|
||||
.travis.yml
|
||||
client/node_modules/**
|
||||
!client/node_modules/vscode-jsonrpc/**
|
||||
!client/node_modules/vscode-languageclient/**
|
||||
!client/node_modules/vscode-languageserver-protocol/**
|
||||
!client/node_modules/vscode-languageserver-types/**
|
||||
7
CHANGELOG.md
Normal file
7
CHANGELOG.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Change Log
|
||||
All notable changes to the "elm-language-server" extension will be documented in this file.
|
||||
|
||||
Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.
|
||||
|
||||
## [Unreleased]
|
||||
- Initial release
|
||||
17
License.txt
Normal file
17
License.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
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.
|
||||
38
README.md
Normal file
38
README.md
Normal file
@@ -0,0 +1,38 @@
|
||||
# LSP Example
|
||||
|
||||
Heavily documented sample code for https://code.visualstudio.com/docs/extensions/example-language-server.
|
||||
|
||||
## Functionality
|
||||
|
||||
This Language Server works for plain text file. It has the following language features:
|
||||
- Completions
|
||||
- Diagnostics regenerated on each file change or configuration change
|
||||
|
||||
It also includes an End-to-End test.
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── client // Language Client
|
||||
│ ├── src
|
||||
│ │ ├── test // End to End tests for Language Client / Server
|
||||
│ │ └── extension.ts // Language Client entry point
|
||||
├── package.json // The extension manifest.
|
||||
└── server // Language Server
|
||||
└── src
|
||||
└── server.ts // Language Server entry point
|
||||
```
|
||||
|
||||
## Compile and Run
|
||||
|
||||
- Run `npm install` in this folder. This installs all necessary npm modules in both the client and server folder
|
||||
- Open VS Code on this folder.
|
||||
- Press Ctrl+Shift+B to compile the client and server.
|
||||
- Switch to the Debug viewlet.
|
||||
- Select `Launch Client` from the drop down.
|
||||
- Run the lauch config.
|
||||
- If you want to debug the server as well use the launch configuration `Attach to Server`
|
||||
- In the [Extension Development Host] instance of VSCode, open a document in 'plain text' language mode.
|
||||
- Type `j` or `t` to see `Javascript` and `TypeScript` completion.
|
||||
- Enter text content such as `AAA aaa BBB`. The extension will emit diagnostics for all words in all-uppercase.
|
||||
62
client/elm.configuration.json
Normal file
62
client/elm.configuration.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"comments": {
|
||||
"lineComment": "--",
|
||||
"blockComment": [
|
||||
"{-",
|
||||
"-}"
|
||||
]
|
||||
},
|
||||
"brackets": [
|
||||
[
|
||||
"{",
|
||||
"}"
|
||||
],
|
||||
[
|
||||
"[",
|
||||
"]"
|
||||
],
|
||||
[
|
||||
"(",
|
||||
")"
|
||||
]
|
||||
],
|
||||
"surroundingPairs": [
|
||||
[
|
||||
"{",
|
||||
"}"
|
||||
],
|
||||
[
|
||||
"[",
|
||||
"]"
|
||||
],
|
||||
[
|
||||
"(",
|
||||
")"
|
||||
],
|
||||
[
|
||||
"\"",
|
||||
"\""
|
||||
]
|
||||
],
|
||||
"autoClosingPairs": [
|
||||
[
|
||||
"(",
|
||||
")"
|
||||
],
|
||||
[
|
||||
"{",
|
||||
"}"
|
||||
],
|
||||
[
|
||||
"[",
|
||||
"]"
|
||||
],
|
||||
[
|
||||
"\"",
|
||||
"\""
|
||||
]
|
||||
],
|
||||
"folding": {
|
||||
"offSide": true
|
||||
}
|
||||
}
|
||||
1795
client/package-lock.json
generated
Normal file
1795
client/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
client/package.json
Normal file
23
client/package.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "elm-language-server-client",
|
||||
"description": "VSCode client for the elm language server",
|
||||
"author": "Kolja Lampe",
|
||||
"license": "MIT",
|
||||
"publisher": "Kolja Lampe",
|
||||
"version": "0.0.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/razzeee/elm-language-server"
|
||||
},
|
||||
"engines": {
|
||||
"vscode": "^1.23.0"
|
||||
},
|
||||
"scripts": {
|
||||
"update-vscode": "node ./node_modules/vscode/bin/install",
|
||||
"postinstall": "node ./node_modules/vscode/bin/install"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode": "^1.1.18",
|
||||
"vscode-languageclient": "^4.2.1"
|
||||
}
|
||||
}
|
||||
62
client/src/extension.ts
Normal file
62
client/src/extension.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
'use strict';
|
||||
|
||||
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) {
|
||||
// The server is implemented in node
|
||||
let serverModule = context.asAbsolutePath(
|
||||
path.join('server', 'out', 'server.js')
|
||||
);
|
||||
// The debug options for the server
|
||||
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
|
||||
let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
|
||||
|
||||
// If the extension is launched in debug mode then the debug server options are used
|
||||
// Otherwise the run options are used
|
||||
let serverOptions: ServerOptions = {
|
||||
run: { module: serverModule, transport: TransportKind.ipc },
|
||||
debug: {
|
||||
module: serverModule,
|
||||
transport: TransportKind.ipc,
|
||||
options: debugOptions
|
||||
}
|
||||
};
|
||||
|
||||
// Options to control the language client
|
||||
let clientOptions: LanguageClientOptions = {
|
||||
// Register the server for plain text documents
|
||||
documentSelector: [{ scheme: 'file', language: 'elm' }],
|
||||
synchronize: {
|
||||
// Notify the server about file changes to '.clientrc files contained in the workspace
|
||||
fileEvents: workspace.createFileSystemWatcher('**/.clientrc')
|
||||
}
|
||||
};
|
||||
|
||||
// Create the language client and start the client.
|
||||
client = new LanguageClient(
|
||||
'elmLanguageServer',
|
||||
'ELM Language Server',
|
||||
serverOptions,
|
||||
clientOptions
|
||||
);
|
||||
|
||||
// Start the client. This will also launch the server
|
||||
client.start();
|
||||
}
|
||||
|
||||
export function deactivate(): Thenable<void> {
|
||||
if (!client) {
|
||||
return undefined;
|
||||
}
|
||||
return client.stop();
|
||||
}
|
||||
44
client/src/test/completion.test.ts
Normal file
44
client/src/test/completion.test.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as assert from 'assert';
|
||||
import { getDocUri, activate } from './helper';
|
||||
|
||||
describe('Should do completion', () => {
|
||||
const docUri = getDocUri('completion.txt');
|
||||
|
||||
it('Completes JS/TS in txt file', async () => {
|
||||
await testCompletion(docUri, new vscode.Position(0, 0), {
|
||||
items: [
|
||||
{ label: 'JavaScript', kind: vscode.CompletionItemKind.Text },
|
||||
{ label: 'TypeScript', kind: vscode.CompletionItemKind.Text }
|
||||
]
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function testCompletion(
|
||||
docUri: vscode.Uri,
|
||||
position: vscode.Position,
|
||||
expectedCompletionList: vscode.CompletionList
|
||||
) {
|
||||
await activate(docUri);
|
||||
|
||||
// Executing the command `vscode.executeCompletionItemProvider` to simulate triggering completion
|
||||
const actualCompletionList = (await vscode.commands.executeCommand(
|
||||
'vscode.executeCompletionItemProvider',
|
||||
docUri,
|
||||
position
|
||||
)) as vscode.CompletionList;
|
||||
|
||||
assert.equal(actualCompletionList.items.length, expectedCompletionList.items.length);
|
||||
expectedCompletionList.items.forEach((expectedItem, i) => {
|
||||
const actualItem = actualCompletionList.items[i];
|
||||
assert.equal(actualItem.label, expectedItem.label);
|
||||
assert.equal(actualItem.kind, expectedItem.kind);
|
||||
});
|
||||
}
|
||||
42
client/src/test/diagnostics.test.ts
Normal file
42
client/src/test/diagnostics.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode'
|
||||
import * as assert from 'assert'
|
||||
import { getDocUri, activate } from './helper'
|
||||
|
||||
describe('Should get diagnostics', () => {
|
||||
const docUri = getDocUri('diagnostics.txt')
|
||||
|
||||
it('Diagnoses uppercase texts', async () => {
|
||||
await testDiagnostics(docUri, [
|
||||
{ message: 'ANY is all uppercase.', range: toRange(0, 0, 0, 3), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' },
|
||||
{ message: 'ANY is all uppercase.', range: toRange(0, 14, 0, 17), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' },
|
||||
{ message: 'OS is all uppercase.', range: toRange(0, 18, 0, 20), severity: vscode.DiagnosticSeverity.Warning, source: 'ex' }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
function toRange(sLine: number, sChar: number, eLine: number, eChar: number) {
|
||||
const start = new vscode.Position(sLine, sChar)
|
||||
const end = new vscode.Position(eLine, eChar)
|
||||
return new vscode.Range(start, end)
|
||||
}
|
||||
|
||||
async function testDiagnostics(docUri: vscode.Uri, expectedDiagnostics: vscode.Diagnostic[]) {
|
||||
await activate(docUri)
|
||||
|
||||
const actualDiagnostics = vscode.languages.getDiagnostics(docUri);
|
||||
|
||||
assert.equal(actualDiagnostics.length, expectedDiagnostics.length);
|
||||
|
||||
expectedDiagnostics.forEach((expectedDiagnostic, i) => {
|
||||
const actualDiagnostic = actualDiagnostics[i]
|
||||
assert.equal(actualDiagnostic.message, expectedDiagnostic.message)
|
||||
assert.deepEqual(actualDiagnostic.range, expectedDiagnostic.range)
|
||||
assert.equal(actualDiagnostic.severity, expectedDiagnostic.severity)
|
||||
})
|
||||
}
|
||||
48
client/src/test/helper.ts
Normal file
48
client/src/test/helper.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as vscode from 'vscode';
|
||||
import * as path from 'path';
|
||||
|
||||
export let doc: vscode.TextDocument;
|
||||
export let editor: vscode.TextEditor;
|
||||
export let documentEol: string;
|
||||
export let platformEol: string;
|
||||
|
||||
/**
|
||||
* Activates the vscode.lsp-sample extension
|
||||
*/
|
||||
export async function activate(docUri: vscode.Uri) {
|
||||
// The extensionId is `publisher.name` from package.json
|
||||
const ext = vscode.extensions.getExtension('vscode.lsp-sample');
|
||||
await ext.activate();
|
||||
try {
|
||||
doc = await vscode.workspace.openTextDocument(docUri);
|
||||
editor = await vscode.window.showTextDocument(doc);
|
||||
await sleep(2000); // Wait for server activation
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
async function sleep(ms: number) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export const getDocPath = (p: string) => {
|
||||
return path.resolve(__dirname, '../../testFixture', p);
|
||||
};
|
||||
export const getDocUri = (p: string) => {
|
||||
return vscode.Uri.file(getDocPath(p));
|
||||
};
|
||||
|
||||
export async function setTestContent(content: string): Promise<boolean> {
|
||||
const all = new vscode.Range(
|
||||
doc.positionAt(0),
|
||||
doc.positionAt(doc.getText().length)
|
||||
);
|
||||
return editor.edit(eb => eb.replace(all, content));
|
||||
}
|
||||
15
client/src/test/index.ts
Normal file
15
client/src/test/index.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
* ------------------------------------------------------------------------------------------ */
|
||||
'use strict';
|
||||
|
||||
import * as testRunner from 'vscode/lib/testrunner';
|
||||
|
||||
testRunner.configure({
|
||||
ui: 'bdd',
|
||||
useColors: true,
|
||||
timeout: 100000
|
||||
});
|
||||
|
||||
module.exports = testRunner;
|
||||
0
client/testFixture/completion.txt
Normal file
0
client/testFixture/completion.txt
Normal file
1
client/testFixture/diagnostics.txt
Normal file
1
client/testFixture/diagnostics.txt
Normal file
@@ -0,0 +1 @@
|
||||
ANY browsers, ANY OS.
|
||||
17
client/tsconfig.json
Normal file
17
client/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"outDir": "out",
|
||||
"rootDir": "src",
|
||||
"lib": [ "es6" ],
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
30
language-configuration.json
Normal file
30
language-configuration.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"comments": {
|
||||
// symbol used for single line comment. Remove this entry if your language does not support line comments
|
||||
"lineComment": "//",
|
||||
// symbols used for start and end a block comment. Remove this entry if your language does not support block comments
|
||||
"blockComment": [ "/*", "*/" ]
|
||||
},
|
||||
// symbols used as brackets
|
||||
"brackets": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"]
|
||||
],
|
||||
// symbols that are auto closed when typing
|
||||
"autoClosingPairs": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["\"", "\""],
|
||||
["'", "'"]
|
||||
],
|
||||
// symbols that that can be used to surround a selection
|
||||
"surroundingPairs": [
|
||||
["{", "}"],
|
||||
["[", "]"],
|
||||
["(", ")"],
|
||||
["\"", "\""],
|
||||
["'", "'"]
|
||||
]
|
||||
}
|
||||
26
package-lock.json
generated
Normal file
26
package-lock.json
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "elm-language-server",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/mocha": {
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.4.tgz",
|
||||
"integrity": "sha512-XMHApnKWI0jvXU5gLcSTsRjJBpSzP0BG+2oGv98JFyS4a5R0tRy0oshHBRndb3BuHb9AwDKaUL8Ja7GfUvsG4g==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "8.10.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.21.tgz",
|
||||
"integrity": "sha512-87XkD9qDXm8fIax+5y7drx84cXsu34ZZqfB7Cial3Q/2lxSoJ/+DRaWckkCbxP41wFSIrrb939VhzaNxj4eY1w==",
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "2.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.8.3.tgz",
|
||||
"integrity": "sha512-K7g15Bb6Ra4lKf7Iq2l/I5/En+hLIHmxWZGq3D4DIRNFxMNV6j2SHSvDOqs2tGd4UvD/fJvrwopzQXjLrT7Itw==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
78
package.json
Normal file
78
package.json
Normal file
@@ -0,0 +1,78 @@
|
||||
{
|
||||
"name": "elm-language-server",
|
||||
"displayName": "Elm",
|
||||
"description": "A language server for Elm",
|
||||
"author": "Kolja Lampe",
|
||||
"license": "MIT",
|
||||
"version": "1.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Microsoft/vscode-extension-samples"
|
||||
},
|
||||
"publisher": "vscode",
|
||||
"categories": [],
|
||||
"keywords": [
|
||||
"multi-root ready"
|
||||
],
|
||||
"engines": {
|
||||
"vscode": "^1.25.0"
|
||||
},
|
||||
"activationEvents": [
|
||||
"onLanguage:plaintext"
|
||||
],
|
||||
"main": "./client/out/extension",
|
||||
"contributes": {
|
||||
"languages": [
|
||||
{
|
||||
"id": "elm",
|
||||
"aliases": [
|
||||
"Elm",
|
||||
"elm"
|
||||
],
|
||||
"extensions": [
|
||||
".elm"
|
||||
],
|
||||
"configuration": "./language-configuration.json"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
{
|
||||
"language": "elm",
|
||||
"scopeName": "source.elm",
|
||||
"path": "./syntaxes/elm.tmLanguage"
|
||||
}
|
||||
],
|
||||
"configuration": {
|
||||
"type": "object",
|
||||
"title": "Example configuration",
|
||||
"properties": {
|
||||
"languageServerExample.trace.server": {
|
||||
"scope": "window",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"off",
|
||||
"messages",
|
||||
"verbose"
|
||||
],
|
||||
"default": "off",
|
||||
"description": "Traces the communication between VS Code and the language server."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"vscode:prepublish": "cd client && npm run update-vscode && cd .. && npm run compile",
|
||||
"compile:client": "tsc -p ./client/tsconfig.json",
|
||||
"compile:server": "tsc -p ./server/tsconfig.json",
|
||||
"watch:client": "tsc -w -p ./client/tsconfig.json",
|
||||
"watch:server": "tsc -w -p ./server/tsconfig.json",
|
||||
"compile": "npm run compile:client && npm run compile:server",
|
||||
"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",
|
||||
"typescript": "2.8.3"
|
||||
}
|
||||
}
|
||||
6
scripts/e2e.sh
Normal file
6
scripts/e2e.sh
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
export CODE_TESTS_PATH="$(pwd)/client/out/test"
|
||||
export CODE_TESTS_WORKSPACE="$(pwd)/client/testFixture"
|
||||
|
||||
node "$(pwd)/client/node_modules/vscode/bin/test"
|
||||
131
server/package-lock.json
generated
Normal file
131
server/package-lock.json
generated
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"name": "elm-language-server",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"cross-spawn": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.0.tgz",
|
||||
"integrity": "sha1-glR3SrR4a4xbPPTfumbOVjkywlI=",
|
||||
"requires": {
|
||||
"lru-cache": "^4.0.1",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"find-elm-dependencies": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/find-elm-dependencies/-/find-elm-dependencies-1.0.2.tgz",
|
||||
"integrity": "sha512-gnvu2zAKFEHd76zV/JkRvof7HNyM2X8yW5vflCfWbXeo9hmXMndz/SrEsTQFSXXgNqf0AdjhQSRPnG8JYR92oQ==",
|
||||
"requires": {
|
||||
"firstline": "1.2.0",
|
||||
"lodash": "4.14.2"
|
||||
}
|
||||
},
|
||||
"firstline": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/firstline/-/firstline-1.2.0.tgz",
|
||||
"integrity": "sha1-yfSIbn9/vwr8EtcZQdzgaxkq6gU="
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.14.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.14.2.tgz",
|
||||
"integrity": "sha1-u8zOY3OkAPv9CoxnykL20e9BZDI="
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz",
|
||||
"integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==",
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"node-elm-compiler": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/node-elm-compiler/-/node-elm-compiler-4.5.0.tgz",
|
||||
"integrity": "sha512-XlyiHxqBizqEHaYj4UaO5/qmxeh1Ir/M02RLKsIgHBR7Z8snwoXfdpVntlfF64mcAGkuA1KY0CJsqk0IpAfyLQ==",
|
||||
"requires": {
|
||||
"cross-spawn": "4.0.0",
|
||||
"find-elm-dependencies": "1.0.2",
|
||||
"lodash": "4.14.2",
|
||||
"temp": "^0.8.3"
|
||||
}
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz",
|
||||
"integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI="
|
||||
},
|
||||
"temp": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz",
|
||||
"integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=",
|
||||
"requires": {
|
||||
"os-tmpdir": "^1.0.0",
|
||||
"rimraf": "~2.2.6"
|
||||
}
|
||||
},
|
||||
"vscode-jsonrpc": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.6.2.tgz",
|
||||
"integrity": "sha512-T24Jb5V48e4VgYliUXMnZ379ItbrXgOimweKaJshD84z+8q7ZOZjJan0MeDe+Ugb+uqERDVV8SBmemaGMSMugA=="
|
||||
},
|
||||
"vscode-languageserver": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-4.2.1.tgz",
|
||||
"integrity": "sha512-5WAxaK1nEpe52ZaWNMqmd6rO5CIE72J/7UkGKPUTdGa0l0haWHS69tpRz+LetBlgTpP7PYacl4xhDaLZv82a+g==",
|
||||
"requires": {
|
||||
"vscode-languageserver-protocol": "^3.8.1",
|
||||
"vscode-uri": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"vscode-languageserver-protocol": {
|
||||
"version": "3.8.1",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.8.1.tgz",
|
||||
"integrity": "sha512-KdeetvQ2JavRiuE9afNrV5+xJZocj7NGPQwH4kpSFw5cp+0wijv87qgXfSEvmwPUaknhMBoSuSrSIG/LRrzWJQ==",
|
||||
"requires": {
|
||||
"vscode-jsonrpc": "^3.6.2",
|
||||
"vscode-languageserver-types": "^3.8.1"
|
||||
}
|
||||
},
|
||||
"vscode-languageserver-types": {
|
||||
"version": "3.8.2",
|
||||
"resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.8.2.tgz",
|
||||
"integrity": "sha512-2RMkyt1O1czGPCnkjKZWSio2D8oh3XlQ4zi4W2xL8q2Dvi4hB3/DEt+wYyzo4hmE2ZFP0RB8PXyzHyed7p1hbw=="
|
||||
},
|
||||
"vscode-uri": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.5.tgz",
|
||||
"integrity": "sha1-O4majvccN/MFTXm9vdoxx7828g0="
|
||||
},
|
||||
"which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
}
|
||||
}
|
||||
}
|
||||
21
server/package.json
Normal file
21
server/package.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "elm-language-server",
|
||||
"description": "Implementation of a elm language server in node.",
|
||||
"version": "1.0.0",
|
||||
"author": "Kolja Lampe",
|
||||
"license": "MIT",
|
||||
"publisher": "Kolja Lampe",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/razzeee/elm-language-server"
|
||||
},
|
||||
"dependencies": {
|
||||
"vscode-languageserver": "^4.2.1",
|
||||
"node-elm-compiler": "^4.5.0",
|
||||
"vscode-uri": "^1.0.5"
|
||||
},
|
||||
"scripts": {}
|
||||
}
|
||||
210
server/src/server.ts
Normal file
210
server/src/server.ts
Normal file
@@ -0,0 +1,210 @@
|
||||
'use strict';
|
||||
import * as cp from 'child_process';
|
||||
import Uri from 'vscode-uri'
|
||||
const Compiler = require('node-elm-compiler');
|
||||
import {
|
||||
createConnection,
|
||||
TextDocuments,
|
||||
TextDocument,
|
||||
Diagnostic,
|
||||
DiagnosticSeverity,
|
||||
ProposedFeatures,
|
||||
InitializeParams,
|
||||
DidChangeConfigurationNotification,
|
||||
CompletionItem,
|
||||
CompletionItemKind,
|
||||
TextDocumentPositionParams,
|
||||
Range,
|
||||
Position,
|
||||
TextEdit
|
||||
} from 'vscode-languageserver';
|
||||
|
||||
// Create a connection for the server. The connection uses Node's IPC as a transport.
|
||||
// Also include all preview / proposed LSP features.
|
||||
let connection = createConnection(ProposedFeatures.all);
|
||||
|
||||
// Create a simple text document manager. The text document manager
|
||||
// supports full document sync only
|
||||
let documents: TextDocuments = new TextDocuments();
|
||||
|
||||
let hasConfigurationCapability: boolean = false;
|
||||
let hasWorkspaceFolderCapability: boolean = false;
|
||||
|
||||
connection.onInitialize((params: InitializeParams) => {
|
||||
let capabilities = params.capabilities;
|
||||
|
||||
// Does the client support the `workspace/configuration` request?
|
||||
// If not, we will fall back using global settings
|
||||
hasConfigurationCapability =
|
||||
capabilities.workspace && !!capabilities.workspace.configuration;
|
||||
hasWorkspaceFolderCapability =
|
||||
capabilities.workspace && !!capabilities.workspace.workspaceFolders;
|
||||
|
||||
return {
|
||||
capabilities: {
|
||||
textDocumentSync: documents.syncKind,
|
||||
// Tell the client that the server supports code completion
|
||||
completionProvider: {
|
||||
resolveProvider: true
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
connection.onInitialized(() => {
|
||||
if (hasConfigurationCapability) {
|
||||
// Register for all configuration changes.
|
||||
connection.client.register(
|
||||
DidChangeConfigurationNotification.type,
|
||||
undefined
|
||||
);
|
||||
}
|
||||
if (hasWorkspaceFolderCapability) {
|
||||
connection.workspace.onDidChangeWorkspaceFolders(_event => {
|
||||
connection.console.log('Workspace folder change event received.');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
documents.onDidOpen(params => {
|
||||
validateTextDocument(params.document);
|
||||
});
|
||||
|
||||
documents.onDidSave(params => {
|
||||
validateTextDocument(params.document);
|
||||
});
|
||||
|
||||
async function validateTextDocument(textDocument: TextDocument): Promise<void> {
|
||||
connection.console.log('Validate text');
|
||||
let uri = Uri.parse(textDocument.uri);
|
||||
|
||||
let diagnostics: Diagnostic[] = []
|
||||
try {
|
||||
await Compiler.compileToString(uri.fsPath, { report: 'json' })
|
||||
|
||||
} catch (err) {
|
||||
const issues = JSON.parse(err.message.split('\n')[1]);
|
||||
const byFile = issues.reduce((acc: any, issue: any) => {
|
||||
if (acc[issue.file]) {
|
||||
acc[issue.file].push(issue);
|
||||
} else {
|
||||
acc[issue.file] = [issue];
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
Object.keys(byFile).forEach((file: string) => {
|
||||
byFile[file].map((issue: any) => {
|
||||
diagnostics.push( {
|
||||
severity: DiagnosticSeverity.Error,
|
||||
source: "Elm",
|
||||
message: issue.details,
|
||||
range: {
|
||||
start: {
|
||||
line: issue.region.start.line - 1,
|
||||
character: issue.region.start.column - 1,
|
||||
},
|
||||
end: {
|
||||
line: issue.region.end.line - 1,
|
||||
character: issue.region.end.column - 1,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
finally {
|
||||
connection.sendDiagnostics({
|
||||
uri: textDocument.uri,
|
||||
diagnostics: diagnostics,
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
connection.onDidChangeWatchedFiles(_change => {
|
||||
// Monitored files have change in VSCode
|
||||
connection.console.log('We received 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.onDocumentFormatting(params => {
|
||||
const document = documents.get(params.textDocument.uri);
|
||||
const text = document.getText();
|
||||
|
||||
const wholeDocument = Range.create(
|
||||
Position.create(0, 0),
|
||||
document.positionAt(text.length - 1),
|
||||
);
|
||||
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
const cmd = cp.exec('elm-format --stdin', (err, stdout) => {
|
||||
err ? reject(err) : resolve(stdout);
|
||||
});
|
||||
|
||||
cmd.stdin.write(text);
|
||||
cmd.stdin.end();
|
||||
})
|
||||
.then(formattedText => {
|
||||
return [TextEdit.replace(wholeDocument, formattedText)];
|
||||
})
|
||||
.catch(_err => {
|
||||
// if ((<string>err.message).indexOf('SYNTAX PROBLEM') >= 0) {
|
||||
// return new LServer.ResponseError(
|
||||
// LServer.ErrorCodes.ParseError,
|
||||
// 'Running elm-format failed. Check the file for syntax errors.',
|
||||
// );
|
||||
// } else {
|
||||
// return new LServer.ResponseError(
|
||||
// LServer.ErrorCodes.InternalError,
|
||||
// 'Running elm-format failed. Install from ' +
|
||||
// "https://github.com/avh4/elm-format and make sure it's on your path",
|
||||
// );
|
||||
// }
|
||||
return [];
|
||||
});
|
||||
});
|
||||
|
||||
// Make the text document manager listen on the connection
|
||||
// for open, change and close text document events
|
||||
documents.listen(connection);
|
||||
|
||||
// Listen on the connection
|
||||
connection.listen();
|
||||
18
server/tsconfig.json
Normal file
18
server/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": "../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"outDir": "out",
|
||||
"rootDir": "src",
|
||||
"lib": [ "es6" ]
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
602
syntaxes/elm.tmLanguage
Normal file
602
syntaxes/elm.tmLanguage
Normal file
@@ -0,0 +1,602 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>fileTypes</key>
|
||||
<array>
|
||||
<string>elm</string>
|
||||
</array>
|
||||
<key>name</key>
|
||||
<string>Elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.entity.elm</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.entity.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(`)[a-zA-Z_']*?(`)</string>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.function.infix.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\(\)</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.unit.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>^\b((effect|port)\s+)?(module)\s+</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
<key>3</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>$|;</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>meta.declaration.module.elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#module_name</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(where)\s*\{</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>\}</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#type_signature</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(exposing)</string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#module_exports</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(where)</string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>[a-z]+</string>
|
||||
<key>name</key>
|
||||
<string>invalid</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>^\b(import)\s+((open)\s+)?</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
<key>3</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>invalid</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>($|;)</string>
|
||||
<key>name</key>
|
||||
<string>meta.import.elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(as|exposing)</string>
|
||||
<key>name</key>
|
||||
<string>keyword.import.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#module_name</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#module_exports</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>(\[)(glsl)(\|)</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>support.function.prelude.elm</string>
|
||||
</dict>
|
||||
<key>3</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>(\|\])</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>entity.glsl.elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>source.glsl</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(type alias|type|case|of|let|in|as)\s+</string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b(if|then|else)\s+</string>
|
||||
<key>name</key>
|
||||
<string>keyword.control.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>Floats are always decimal</string>
|
||||
<key>match</key>
|
||||
<string>\b([0-9]+\.[0-9]+([eE][+-]?[0-9]+)?|[0-9]+[eE][+-]?[0-9]+)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.float.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b([0-9]+)\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.numeric.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>"""</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>"""</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.double.elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\'\&])</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\^[A-Z@\[\]\\\^_]</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.control.elm</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>"</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>"</string>
|
||||
<key>endCaptures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>name</key>
|
||||
<string>string.quoted.double.elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\\(NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS|US|SP|DEL|[abfnrtv\\\"'\&])</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\^[A-Z@\[\]\\\^_]</string>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.control.elm</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.begin.elm</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>constant.character.escape.elm</string>
|
||||
</dict>
|
||||
<key>3</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.string.end.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(?x)
|
||||
(')
|
||||
(?:
|
||||
[\ -\[\]-~] # Basic Char
|
||||
| (\\(?:NUL|SOH|STX|ETX|EOT|ENQ|ACK|BEL|BS|HT|LF|VT|FF|CR|SO|SI|DLE
|
||||
|DC1|DC2|DC3|DC4|NAK|SYN|ETB|CAN|EM|SUB|ESC|FS|GS|RS
|
||||
|US|SP|DEL|[abfnrtv\\\"'\&])) # Escapes
|
||||
| (\^[A-Z@\[\]\\\^_]) # Control Chars
|
||||
)
|
||||
(')</string>
|
||||
<key>name</key>
|
||||
<string>string.quoted.single.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>^(port\s+)?([a-z_][a-zA-Z0-9_']*|\([|!%$+\-.,=</>]+\))\s*((:)([:]+)?)</string>
|
||||
<key>beginCaptures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.port.elm</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>entity.name.function.elm</string>
|
||||
</dict>
|
||||
<key>4</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.colon.elm</string>
|
||||
</dict>
|
||||
<key>5</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>invalid</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>$\n?</string>
|
||||
<key>name</key>
|
||||
<string>meta.function.type-declaration.elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#type_signature</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\bport\s+</string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.port.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b[A-Z]\w*\b</string>
|
||||
<key>name</key>
|
||||
<string>constant.other.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#comments</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>^[a-z][A-Za-z0-9_']*\s+</string>
|
||||
<key>name</key>
|
||||
<string>entity.name.function.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#infix_op</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>[|!%$?~+:\-.=</>&\\*^]+</string>
|
||||
<key>name</key>
|
||||
<string>keyword.operator.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>support.function.delimiter.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>([\[\]\{\},])</string>
|
||||
<key>name</key>
|
||||
<string>constant.language.delimiter.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>([\(\)])</string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.parenthesis.elm</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>repository</key>
|
||||
<dict>
|
||||
<key>block_comment</key>
|
||||
<dict>
|
||||
<key>applyEndPatternLast</key>
|
||||
<integer>1</integer>
|
||||
<key>begin</key>
|
||||
<string>\{-(?!#)</string>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>0</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>end</key>
|
||||
<string>-\}</string>
|
||||
<key>name</key>
|
||||
<string>comment.block.elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#block_comment</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>comments</key>
|
||||
<dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>punctuation.definition.comment.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>(--).*$\n?</string>
|
||||
<key>name</key>
|
||||
<string>comment.line.double-dash.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#block_comment</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>infix_op</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(\([|!%$+:\-.=</>]+\)|\(,+\))</string>
|
||||
<key>name</key>
|
||||
<string>entity.name.function.infix.elm</string>
|
||||
</dict>
|
||||
<key>module_exports</key>
|
||||
<dict>
|
||||
<key>begin</key>
|
||||
<string>\(</string>
|
||||
<key>end</key>
|
||||
<string>\)</string>
|
||||
<key>name</key>
|
||||
<string>meta.declaration.exports.elm</string>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b[a-z][a-zA-Z_'0-9]*</string>
|
||||
<key>name</key>
|
||||
<string>entity.name.function.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b[A-Z][A-Za-z_'0-9]*</string>
|
||||
<key>name</key>
|
||||
<string>storage.type.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>,</string>
|
||||
<key>name</key>
|
||||
<string>punctuation.separator.comma.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#infix_op</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>comment</key>
|
||||
<string>So named because I don't know what to call this.</string>
|
||||
<key>match</key>
|
||||
<string>\(.*?\)</string>
|
||||
<key>name</key>
|
||||
<string>meta.other.unknown.elm</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
<key>module_name</key>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>[A-Z][A-Za-z._']*</string>
|
||||
<key>name</key>
|
||||
<string>support.other.module.elm</string>
|
||||
</dict>
|
||||
<key>type_signature</key>
|
||||
<dict>
|
||||
<key>patterns</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>captures</key>
|
||||
<dict>
|
||||
<key>1</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>entity.other.inherited-class.elm</string>
|
||||
</dict>
|
||||
<key>2</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>variable.other.generic-type.elm</string>
|
||||
</dict>
|
||||
<key>3</key>
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>keyword.other.big-arrow.elm</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>match</key>
|
||||
<string>\(\s*([A-Z][A-Za-z]*)\s+([a-z][A-Za-z_']*)\)\s*(=>)</string>
|
||||
<key>name</key>
|
||||
<string>meta.class-constraint.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>-></string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.arrow.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>=></string>
|
||||
<key>name</key>
|
||||
<string>keyword.other.big-arrow.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b[a-z][a-zA-Z0-9_']*\b</string>
|
||||
<key>name</key>
|
||||
<string>variable.other.generic-type.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\b[A-Z][a-zA-Z0-9_']*\b</string>
|
||||
<key>name</key>
|
||||
<string>storage.type.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>\(\)</string>
|
||||
<key>name</key>
|
||||
<string>support.constant.unit.elm</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>include</key>
|
||||
<string>#comments</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>scopeName</key>
|
||||
<string>source.elm</string>
|
||||
<key>uuid</key>
|
||||
<string>2cb90e5e-6e98-456d-9a8a-b59935dbc4b0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
8
tsconfig.base.json
Normal file
8
tsconfig.base.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true
|
||||
}
|
||||
}
|
||||
27
vsc-extension-quickstart.md
Normal file
27
vsc-extension-quickstart.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# Welcome to your 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 language support and define
|
||||
the location of the grammar file that has been copied into your extension.
|
||||
* `syntaxes/elm.tmLanguage` - this is the Text mate grammar file that is used for tokenization.
|
||||
* `language-configuration.json` - this the language configuration, defining the tokens that are used for
|
||||
comments and brackets.
|
||||
|
||||
## Get up and running straight away
|
||||
* Make sure the language configuration settings in `language-configuration.json` are accurate.
|
||||
* Press `F5` to open a new window with your extension loaded.
|
||||
* Create a new file with a file name suffix matching your language.
|
||||
* Verify that syntax highlighting works and that the language configuration settings are working.
|
||||
|
||||
## Make changes
|
||||
* You can relaunch the extension from the debug toolbar after making changes to the files listed above.
|
||||
* You can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes.
|
||||
|
||||
## Add more language features
|
||||
* To add features such as intellisense, hovers and validators check out the VS Code extenders documentation at
|
||||
https://code.visualstudio.com/docs
|
||||
|
||||
## Install your extension
|
||||
* To start using your extension with Visual Studio Code copy it into the `<user home>/.vscode/extensions` folder and restart Code.
|
||||
* To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension.
|
||||
Reference in New Issue
Block a user