Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 2de7a2a

Browse files
committed
Documentation
1 parent 731fd9c commit 2de7a2a

File tree

2 files changed

+61
-13
lines changed

2 files changed

+61
-13
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
},
6161
"syntaxTree.trailingComma": {
6262
"default": false,
63-
"markdownDescription": "Adds an extra comma after the last item of arrays, hashes and parameters.",
63+
"markdownDescription": "Adds a trailing comma to multi-line array literals, hash literals, and method parameters.",
6464
"type": "boolean"
6565
},
6666
"syntaxTree.additionalPlugins": {

src/extension.ts

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use strict";
22

3-
import { ConfigurationChangeEvent, ExtensionContext, commands, window, workspace } from "vscode";
3+
import { ExtensionContext, commands, window, workspace } from "vscode";
44
import { LanguageClient, ServerOptions } from "vscode-languageclient/node";
55
import { promisify } from "util";
66
import { exec } from "child_process";
@@ -10,49 +10,85 @@ import Visualize from "./Visualize";
1010

1111
const promiseExec = promisify(exec);
1212

13+
// This is the expected top-level export that is called by VSCode.
1314
export function activate(context: ExtensionContext) {
15+
// This output channel is going to contain all of our informational messages.
16+
// It's not really meant for the end-user, it's more for debugging.
1417
const outputChannel = window.createOutputChannel("Syntax Tree");
18+
19+
// These objects will get initialized once the language client is ready.
1520
let languageClient: LanguageClient | null = null;
1621
let visualizer: Visualize | null = null;
1722

23+
// This is the list of objects that implement the Disposable interface. They
24+
// will all get cleaned up with this extension is deactivated. It's important
25+
// to add them to this list so we don't leak memory.
1826
context.subscriptions.push(
27+
// The output channel itself is a disposable. When the extension is
28+
// deactivated it will be removed from the list.
1929
outputChannel,
30+
31+
// Each of the commands that interacts with this extension is a disposable.
32+
// It's important to register them here as opposed to whenever the client
33+
// starts up because we don't want to register them again whenever the
34+
// client restarts.
2035
commands.registerCommand("syntaxTree.start", startLanguageServer),
2136
commands.registerCommand("syntaxTree.stop", stopLanguageServer),
2237
commands.registerCommand("syntaxTree.restart", restartLanguageServer),
2338
commands.registerCommand("syntaxTree.visualize", () => visualizer?.visualize()),
2439
commands.registerCommand("syntaxTree.showOutputChannel", () => outputChannel.show()),
25-
workspace.onDidChangeConfiguration(event =>
26-
event.affectsConfiguration("syntaxTree") &&
27-
restartLanguageServer())
40+
workspace.onDidChangeConfiguration(event => {
41+
if (event.affectsConfiguration("syntaxTree")) {
42+
restartLanguageServer();
43+
}
44+
})
2845
);
2946

47+
// We're returning a Promise from this function that will start the Ruby
48+
// subprocess.
3049
return startLanguageServer();
3150

51+
// This function is called when the extension is activated or when the
52+
// language server is restarted.
3253
async function startLanguageServer() {
54+
// The top-level configuration group is syntaxTree. All of the configuration
55+
// for the extension is under that group.
3356
const config = workspace.getConfiguration("syntaxTree");
34-
const addlPlugins = config.get<string[]>("additionalPlugins") || [];
35-
const singleQuotes = config.get<boolean>("singleQuotes");
36-
const trailingComma = config.get<boolean>("trailingComma");
3757

58+
// The args are going to be passed to the stree executable. It's important
59+
// that it lines up with what the CLI expects.
3860
const args = ["lsp"];
39-
4061
const plugins = new Set<string>();
41-
if (singleQuotes) {
62+
63+
if (config.get<boolean>("singleQuotes")) {
4264
plugins.add("plugin/single_quotes");
4365
}
44-
if (trailingComma) {
66+
67+
if (config.get<boolean>("trailingComma")) {
4568
plugins.add("plugin/trailing_comma");
4669
}
47-
addlPlugins.forEach(plugins.add);
4870

49-
if (plugins.size) {
71+
const additionalPlugins = config.get<string[]>("additionalPlugins");
72+
if (additionalPlugins) {
73+
additionalPlugins.forEach(plugin => plugins.add(plugin));
74+
}
75+
76+
// If there are any plugins, then we'll pass the --plugins command line
77+
// option to the stree lsp command.
78+
if (plugins.size > 0) {
5079
args.push(`--plugins=${Array.from(plugins).join(",")}`);
5180
}
5281

5382
outputChannel.appendLine(`Starting language server with ${plugins.size} plugin(s)...`);
5483
let run: ServerOptions = { command: "stree", args };
5584

85+
// There's a bit of complexity here. Basically, if there's an open folder,
86+
// then w're going to check if the syntax_tree gem is inside the bundle. If
87+
// it is, then we'll run bundle exec stree. This is good, because it'll
88+
// ensure that we get the correct version of the gem. If it's not in the
89+
// bundle or there is no bundle, then we'll just run the global stree. This
90+
// might be correct in the end if the right environment variables are set,
91+
// but it's a bit of a prayer.
5692
if (workspace.workspaceFolders) {
5793
const cwd = workspace.workspaceFolders![0].uri.fsPath;
5894

@@ -64,30 +100,42 @@ export function activate(context: ExtensionContext) {
64100
}
65101
}
66102

103+
// Here, we instantiate the language client. This is the object that is
104+
// responsible for the communication and management of the Ruby subprocess.
67105
languageClient = new LanguageClient("Syntax Tree", { run, debug: run }, {
68106
documentSelector: [
69107
{ scheme: "file", language: "ruby" },
70108
],
71109
outputChannel
72110
});
73111

112+
// Here we're going to wait for the language server to start.
74113
context.subscriptions.push(languageClient.start());
75114
await languageClient.onReady();
76115

116+
// Finally, now that the language server has been properly started, we can
117+
// add the various features to the extension. Each of them in turn
118+
// implements Disposable so that they clean up their own resources.
77119
visualizer = new Visualize(languageClient, outputChannel);
78120
context.subscriptions.push(
79121
new InlayHints(languageClient, outputChannel),
80122
visualizer
81123
);
82124
}
83125

126+
// This function is called as part of the shutdown or restart process. It's
127+
// always user-initiated either through manually executing an action or
128+
// changing some configuration.
84129
async function stopLanguageServer() {
85130
if (languageClient) {
86131
outputChannel.appendLine("Stopping language server...");
87132
await languageClient.stop();
88133
}
89134
}
90135

136+
// This function is called as part of the restart process. Like
137+
// stopLanguageServer, it's always user-initiated either through manually
138+
// executing an action or changing some configuration.
91139
async function restartLanguageServer() {
92140
outputChannel.appendLine("Restarting language server...");
93141
await stopLanguageServer();

0 commit comments

Comments
 (0)