Skip to content

Commit bc5b468

Browse files
author
Danila Volkov
committed
copy all from vscode-func
1 parent 4e9f347 commit bc5b468

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+9937
-0
lines changed

.vscode/launch.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "Attach",
9+
"port": 6009,
10+
"request": "attach",
11+
"skipFiles": [
12+
"<node_internals>/**"
13+
],
14+
"type": "pwa-node"
15+
},
16+
{
17+
"args": [
18+
"--extensionDevelopmentPath=${workspaceFolder}"
19+
],
20+
"name": "Launch Extension",
21+
"outFiles": [
22+
"${workspaceFolder}/out/**/*.js"
23+
],
24+
"request": "launch",
25+
"type": "pwa-extensionHost"
26+
}
27+
]
28+
}

.vscodeignore

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
**/*
2+
3+
# Include only this files
4+
!dist/
5+
!LICENSE
6+
!CHANGELOG.md
7+
!package.json
8+
!README.md
9+
!language-configuration.json
10+
!syntaxes/
11+
!snippets/
12+
!logo.png

client/package.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "client",
3+
"description": "VSCode client part of the extension",
4+
"private": true,
5+
"engines": {
6+
"vscode": "^1.63.0"
7+
},
8+
"dependencies": {
9+
"vscode-languageclient": "^8.0.2",
10+
"vscode-uri": "^3.0.7"
11+
},
12+
"devDependencies": {
13+
"@types/node": "^17.0.23",
14+
"@types/vscode": "^1.63.0"
15+
}
16+
}

client/src/extension.ts

+203
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
import * as vscode from 'vscode';
2+
import { Utils } from 'vscode-uri';
3+
import * as path from 'path';
4+
import { workspace } from 'vscode';
5+
import {
6+
LanguageClient,
7+
LanguageClientOptions,
8+
RevealOutputChannelOn,
9+
ServerOptions,
10+
TransportKind
11+
} from 'vscode-languageclient/node';
12+
import { TextEncoder } from 'util';
13+
14+
15+
let client: LanguageClient;
16+
17+
18+
export function activate(context: vscode.ExtensionContext) {
19+
vscode.commands.registerCommand('func.copyToClipboard', (str: string) => {
20+
vscode.env.clipboard.writeText(str);
21+
vscode.window.showInformationMessage(`Copied ${str} to clipboard`);
22+
})
23+
24+
startServer(context)
25+
}
26+
27+
export function deactivate(): Thenable<void> | undefined {
28+
if (!client) {
29+
return undefined;
30+
}
31+
return client.stop();
32+
}
33+
34+
async function startServer(context: vscode.ExtensionContext): Promise<vscode.Disposable> {
35+
const disposables: vscode.Disposable[] = [];
36+
const databaseName = context.workspaceState.get('dbName', `func_${Math.random().toString(32).slice(2)}`);
37+
context.workspaceState.update('dbName', databaseName);
38+
39+
const clientOptions: LanguageClientOptions = {
40+
outputChannelName: 'FunC',
41+
revealOutputChannelOn: RevealOutputChannelOn.Never,
42+
documentSelector: [{ scheme: 'file', language: 'func' }],
43+
synchronize: {
44+
fileEvents: workspace.createFileSystemWatcher('**/.func.yml')
45+
},
46+
initializationOptions: {
47+
treeSitterWasmUri: Utils.joinPath(context.extensionUri, './dist/tree-sitter.wasm').fsPath,
48+
langUri: Utils.joinPath(context.extensionUri, './dist/tree-sitter-func.wasm').fsPath,
49+
databaseName
50+
}
51+
};
52+
53+
const serverModule = context.asAbsolutePath(
54+
path.join('dist', 'server.js')
55+
);
56+
57+
// pass initial configuration to env
58+
const extConfig = vscode.workspace.getConfiguration('func');
59+
const options = {
60+
env: {
61+
FUNC_SYMBOL_DISCOVERY: extConfig.get('symbolDiscovery'),
62+
FUNC_AUTOCOMPLETE_ADD_PARENTHESES: extConfig.get('autocompleteAddParentheses'),
63+
FUNC_EXPRERIMENTAL_DIAGNOSTICS: extConfig.get('experimentalDiagnostics'),
64+
}
65+
}
66+
const debugOptions = { ...options, execArgv: ['--nolazy', '--inspect=6009'] };
67+
const serverOptions: ServerOptions = {
68+
run: {
69+
module: serverModule,
70+
transport: TransportKind.ipc,
71+
options: options
72+
},
73+
debug: {
74+
module: serverModule,
75+
transport: TransportKind.ipc,
76+
options: debugOptions
77+
}
78+
};
79+
client = new LanguageClient(
80+
'funcServer',
81+
'FunC Language Server',
82+
serverOptions,
83+
clientOptions
84+
);
85+
86+
await client.start();
87+
88+
// serve fileRead request
89+
client.onRequest('file/read', async raw => {
90+
const uri = vscode.Uri.parse(raw);
91+
92+
if (uri.scheme === 'vscode-notebook-cell') {
93+
// we are dealing with a notebook
94+
try {
95+
const doc = await vscode.workspace.openTextDocument(uri);
96+
return new TextEncoder().encode(doc.getText());
97+
} catch (err) {
98+
console.warn(err);
99+
return { type: 'not-found' };
100+
}
101+
}
102+
103+
if (vscode.workspace.fs.isWritableFileSystem(uri.scheme) === undefined) {
104+
// undefined means we don't know anything about these uris
105+
return { type: 'not-found' };
106+
}
107+
108+
let data: Uint8Array;
109+
try {
110+
const stat = await vscode.workspace.fs.stat(uri);
111+
if (stat.size > 1024 ** 2) {
112+
console.warn(`IGNORING "${uri.toString()}" because it is too large (${stat.size}bytes)`);
113+
data = Buffer.from(new Uint8Array());
114+
} else {
115+
data = await vscode.workspace.fs.readFile(uri);
116+
}
117+
return data;
118+
} catch (err) {
119+
if (err instanceof vscode.FileSystemError) {
120+
return { type: 'not-found' };
121+
}
122+
// graceful
123+
console.warn(err);
124+
return { type: 'not-found' };
125+
}
126+
});
127+
128+
client.onRequest('completion/matching-files', async (raw: { pathPrefix: string, uri: string }) => {
129+
const uri = vscode.Uri.parse(raw.uri);
130+
let searchDirName = Utils.joinPath(uri, '..', raw.pathPrefix, (raw.pathPrefix.trim().length === 0 || raw.pathPrefix.endsWith(path.sep)) ? '' : '..');
131+
let toSearch = raw.pathPrefix.split(path.sep).pop() ?? '';
132+
133+
try {
134+
let files = await vscode.workspace.fs.readDirectory(searchDirName);
135+
return files
136+
.filter(([path, type]) => {
137+
if (path === toSearch) return false;
138+
139+
return path.startsWith(toSearch) && (type !== vscode.FileType.File || path.endsWith('.fc'));
140+
})
141+
.map(([segment, type]) => {
142+
if (type === vscode.FileType.Directory) {
143+
return segment + path.sep;
144+
}
145+
return segment;
146+
});
147+
} catch {
148+
return [];
149+
}
150+
});
151+
152+
// notify at configuration change
153+
vscode.workspace.onDidChangeConfiguration((change) => {
154+
if (change.affectsConfiguration('func')) {
155+
client.sendNotification('configuration/change', {
156+
symbolDiscovery: vscode.workspace.getConfiguration('func').get('symbolDiscovery'),
157+
autocompleteAddParentheses: vscode.workspace.getConfiguration('func').get('autocompleteAddParentheses'),
158+
experimentalDiagnostics: vscode.workspace.getConfiguration('func').get('experimentalDiagnostics'),
159+
});
160+
}
161+
})
162+
163+
const langPattern = `**/*.fc`;
164+
const watcher = vscode.workspace.createFileSystemWatcher(langPattern);
165+
disposables.push(watcher);
166+
167+
// file discover and watching. in addition to text documents we annouce and provide
168+
// all matching files
169+
170+
// workaround for https://github.com/microsoft/vscode/issues/48674
171+
const exclude = `{${[
172+
...Object.keys(vscode.workspace.getConfiguration('search', null).get('exclude') ?? {}),
173+
...Object.keys(vscode.workspace.getConfiguration('files', null).get('exclude') ?? {})
174+
].join(',')}}`;
175+
176+
let size: number = Math.max(0, vscode.workspace.getConfiguration('func').get<number>('symbolIndexSize', 500));
177+
178+
const init = async () => {
179+
let all = await vscode.workspace.findFiles(langPattern, exclude);
180+
181+
const uris = all.slice(0, size);
182+
console.info(`USING ${uris.length} of ${all.length} files for ${langPattern}`);
183+
184+
await client.sendRequest('queue/init', uris.map(String));
185+
};
186+
187+
const initCancel = new Promise<void>(resolve => disposables.push(new vscode.Disposable(resolve)));
188+
vscode.window.withProgress({ location: vscode.ProgressLocation.Window, title: '[FunC] Building Index...' }, () => Promise.race([init(), initCancel]));
189+
190+
disposables.push(watcher.onDidCreate(uri => {
191+
client.sendNotification('queue/add', uri.toString());
192+
}));
193+
disposables.push(watcher.onDidDelete(uri => {
194+
client.sendNotification('queue/remove', uri.toString());
195+
client.sendNotification('file-cache/remove', uri.toString());
196+
}));
197+
disposables.push(watcher.onDidChange(uri => {
198+
client.sendNotification('queue/add', uri.toString());
199+
client.sendNotification('file-cache/remove', uri.toString());
200+
}));
201+
202+
return new vscode.Disposable(() => disposables.forEach(d => d.dispose()));
203+
}

client/tsconfig.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"module": "commonjs",
4+
"target": "es2020",
5+
"lib": ["es2020"],
6+
"sourceMap": true
7+
},
8+
"include": ["src"],
9+
"exclude": ["node_modules", ".vscode-test"]
10+
}

0 commit comments

Comments
 (0)