Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
## Source discovery

Iris discovers sources through `spago.lock` by default. To use a command instead,
set `iris.sourceCommand` in your VS Code settings:
set `iris.server.sources` in your VS Code settings:

```json
{
"iris.sourceCommand": {
"iris.server.sources": {
"kind": "command",
"program": "spago",
"arguments": ["sources"]
}
Expand All @@ -18,10 +19,18 @@ set `iris.sourceCommand` in your VS Code settings:

The command must print one source path or glob per line. Arguments are passed
unchanged, without shell parsing or expansion. Only configure commands you trust.
Omit `arguments` when the program takes no arguments. Set `iris.sourceCommand` to
`null` or remove it to use Spago discovery, provided no deprecated source command
is configured. Reload the VS Code window after changing source discovery settings.
Omit `arguments` when the program takes no arguments. Set `iris.server.sources` to
`{ "kind": "spago" }` to explicitly select Spago over a deprecated source command,
or remove it to inherit startup source discovery, which defaults to Spago. Server
settings apply without reloading the VS Code window.

String values such as `"spago sources"` must be migrated to the object above for
Iris's `--config` interface. The deprecated `purescriptAnalyzer.sourceCommand`
setting uses the same object format.
The deprecated `iris.sourceCommand` setting continues to configure startup source
discovery during migration.

## Settings

VS Code client settings use the `iris.client` namespace. For example, set
`iris.client.serverPath` to select a particular Iris executable. Language server
settings use `iris.server`; diagnostic triggers are available as
`iris.server.diagnostics.onOpen`, `iris.server.diagnostics.onSave`, and
`iris.server.diagnostics.onChange`.
117 changes: 85 additions & 32 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,69 +53,122 @@
"configuration": {
"title": "Iris",
"properties": {
"iris.serverPath": {
"iris.client.serverPath": {
"type": "string",
"default": "",
"description": "Path or command used to start the Iris language server. If unset, Iris searches PATH for iris, then purescript-analyzer."
"description": "Path or command used to start the Iris language server. If unset, Iris searches PATH for iris."
},
"iris.sourceCommand": {
"iris.server.sources": {
"description": "How Iris discovers project sources. Changes apply to the running language server.",
"default": null,
"scope": "resource",
"oneOf": [
{
"type": "null"
},
{
"type": "object",
"required": [
"kind"
],
"additionalProperties": false,
"properties": {
"kind": {
"type": "string",
"const": "spago"
}
}
},
{
"type": "object",
"required": [
"kind",
"program"
],
"additionalProperties": false,
"properties": {
"kind": {
"type": "string",
"const": "command"
},
"program": {
"type": "string",
"minLength": 1,
"pattern": "[^\\u0009-\\u000D\\u0020\\u0085\\u00A0\\u1680\\u2000-\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000]",
"description": "Executable name or path, passed unchanged without shell parsing."
},
"arguments": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "Arguments passed unchanged to the executable."
}
}
}
]
},
"iris.server.diagnostics.onOpen": {
"type": [
"object",
"boolean",
"null"
],
"default": null,
"description": "Executable and arguments used to obtain source files, without shell parsing. If unset, Iris uses spago.lock integration. Reload the window after changing this setting.",
"required": [
"program"
"scope": "resource",
"description": "Publish diagnostics when a document opens. Iris defaults to true. Changes apply to the running language server."
},
"iris.server.diagnostics.onSave": {
"type": [
"boolean",
"null"
],
"additionalProperties": false,
"properties": {
"program": {
"type": "string",
"minLength": 1,
"description": "Executable name or path."
},
"arguments": {
"type": "array",
"items": {
"type": "string"
},
"default": [],
"description": "Arguments passed unchanged to the executable."
}
}
"default": null,
"scope": "resource",
"description": "Publish diagnostics when a document is saved. Iris defaults to true. Changes apply to the running language server."
},
"purescriptAnalyzer.serverPath": {
"iris.server.diagnostics.onChange": {
"type": [
"boolean",
"null"
],
"default": null,
"scope": "resource",
"description": "Publish diagnostics when a document changes. Iris defaults to false. Changes apply to the running language server."
},
"iris.serverPath": {
"type": "string",
"default": "",
"description": "Deprecated. Use iris.serverPath instead.",
"deprecationMessage": "Use iris.serverPath instead."
"description": "Deprecated. Use iris.client.serverPath instead.",
"deprecationMessage": "Use iris.client.serverPath instead."
},
"purescriptAnalyzer.sourceCommand": {
"iris.sourceCommand": {
"type": [
"object",
"null"
],
"default": null,
"description": "Deprecated. Use iris.server.sources instead.",
"deprecationMessage": "Use iris.server.sources instead.",
"required": [
"program"
],
"additionalProperties": false,
"properties": {
"program": {
"type": "string",
"minLength": 1
"minLength": 1,
"description": "Executable name or path."
},
"arguments": {
"type": "array",
"items": {
"type": "string"
},
"default": []
"default": [],
"description": "Arguments passed unchanged to the executable."
}
},
"description": "Deprecated. Use iris.sourceCommand instead.",
"deprecationMessage": "Use iris.sourceCommand instead."
}
}
}
}
Expand Down
39 changes: 12 additions & 27 deletions src/configuration.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import * as fs from "fs";
import * as path from "path";

export const defaultServerCommands = ["iris", "purescript-analyzer"];
export const defaultServerCommand = "iris";

export interface SourceCommand {
program: string;
arguments?: string[];
}

export interface ExtensionSettings {
export interface ClientSettings {
serverPath?: string;
}

export interface LegacySettings extends ClientSettings {
sourceCommand?: SourceCommand | null;
}

export interface ConfigurationInput {
iris?: ExtensionSettings;
purescriptAnalyzer?: ExtensionSettings;
client?: ClientSettings;
iris?: LegacySettings;
pathValue?: string;
platform?: NodeJS.Platform;
pathExtensions?: string;
Expand All @@ -42,27 +45,23 @@ export function resolveConfiguration(

export function resolveServerPath(input: ConfigurationInput) {
return (
trimmed(input.client?.serverPath) ||
trimmed(input.iris?.serverPath) ||
trimmed(input.purescriptAnalyzer?.serverPath) ||
findFirstExecutable(
defaultServerCommands,
findExecutable(
defaultServerCommand,
input.pathValue ?? process.env.PATH ?? "",
{
fileSystem: input.fileSystem,
pathExtensions: input.pathExtensions,
platform: input.platform,
},
) ||
defaultServerCommands[0]
defaultServerCommand
);
}

export function resolveSourceCommand(input: ConfigurationInput) {
return (
input.iris?.sourceCommand ??
input.purescriptAnalyzer?.sourceCommand ??
undefined
);
return input.iris?.sourceCommand ?? undefined;
}

export interface FindExecutableOptions {
Expand All @@ -71,20 +70,6 @@ export interface FindExecutableOptions {
fileSystem?: ExecutableFileSystem;
}

export function findFirstExecutable(
commands: readonly string[],
pathValue: string,
options: FindExecutableOptions = {},
) {
for (const command of commands) {
const executablePath = findExecutable(command, pathValue, options);
if (executablePath) {
return executablePath;
}
}
return undefined;
}

export function findExecutable(
command: string,
pathValue: string,
Expand Down
17 changes: 8 additions & 9 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,19 @@ import {
let client: LanguageClient;

export function activate(context: ExtensionContext) {
const config = workspace.getConfiguration("iris");
const legacyConfig = workspace.getConfiguration("purescriptAnalyzer");
const clientConfig = workspace.getConfiguration("iris.client");
const irisConfig = workspace.getConfiguration("iris");
const resolvedConfig = resolveConfiguration({
iris: {
serverPath: config.get<string>("serverPath"),
sourceCommand: config.get<SourceCommand | null>("sourceCommand"),
client: {
serverPath: clientConfig.get<string>("serverPath"),
},
purescriptAnalyzer: {
serverPath: legacyConfig.get<string>("serverPath"),
sourceCommand: legacyConfig.get<SourceCommand | null>("sourceCommand"),
iris: {
serverPath: irisConfig.get<string>("serverPath"),
sourceCommand: irisConfig.get<SourceCommand | null>("sourceCommand"),
},
});

const args: string[] = [];
const args = ["lsp"];
if (resolvedConfig.sourceCommand) {
args.push(
"--config",
Expand Down
8 changes: 3 additions & 5 deletions test/integration/runTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ async function main() {
"--skip-release-notes",
"--skip-welcome",
],
extensionTestsEnv: {
IRIS_PATH: irisPath,
},
});
}

Expand Down Expand Up @@ -163,8 +160,9 @@ function prepareWorkspace(
path.join(vscodeDirectory, "settings.json"),
JSON.stringify(
{
"iris.serverPath": irisPath,
"iris.sourceCommand": {
"iris.client.serverPath": irisPath,
"iris.server.sources": {
kind: "command",
program: process.execPath,
arguments: [sourceFilesScript],
},
Expand Down
18 changes: 0 additions & 18 deletions test/integration/suite/features/activation.test.ts

This file was deleted.

Loading
Loading