mirror of
https://github.com/foambubble/foam.git
synced 2026-01-10 06:28:12 -05:00
Setup Language Server boilerplate (#258)
This commit is contained in:
19
.vscode/launch.json
vendored
19
.vscode/launch.json
vendored
@@ -71,6 +71,25 @@
|
||||
"cwd": "${workspaceFolder}/packages/foam-core",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"preLaunchTask": "${defaultBuildTask}"
|
||||
},
|
||||
{
|
||||
"name": "Debug Language Server",
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"port": 6009,
|
||||
// large timeout to account for typescript watch startup time
|
||||
"timeout": 30000,
|
||||
"restart": true,
|
||||
"trace": true,
|
||||
"localRoot": "${workspaceFolder}/packages/foam-language-server/src/",
|
||||
"remoteRoot": "${workspaceFolder}/packages/foam-language-server/dist/",
|
||||
"outFiles": ["${workspaceFolder}/packages/foam-language-server/dist/**/*.js"]
|
||||
},
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
"name": "Run Extension & Debug LSP",
|
||||
"configurations": ["Run VSCode Extension", "Debug Language Server"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
29
packages/foam-language-server/package.json
Normal file
29
packages/foam-language-server/package.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "foam-language-server",
|
||||
"author": "Jani Eväkallio",
|
||||
"repository": "https://github.com/foambubble/foam",
|
||||
"version": "0.3.0",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"clean": "rimraf dist",
|
||||
"build": "tsdx build --tsconfig ./tsconfig.build.json",
|
||||
"test": "tsdx test",
|
||||
"lint": "tsdx lint src test",
|
||||
"watch": "tsdx watch",
|
||||
"prepare": "npm run build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tsdx": "^0.13.2",
|
||||
"tslib": "^2.0.0",
|
||||
"typescript": "^3.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"foam-core": "^0.3.0",
|
||||
"vscode-languageserver": "^6.1.1"
|
||||
},
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts"
|
||||
}
|
||||
125
packages/foam-language-server/src/index.ts
Normal file
125
packages/foam-language-server/src/index.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
createConnection,
|
||||
ProposedFeatures,
|
||||
InitializeParams,
|
||||
DidChangeConfigurationNotification,
|
||||
CompletionItem,
|
||||
CompletionItemKind,
|
||||
TextDocumentPositionParams,
|
||||
TextDocumentSyncKind,
|
||||
InitializeResult
|
||||
} from 'vscode-languageserver';
|
||||
|
||||
const data = [
|
||||
{
|
||||
text: 'Foam',
|
||||
displayName: 'Foam',
|
||||
description: 'Foam is a personal knowledge management and sharing system built on Visual Studio Code and GitHub.'
|
||||
},
|
||||
{
|
||||
text: 'Roam',
|
||||
displayName: 'Roam Research',
|
||||
description: 'Roam is a A note-taking tool for networked thought',
|
||||
},
|
||||
{
|
||||
text: 'Obsidian',
|
||||
displayName: "Obsidian",
|
||||
description: 'Obsidian is a powerful knowledge base that works on top of a local folder of plain text Markdown files.'
|
||||
}
|
||||
];
|
||||
|
||||
// Create a connection for the server, using Node's IPC as a transport.
|
||||
// Also include all preview / proposed LSP features.
|
||||
let connection = createConnection(ProposedFeatures.all);
|
||||
|
||||
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 fall back using global settings.
|
||||
hasConfigurationCapability = !!(
|
||||
capabilities.workspace && !!capabilities.workspace.configuration
|
||||
);
|
||||
|
||||
hasWorkspaceFolderCapability = !!(
|
||||
capabilities.workspace && !!capabilities.workspace.workspaceFolders
|
||||
);
|
||||
|
||||
const result: InitializeResult = {
|
||||
capabilities: {
|
||||
textDocumentSync: TextDocumentSyncKind.Incremental,
|
||||
// Tell the client that this server supports code completion.
|
||||
completionProvider: {
|
||||
triggerCharacters: ["["],
|
||||
resolveProvider: true
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (hasWorkspaceFolderCapability) {
|
||||
result.capabilities.workspace = {
|
||||
workspaceFolders: {
|
||||
supported: true
|
||||
}
|
||||
};
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
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.');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
connection.onDidChangeConfiguration(change => {
|
||||
if (hasConfigurationCapability) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
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[] => {
|
||||
console.log('onCompletion.textDocumentPosition', _textDocumentPosition);
|
||||
// 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 data.map(item => ({
|
||||
label: item.displayName,
|
||||
kind: CompletionItemKind.Text,
|
||||
data: item.text
|
||||
}));
|
||||
}
|
||||
);
|
||||
|
||||
// This handler resolves additional information for the item selected in
|
||||
// the completion list.
|
||||
connection.onCompletionResolve(
|
||||
(item: CompletionItem): CompletionItem => {
|
||||
console.log('onCompletionResolve.item', item);
|
||||
const product = data.find(p => p.text = item.data);
|
||||
if (product) {
|
||||
item.detail = product.displayName;
|
||||
item.documentation = product.description;
|
||||
}
|
||||
return item;
|
||||
}
|
||||
);
|
||||
|
||||
// Listen on the connection
|
||||
connection.listen();
|
||||
8
packages/foam-language-server/tsconfig.build.json
Normal file
8
packages/foam-language-server/tsconfig.build.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "es6",
|
||||
"sourceMap": true,
|
||||
"inlineSourceMap": false
|
||||
}
|
||||
}
|
||||
31
packages/foam-language-server/tsconfig.json
Normal file
31
packages/foam-language-server/tsconfig.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": "src",
|
||||
"composite": true,
|
||||
"esModuleInterop": true,
|
||||
"importHelpers": true,
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"lib": [
|
||||
"esnext"
|
||||
],
|
||||
|
||||
// @NOTE regarding inlineSourceMap:
|
||||
//
|
||||
// Preferrably we would use "sourceMap": true to generate
|
||||
// *.map.js files instead of inline base64 encoded source maps,
|
||||
// however for some reason the VSCode Node debugger looks
|
||||
// for source maps in the src/ directory instead of dist/ directory,
|
||||
// causing the VSCode debugging experience to break.
|
||||
"inlineSourceMap": true,
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"],
|
||||
"references": [{
|
||||
"path": "../foam-core"
|
||||
}]
|
||||
}
|
||||
@@ -91,8 +91,8 @@
|
||||
"build": "tsc -p ./",
|
||||
"test": "jest",
|
||||
"lint": "eslint src --ext ts",
|
||||
"clean": "tsc --build ./tsconfig.json ../foam-core/tsconfig.json --clean",
|
||||
"watch": "tsc --build ./tsconfig.json ../foam-core/tsconfig.json --watch",
|
||||
"clean": "tsc --build ./tsconfig.json ../foam-core/tsconfig.json ../foam-language-server/tsconfig.json --clean",
|
||||
"watch": "tsc --build ./tsconfig.json ../foam-core/tsconfig.json ../foam-language-server/tsconfig.json --watch",
|
||||
"vscode:start-debugging": "yarn clean && yarn watch",
|
||||
"vscode:prepublish": "yarn npm-install && yarn run build",
|
||||
"npm-install": "rimraf node_modules && npm i",
|
||||
@@ -120,6 +120,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"dateformat": "^3.0.3",
|
||||
"foam-core": "0.3.0"
|
||||
"foam-core": "0.3.0",
|
||||
"vscode-languageclient": "^6.1.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,14 @@ export function activate(context: ExtensionContext) {
|
||||
});
|
||||
}
|
||||
|
||||
export function deactivate() {
|
||||
export async function deactivate(): Promise<void> {
|
||||
workspaceWatcher?.dispose();
|
||||
|
||||
// call all deactivate functions and if any of them
|
||||
// return promises, wait for their completion
|
||||
await Promise.all(features.map(
|
||||
f => (f.deactivate && f.deactivate()) || Promise.resolve()
|
||||
));
|
||||
}
|
||||
|
||||
function isLocalMarkdownFile(uri: Uri) {
|
||||
@@ -69,7 +75,7 @@ const bootstrap = async (config: FoamConfig) => {
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
workspaceWatcher.onDidCreate(uri => {
|
||||
if (isLocalMarkdownFile(uri)) {
|
||||
addFile(uri).then(() => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import createReferences from "./wikilink-reference-generation";
|
||||
import openDailyNote from "./open-daily-note";
|
||||
import janitor from "./janitor";
|
||||
import languageServerClient from "./language-server-client";
|
||||
import { FoamFeature } from "../types";
|
||||
|
||||
export const features: FoamFeature[] = [createReferences, openDailyNote, janitor];
|
||||
export const features: FoamFeature[] = [createReferences, languageServerClient, openDailyNote, janitor];
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import * as path from "path";
|
||||
import { workspace, ExtensionContext } from "vscode";
|
||||
import { FoamFeature } from "../../types";
|
||||
|
||||
import {
|
||||
LanguageClient,
|
||||
LanguageClientOptions,
|
||||
ServerOptions,
|
||||
TransportKind
|
||||
} from "vscode-languageclient";
|
||||
|
||||
let client: LanguageClient;
|
||||
|
||||
const feature: FoamFeature = {
|
||||
activate: (context: ExtensionContext) => {
|
||||
// @TODO figure out path for production deploys
|
||||
let serverModule = context.asAbsolutePath(
|
||||
path.join("..", "foam-language-server", "dist", "index.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 markdown documents
|
||||
documentSelector: [
|
||||
{ scheme: "file", language: "markdown" },
|
||||
{ scheme: "file", language: "mdx" }
|
||||
],
|
||||
synchronize: {
|
||||
fileEvents: workspace.createFileSystemWatcher(
|
||||
"**/.vscode/settings.json"
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
// Create the language client and start the client.
|
||||
client = new LanguageClient(
|
||||
"foam-language-server",
|
||||
"Foam Language Server",
|
||||
serverOptions,
|
||||
clientOptions
|
||||
);
|
||||
|
||||
console.log(
|
||||
"Starting foam-language-server with options\n",
|
||||
JSON.stringify(serverOptions, null, 2)
|
||||
);
|
||||
|
||||
// Start the client. This will also launch the server
|
||||
client.start();
|
||||
},
|
||||
deactivate() {
|
||||
if (client) {
|
||||
console.log("Stopping foam-language-server");
|
||||
return client.stop();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default feature;
|
||||
3
packages/foam-vscode/src/types.d.ts
vendored
3
packages/foam-vscode/src/types.d.ts
vendored
@@ -2,5 +2,6 @@ import { ExtensionContext } from "vscode";
|
||||
import { Foam } from "foam-core";
|
||||
|
||||
export interface FoamFeature {
|
||||
activate: (context: ExtensionContext, foamPromise: Promise<Foam>) => void
|
||||
activate: (context: ExtensionContext, foamPromise: Promise<Foam>) => void,
|
||||
deactivate?: () => Promise<void>
|
||||
}
|
||||
|
||||
@@ -12,5 +12,7 @@
|
||||
"exclude": ["node_modules", ".vscode-test"],
|
||||
"references": [{
|
||||
"path": "../foam-core"
|
||||
}, {
|
||||
"path": "../foam-language-server"
|
||||
}]
|
||||
}
|
||||
|
||||
33
yarn.lock
33
yarn.lock
@@ -11815,6 +11815,39 @@ vfile@^4.0.0:
|
||||
unist-util-stringify-position "^2.0.0"
|
||||
vfile-message "^2.0.0"
|
||||
|
||||
vscode-jsonrpc@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-5.0.1.tgz#9bab9c330d89f43fc8c1e8702b5c36e058a01794"
|
||||
integrity sha512-JvONPptw3GAQGXlVV2utDcHx0BiY34FupW/kI6mZ5x06ER5DdPG/tXWMVHjTNULF5uKPOUUD0SaXg5QaubJL0A==
|
||||
|
||||
vscode-languageclient@^6.1.3:
|
||||
version "6.1.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-6.1.3.tgz#c979c5bb5855714a0307e998c18ca827c1b3953a"
|
||||
integrity sha512-YciJxk08iU5LmWu7j5dUt9/1OLjokKET6rME3cI4BRpiF6HZlusm2ZwPt0MYJ0lV5y43sZsQHhyon2xBg4ZJVA==
|
||||
dependencies:
|
||||
semver "^6.3.0"
|
||||
vscode-languageserver-protocol "^3.15.3"
|
||||
|
||||
vscode-languageserver-protocol@^3.15.3:
|
||||
version "3.15.3"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.3.tgz#3fa9a0702d742cf7883cb6182a6212fcd0a1d8bb"
|
||||
integrity sha512-zrMuwHOAQRhjDSnflWdJG+O2ztMWss8GqUUB8dXLR/FPenwkiBNkMIJJYfSN6sgskvsF0rHAoBowNQfbyZnnvw==
|
||||
dependencies:
|
||||
vscode-jsonrpc "^5.0.1"
|
||||
vscode-languageserver-types "3.15.1"
|
||||
|
||||
vscode-languageserver-types@3.15.1:
|
||||
version "3.15.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.15.1.tgz#17be71d78d2f6236d414f0001ce1ef4d23e6b6de"
|
||||
integrity sha512-+a9MPUQrNGRrGU630OGbYVQ+11iOIovjCkqxajPa9w57Sd5ruK8WQNsslzpa0x/QJqC8kRc2DUxWjIFwoNm4ZQ==
|
||||
|
||||
vscode-languageserver@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-6.1.1.tgz#d76afc68172c27d4327ee74332b468fbc740d762"
|
||||
integrity sha512-DueEpkUAkD5XTR4MLYNr6bQIp/UFR0/IPApgXU3YfCBCB08u2sm9hRCs6DxYZELkk++STPjpcjksR2H8qI3cDQ==
|
||||
dependencies:
|
||||
vscode-languageserver-protocol "^3.15.3"
|
||||
|
||||
vscode-test@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-test/-/vscode-test-1.4.0.tgz#a56f73c1667b4d37ba6baa6765f233a19d4ffbfe"
|
||||
|
||||
Reference in New Issue
Block a user