Skip to content

Commit

Permalink
Merge pull request #12 from jabraham17/fix-bugs
Browse files Browse the repository at this point in the history
This PR bundles a number of fixes and improves to the extension

Features
- The extension is no longer reliant on a `CHPL_HOME` value
- Can detect and use prefix-based installs
- Added better error detection and handling
  - When CLS/chplcheck has crashed, the status bar now also has a notification to show that these are not working correctly. 
- Removed the ability to build the tools automatically, this was error prone and only rarely the "correct" course of action
- Syntax highlighting for format string specifiers

List of fixes
- Resolve issues with searching PATH
- Fix syntax highlighting for numbers and the count operator

Tested locally with two versions of a chapel, a CHPL_HOME build from source and with a prefix install from homebrew

[Reviewed by @ShreyasKhandekar]
  • Loading branch information
jabraham17 authored May 28, 2024
2 parents 3523c4d + 78cf1c1 commit d0cc569
Show file tree
Hide file tree
Showing 9 changed files with 273 additions and 136 deletions.
9 changes: 9 additions & 0 deletions DEVELOPER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Documentation for Extension Developers

This document is intended for developers who want to contribute to the Chapel extension for Visual Studio Code.

## Building locally

To build and test the extension locally in debug mode, you can use the Run/Debug tab to launch the extension in a new VSCode window (or press `F5`).

For some debugging purposes, it may be useful to build a local binary of the extension using `vsce`. To do this, run `vsce package -o bin/chapel.vsix` from the root of the repository. This can then be installed in VSCode by selecting "Install from VSIX" in the Extensions view, or by running `code --install-extension bin/chapel.vsix`.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
- Generic Instantiations: inspect generic code with helpful annotations
- Dead Code: highlight dead code that will never execute

