Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'editors/code/src/config.ts')
-rw-r--r--editors/code/src/config.ts184
1 files changed, 108 insertions, 76 deletions
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index eb4f965291..1faa0ad910 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -1,5 +1,6 @@
-import * as path from "path";
+import * as Is from "vscode-languageclient/lib/common/utils/is";
import * as os from "os";
+import * as path from "path";
import * as vscode from "vscode";
import { Env } from "./client";
import { log } from "./util";
@@ -47,7 +48,7 @@ export class Config {
}
private refreshLogging() {
- log.setEnabled(this.traceExtension);
+ log.setEnabled(this.traceExtension ?? false);
log.info("Extension version:", this.package.version);
const cfg = Object.entries(this.cfg).filter(([_, val]) => !(val instanceof Function));
@@ -86,58 +87,84 @@ export class Config {
* [1]: https://github.com/Microsoft/vscode/issues/11514#issuecomment-244707076
*/
private configureLanguage() {
- if (this.typingContinueCommentsOnNewline && !this.configureLang) {
+ // Only need to dispose of the config if there's a change
+ if (this.configureLang) {
+ this.configureLang.dispose();
+ this.configureLang = undefined;
+ }
+
+ let onEnterRules: vscode.OnEnterRule[] = [
+ {
+ // Carry indentation from the previous line
+ beforeText: /^\s*$/,
+ action: { indentAction: vscode.IndentAction.None },
+ },
+ {
+ // After the end of a function/field chain,
+ // with the semicolon on the same line
+ beforeText: /^\s+\..*;/,
+ action: { indentAction: vscode.IndentAction.Outdent },
+ },
+ {
+ // After the end of a function/field chain,
+ // with semicolon detached from the rest
+ beforeText: /^\s+;/,
+ previousLineText: /^\s+\..*/,
+ action: { indentAction: vscode.IndentAction.Outdent },
+ },
+ ];
+
+ if (this.typingContinueCommentsOnNewline) {
const indentAction = vscode.IndentAction.None;
- this.configureLang = vscode.languages.setLanguageConfiguration("rust", {
- onEnterRules: [
- {
- // Doc single-line comment
- // e.g. ///|
- beforeText: /^\s*\/{3}.*$/,
- action: { indentAction, appendText: "/// " },
- },
- {
- // Parent doc single-line comment
- // e.g. //!|
- beforeText: /^\s*\/{2}\!.*$/,
- action: { indentAction, appendText: "//! " },
- },
- {
- // Begins an auto-closed multi-line comment (standard or parent doc)
- // e.g. /** | */ or /*! | */
- beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/,
- afterText: /^\s*\*\/$/,
- action: {
- indentAction: vscode.IndentAction.IndentOutdent,
- appendText: " * ",
- },
- },
- {
- // Begins a multi-line comment (standard or parent doc)
- // e.g. /** ...| or /*! ...|
- beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/,
- action: { indentAction, appendText: " * " },
- },
- {
- // Continues a multi-line comment
- // e.g. * ...|
- beforeText: /^(\ \ )*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
- action: { indentAction, appendText: "* " },
+ onEnterRules = [
+ ...onEnterRules,
+ {
+ // Doc single-line comment
+ // e.g. ///|
+ beforeText: /^\s*\/{3}.*$/,
+ action: { indentAction, appendText: "/// " },
+ },
+ {
+ // Parent doc single-line comment
+ // e.g. //!|
+ beforeText: /^\s*\/{2}\!.*$/,
+ action: { indentAction, appendText: "//! " },
+ },
+ {
+ // Begins an auto-closed multi-line comment (standard or parent doc)
+ // e.g. /** | */ or /*! | */
+ beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/,
+ afterText: /^\s*\*\/$/,
+ action: {
+ indentAction: vscode.IndentAction.IndentOutdent,
+ appendText: " * ",
},
- {
- // Dedents after closing a multi-line comment
- // e.g. */|
- beforeText: /^(\ \ )*\ \*\/\s*$/,
- action: { indentAction, removeText: 1 },
- },
- ],
- });
- }
- if (!this.typingContinueCommentsOnNewline && this.configureLang) {
- this.configureLang.dispose();
- this.configureLang = undefined;
+ },
+ {
+ // Begins a multi-line comment (standard or parent doc)
+ // e.g. /** ...| or /*! ...|
+ beforeText: /^\s*\/\*(\*|\!)(?!\/)([^\*]|\*(?!\/))*$/,
+ action: { indentAction, appendText: " * " },
+ },
+ {
+ // Continues a multi-line comment
+ // e.g. * ...|
+ beforeText: /^(\ \ )*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
+ action: { indentAction, appendText: "* " },
+ },
+ {
+ // Dedents after closing a multi-line comment
+ // e.g. */|
+ beforeText: /^(\ \ )*\ \*\/\s*$/,
+ action: { indentAction, removeText: 1 },
+ },
+ ];
}
+
+ this.configureLang = vscode.languages.setLanguageConfiguration("rust", {
+ onEnterRules,
+ });
}
// We don't do runtime config validation here for simplicity. More on stackoverflow:
@@ -163,18 +190,24 @@ export class Config {
* ```
* So this getter handles this quirk by not requiring the caller to use postfix `!`
*/
- private get<T>(path: string): T {
- return this.cfg.get<T>(path)!;
+ private get<T>(path: string): T | undefined {
+ return substituteVSCodeVariables(this.cfg.get<T>(path));
}
get serverPath() {
return this.get<null | string>("server.path") ?? this.get<null | string>("serverPath");
}
+
get serverExtraEnv(): Env {
const extraEnv =
this.get<{ [key: string]: string | number } | null>("server.extraEnv") ?? {};
- return Object.fromEntries(
- Object.entries(extraEnv).map(([k, v]) => [k, typeof v !== "string" ? v.toString() : v])
+ return substituteVariablesInEnv(
+ Object.fromEntries(
+ Object.entries(extraEnv).map(([k, v]) => [
+ k,
+ typeof v !== "string" ? v.toString() : v,
+ ])
+ )
);
}
get traceExtension() {
@@ -216,13 +249,13 @@ export class Config {
if (sourceFileMap !== "auto") {
// "/rustc/<id>" used by suggestions only.
const { ["/rustc/<id>"]: _, ...trimmed } =
- this.get<Record<string, string>>("debug.sourceFileMap");
+ this.get<Record<string, string>>("debug.sourceFileMap") ?? {};
sourceFileMap = trimmed;
}
return {
engine: this.get<string>("debug.engine"),
- engineSettings: this.get<object>("debug.engineSettings"),
+ engineSettings: this.get<object>("debug.engineSettings") ?? {},
openDebugPane: this.get<boolean>("debug.openDebugPane"),
sourceFileMap: sourceFileMap,
};
@@ -247,37 +280,25 @@ export class Config {
}
}
-const VarRegex = new RegExp(/\$\{(.+?)\}/g);
-
-export function substituteVSCodeVariableInString(val: string): string {
- return val.replace(VarRegex, (substring: string, varName) => {
- if (typeof varName === "string") {
- return computeVscodeVar(varName) || substring;
- } else {
- return substring;
- }
- });
-}
-
-export function substituteVSCodeVariables(resp: any): any {
- if (typeof resp === "string") {
- return substituteVSCodeVariableInString(resp);
- } else if (resp && Array.isArray(resp)) {
+export function substituteVSCodeVariables<T>(resp: T): T {
+ if (Is.string(resp)) {
+ return substituteVSCodeVariableInString(resp) as T;
+ } else if (resp && Is.array<any>(resp)) {
return resp.map((val) => {
return substituteVSCodeVariables(val);
- });
+ }) as T;
} else if (resp && typeof resp === "object") {
const res: { [key: string]: any } = {};
for (const key in resp) {
const val = resp[key];
res[key] = substituteVSCodeVariables(val);
}
- return res;
- } else if (typeof resp === "function") {
- return null;
+ return res as T;
}
return resp;
}
+
+// FIXME: Merge this with `substituteVSCodeVariables` above
export function substituteVariablesInEnv(env: Env): Env {
const missingDeps = new Set<string>();
// vscode uses `env:ENV_NAME` for env vars resolution, and it's easier
@@ -355,6 +376,17 @@ export function substituteVariablesInEnv(env: Env): Env {
return resolvedEnv;
}
+const VarRegex = new RegExp(/\$\{(.+?)\}/g);
+function substituteVSCodeVariableInString(val: string): string {
+ return val.replace(VarRegex, (substring: string, varName) => {
+ if (Is.string(varName)) {
+ return computeVscodeVar(varName) || substring;
+ } else {
+ return substring;
+ }
+ });
+}
+
function computeVscodeVar(varName: string): string | null {
const workspaceFolder = () => {
const folders = vscode.workspace.workspaceFolders ?? [];