Skip to content

Commit 7b80144

Browse files
authored
Improve variable detection (#10)
1 parent a9d4c36 commit 7b80144

File tree

7 files changed

+445
-36
lines changed

7 files changed

+445
-36
lines changed

.devcontainer/devcontainer.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
"build": {
66
"dockerfile": "Dockerfile",
77
// Update 'VARIANT' to pick a Node version: 10, 12, 14
8-
"args": {
8+
"args": {
99
"VARIANT": "14"
1010
}
1111
},
1212

1313
// Set *default* container specific settings.json values on container create.
14-
"settings": {
14+
"settings": {
1515
"terminal.integrated.shell.linux": "/bin/bash"
1616
},
1717

@@ -29,4 +29,4 @@
2929

3030
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
3131
"remoteUser": "node"
32-
}
32+
}

.vscode/settings.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@
77
"out": true // set this to false to include "out" folder in search results
88
},
99
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
10-
"typescript.tsc.autoDetect": "off"
11-
}
10+
"typescript.tsc.autoDetect": "off",
11+
"files.trimTrailingWhitespace": true,
12+
"files.insertFinalNewline": true
13+
}

.yarnrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
--ignore-engines true
1+
--ignore-engines true

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,4 @@
4343
"vscode-test": "^1.5.0",
4444
"vsce": "^1.87.1"
4545
}
46-
}
46+
}

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ export function activate(context: vscode.ExtensionContext) {
55
context.subscriptions.push(vscode.languages.registerInlineValuesProvider('powershell', new PowerShellVariableInlineValuesProvider()));
66
}
77

8-
export function deactivate() {}
8+
export function deactivate() { }

src/powerShellVariableInlineValuesProvider.ts

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,24 @@ import * as vscode from 'vscode';
22

33
export class PowerShellVariableInlineValuesProvider implements vscode.InlineValuesProvider {
44

5-
provideInlineValues(document: vscode.TextDocument, viewport: vscode.Range, context: vscode.InlineValueContext) : vscode.ProviderResult<vscode.InlineValue[]> {
5+
// Known constants
6+
private readonly knownConstants = /^\$(?:true|false|null)$/i;
7+
8+
// https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-5.1#scope-modifiers
9+
private readonly supportedScopes = /^(?:global|local|script|private|using|variable)$/i;
10+
11+
// Variable patterns
12+
// https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_variables?view=powershell-5.1#variable-names-that-include-special-characters
13+
private readonly alphanumChars = /(?:\p{Lu}|\p{Ll}|\p{Lt}|\p{Lm}|\p{Lo}|\p{Nd}|[_?])/.source;
14+
private readonly variableRegex = new RegExp([
15+
'(?:\\$\\{(?<specialName>.*?)(?<!`)\\})', // Special characters variables. Lazy match until unescaped }
16+
`(?:\\$\\w+:${this.alphanumChars}+)`, // Scoped variables
17+
`(?:\\$${this.alphanumChars}+)`, // Normal variables
18+
].join('|'), 'giu'); // u flag to support unicode char classes
19+
20+
provideInlineValues(document: vscode.TextDocument, viewport: vscode.Range, context: vscode.InlineValueContext): vscode.ProviderResult<vscode.InlineValue[]> {
621
const allValues: vscode.InlineValue[] = [];
722

8-
const ignoredVariables = /^\$(?:true|false|null)$/i;
9-
1023
for (let l = 0; l <= context.stoppedLocation.end.line; l++) {
1124
const line = document.lineAt(l);
1225

@@ -15,26 +28,26 @@ export class PowerShellVariableInlineValuesProvider implements vscode.InlineValu
1528
continue;
1629
}
1730

18-
const variableMatches = /(?:\${(.*)})|(?:\$\S+:\S+)|(?:\$\S+)/gi;
19-
for (let match = variableMatches.exec(line.text); match; match = variableMatches.exec(line.text)) {
20-
// If we're looking at an "anything goes" variable, that has a capture group so use that instead
31+
for (let match = this.variableRegex.exec(line.text); match; match = this.variableRegex.exec(line.text)) {
32+
// If we're looking at special characters variable, use the extracted variable name in capture group
2133
let varName = match[0][1] === '{'
22-
? '$' + match[1]
34+
? '$' + match.groups?.specialName?.replace(/`(.)/g, '$1') // Remove backticks used as escape char for curly braces, unicode etc.
2335
: match[0];
2436

2537
// If there's a scope, we need to remove it
2638
const colon = varName.indexOf(':');
2739
if (colon !== -1) {
28-
varName = '$' + varName.substring(colon + 1);
29-
}
40+
// If invalid scope, ignore
41+
const scope = varName.substring(1, colon);
42+
if (!this.supportedScopes.test(scope)) {
43+
continue;
44+
}
3045

31-
// These characters need to be trimmed off
32-
if ([';', ',', '-', '+', '/', '*'].includes(varName[varName.length - 1])) {
33-
varName = varName.substring(0, varName.length - 1);
46+
varName = '$' + varName.substring(colon + 1);
3447
}
3548

3649
// If known PowerShell constant, ignore
37-
if (ignoredVariables.test(varName)) {
50+
if (this.knownConstants.test(varName)) {
3851
continue;
3952
}
4053

0 commit comments

Comments
 (0)