> **_:warning: CAUTION:_**
> **_CAUTION:_**
> These features use a work-in-progress resolver for Chapel called Dyno to further
> inspect your code. To enable these features, use Dyno by setting
> `chapel.chpl-language-server.resolver` to `true`. Enabling the Dyno resolver
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 13 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,8 @@
],
"commands": [
{
"command": "chapel.findChpl",
"title": "Find Chapel",
"category": "chapel"
},
{
"command": "chapel.buildTools",
"title": "Build chpl-language-server and chplcheck",
"command": "chapel.findChplHome",
"title": "Find CHPL_HOME",
"category": "chapel"
},
{
Expand All @@ -114,7 +109,7 @@
"chapel.CHPL_HOME": {
"scope": "window",
"type": "string",
"description": "CHPL_HOME"
"description": "The path to CHPL_HOME. If not provided, the extension may be able to find it automatically if `chpl`, `chplcheck`, and `chpl-language-server` are in PATH."
},
"chapel.CHPL_DEVELOPER": {
"scope": "window",
Expand All @@ -128,6 +123,11 @@
"default": true,
"description": "Enable chplcheck"
},
"chapel.chplcheck.path": {
"scope": "window",
"type": "string",
"description": "An explicit path to the chplcheck executable. If not provided, the extension will look for chplcheck in PATH and in CHPL_HOME"
},
"chapel.chplcheck.args": {
"scope": "window",
"type": "array",
Expand All @@ -143,6 +143,11 @@
"default": true,
"description": "Enable chpl-language-server"
},
"chapel.chpl-language-server.path": {
"scope": "window",
"type": "string",
"description": "An explicit path to the chpl-language-server executable. If not provided, the extension will look for chpl-language-server in PATH and in CHPL_HOME"
},
"chapel.chpl-language-server.resolver": {
"scope": "window",
"type": "boolean",
Expand Down
94 changes: 65 additions & 29 deletions src/ChapelLanguageClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@
* limitations under the License.
*/

import { ToolConfig, getChplDeveloper } from "./configuration";
import { ToolConfig, getChplDeveloper, getChplHome } from "./configuration";
import * as fs from "fs";
import * as vscode from "vscode";
import * as vlc from "vscode-languageclient/node";
import { checkToolPath, checkChplHome, cloneEnv } from "./ChplPaths";
import {
checkToolPath,
checkChplHome,
cloneEnv,
findToolPath,
findPossibleChplHomes,
getWorkspaceFolder,
} from "./ChplPaths";
import { showChplHomeMissingError } from "./extension";
import * as path from "path";

export enum LanguageClientState {
Expand Down Expand Up @@ -62,21 +70,19 @@ class ErrorHandlingClient extends vlc.LanguageClient {
}

export abstract class ChapelLanguageClient {
chplhome: string;
protected config_: ToolConfig;
name: string;
state: LanguageClientState;
tool_path: string;
client: ErrorHandlingClient | undefined;
logger: vscode.LogOutputChannel;
statusBarItem: vscode.StatusBarItem;

constructor(
chplhome: string,
config: ToolConfig,
name: string,
logger: vscode.LogOutputChannel
) {
this.chplhome = chplhome;
this.config_ = config;
this.name = name;
this.state = this.config_.enable
Expand All @@ -85,16 +91,30 @@ export abstract class ChapelLanguageClient {
this.tool_path = this.getToolPath();
this.client = undefined;
this.logger = logger;
this.statusBarItem = vscode.window.createStatusBarItem(
vscode.StatusBarAlignment.Right,
1000
);
// render the text using vscode codicons
this.statusBarItem.text = `$(error) ${this.name}`;
this.statusBarItem.tooltip = `${this.name} is stopped. Click to restart.`;
this.statusBarItem.color = new vscode.ThemeColor(
"statusBarItem.errorForeground"
);
this.statusBarItem.backgroundColor = new vscode.ThemeColor(
"statusBarItem.errorBackground"
);
this.statusBarItem.command = `${this.name}.restart`;
this.statusBarItem.hide();
}

protected abstract getToolPath(): string;

get config(): ToolConfig {
return this.config_;
}
async resetConfig(chplhome: string, config: ToolConfig) {
async resetConfig(config: ToolConfig) {
await this.stop();
this.chplhome = chplhome;
this.config_ = config;
this.state = this.config_.enable
? LanguageClientState.STOPPED
Expand All @@ -105,36 +125,41 @@ export abstract class ChapelLanguageClient {

setErrorState() {
this.state = LanguageClientState.ERRORED;
this.statusBarItem.show();
}

clearError(): void {
this.state = LanguageClientState.STOPPED;
}

private errorFindTools() {
this.setErrorState();
// if invalid chplhome, prompt user to set it
// if missing tool path, warn user that we can't find it, tell them to not override the path or upgrade their chapel version
// otherwise, its likely the tools arent built, so prompt the user to build them

if (checkChplHome(this.chplhome) !== undefined) {
if (this.tool_path === "") {
vscode.window
.showErrorMessage(
"CHPL_HOME is either missing or incorrect, make sure the path is correct",
"Find CHPL_HOME",
`Could not determine the path for ${this.name}. Make sure it is installed. If it is, you may need to set the path manually.`,
`Set ${this.name} Path`,
"Set CHPL_HOME",
"Show Log",
"Ok"
)
.then((value) => {
if (value === "Find CHPL_HOME") {
vscode.commands.executeCommand("chapel.findChpl");
if (value === `Set ${this.name} Path`) {
// TODO
} else if (value === "Set CHPL_HOME") {
vscode.commands.executeCommand("chapel.findChplHome");
} else if (value === "Show Log") {
this.logger.show();
}
});
} else if (checkToolPath(this.tool_path) !== undefined) {
vscode.window
.showErrorMessage(
`${this.name} does not exist in the CHPL_HOME directory, make sure you are using the correct version of Chapel`,
`${this.name} is missing at the path '${this.tool_path}'. If you set the path manually, make sure it is correct. If it is, you may need to upgrade your Chapel version.`,
"Show Log",
"Ok"
)
Expand All @@ -146,15 +171,12 @@ export abstract class ChapelLanguageClient {
} else {
vscode.window
.showErrorMessage(
`${this.name} encountered an error, this is likely because ${this.name} is not installed. Double check that ${this.name} is built.`,
"Build Tools",
`${this.name} encountered an error. You may need to rebuild ${this.name}.`,
"Show Log",
"Ok"
)
.then((value) => {
if (value === "Build Tools") {
vscode.commands.executeCommand(`chapel.buildTools`, this.chplhome);
} else if (value === "Show Log") {
if (value === "Show Log") {
this.logger.show();
}
});
Expand All @@ -168,16 +190,25 @@ export abstract class ChapelLanguageClient {
return Promise.resolve();
}
this.state = LanguageClientState.STARTING;
this.statusBarItem.hide();
let toolPathError = checkToolPath(this.tool_path);
if (toolPathError !== undefined) {
this.logger.error(toolPathError);
this.errorFindTools();
this.state = LanguageClientState.STOPPED;
return Promise.reject();
}

let env = cloneEnv();
env.CHPL_HOME = this.chplhome;
const chplhome = getChplHome();
if (chplhome !== undefined && chplhome !== "") {
this.logger.info(`Using CHPL_HOME: ${chplhome}`);
const chplHomeError = checkChplHome(chplhome);
if (chplHomeError !== undefined) {
showChplHomeMissingError(chplHomeError);
} else {
env.CHPL_HOME = chplhome;
}
}
env.CHPL_DEVELOPER = getChplDeveloper() ? "1" : "0";

let args = this.alwaysArguments();
Expand All @@ -190,7 +221,7 @@ export abstract class ChapelLanguageClient {
command: this.tool_path,
args: args,
options: {
cwd: this.chplhome,
cwd: getWorkspaceFolder()?.uri.fsPath,
env: env,
},
};
Expand Down Expand Up @@ -238,7 +269,7 @@ export abstract class ChapelLanguageClient {
}

this.stop().finally(() => {
this.state = LanguageClientState.ERRORED;
this.setErrorState();

vscode.window
.showErrorMessage(
Expand Down Expand Up @@ -337,20 +368,25 @@ export abstract class ChapelLanguageClient {

export class ChplCheckClient extends ChapelLanguageClient {
getToolPath(): string {
return path.join(this.chplhome, "tools", "chplcheck", "chplcheck");
const path = findToolPath("chplcheck", getChplHome());
if (path === undefined) {
this.setErrorState();
return "";
}
return path;
}
alwaysArguments(): Array<string> {
return ["--lsp"];
}
}
export class CLSClient extends ChapelLanguageClient {
getToolPath(): string {
return path.join(
this.chplhome,
"tools",
"chpl-language-server",
"chpl-language-server"
);
const path = findToolPath("chpl-language-server", getChplHome());
if (path === undefined) {
this.setErrorState();
return "";
}
return path;
}
alwaysArguments(): Array<string> {
let args = [];
Expand Down
Loading

0 comments on commit d0cc569

Please sign in to comment.