Skip to content

Commit 82dad1a

Browse files
authored
UseCorrectCasing: Fix wildcard lookups for command lookup and do not append .exe for applications on Windows (#1210)
* UseCorrectCasing: Fix special case of ? for command lookup and do not correct application names to end in .exe on Windows * Use more generic WildcardPattern.Escape method * Remove application extension more generically and on Windows only * Make applications with an extension preserver the extension and re-use isWindows variable better * Apply suggestions from code review Co-Authored-By: bergmeister <c.bergmeister@gmail.com>
1 parent b0399bc commit 82dad1a

File tree

3 files changed

+40
-2
lines changed

3 files changed

+40
-2
lines changed

Engine/CommandInfoCache.cs

+4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ public CommandInfo GetCommandInfoLegacy(string commandOrAliasName, CommandTypes?
6666
/// <returns>Returns null if command does not exists</returns>
6767
private static CommandInfo GetCommandInfoInternal(string cmdName, CommandTypes? commandType)
6868
{
69+
// 'Get-Command ?' would return % for example due to PowerShell interpreting is a single-character-wildcard search and not just the ? alias.
70+
// For more details see https://github.com/PowerShell/PowerShell/issues/9308
71+
cmdName = WildcardPattern.Escape(cmdName);
72+
6973
using (var ps = System.Management.Automation.PowerShell.Create())
7074
{
7175
ps.AddCommand("Get-Command")

Rules/UseCorrectCasing.cs

+15-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
using System.Collections.Generic;
66
using System.Management.Automation.Language;
77
using Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic;
8+
using System.Management.Automation;
9+
using System.IO;
10+
using System.Runtime.InteropServices;
811
#if !CORECLR
912
using System.ComponentModel.Composition;
1013
#endif
@@ -29,6 +32,11 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
2932

3033
IEnumerable<Ast> commandAsts = ast.FindAll(testAst => testAst is CommandAst, true);
3134

35+
bool isWindows = true;
36+
#if CORECLR
37+
isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
38+
#endif
39+
3240
// Iterates all CommandAsts and check the command name.
3341
foreach (CommandAst commandAst in commandAsts)
3442
{
@@ -52,6 +60,12 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
5260
var fullyqualifiedName = $"{commandInfo.ModuleName}\\{shortName}";
5361
var isFullyQualified = commandName.Equals(fullyqualifiedName, StringComparison.OrdinalIgnoreCase);
5462
var correctlyCasedCommandName = isFullyQualified ? fullyqualifiedName : shortName;
63+
if (isWindows && commandInfo.CommandType == CommandTypes.Application && !Path.HasExtension(commandName))
64+
{
65+
// For binaries that could exist on both Windows and Linux like e.g. git we do not want to expand
66+
// git to git.exe to keep the script cross-platform compliant
67+
correctlyCasedCommandName = Path.GetFileNameWithoutExtension(correctlyCasedCommandName);
68+
}
5569

5670
if (!commandName.Equals(correctlyCasedCommandName, StringComparison.Ordinal))
5771
{
@@ -158,4 +172,4 @@ public override string GetSourceName()
158172
return string.Format(CultureInfo.CurrentCulture, Strings.SourceName);
159173
}
160174
}
161-
}
175+
}

Tests/Rules/UseCorrectCasing.tests.ps1

+21-1
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,31 @@ Describe "UseCorrectCasing" {
1111
Invoke-Formatter '"$(get-childitem)"' | Should -Be '"$(get-childitem)"'
1212
}
1313

14+
It "Corrects alias correctly" {
15+
Invoke-Formatter 'Gci' | Should -Be 'gci'
16+
Invoke-Formatter '?' | Should -Be '?'
17+
}
18+
19+
It "Corrects applications on Windows to not end in .exe" -Skip:($IsLinux -or $IsMacOS) {
20+
Invoke-Formatter 'Cmd' | Should -Be 'cmd'
21+
Invoke-Formatter 'Cmd' | Should -Be 'cmd'
22+
Invoke-Formatter 'MORE' | Should -Be 'more'
23+
Invoke-Formatter 'WinRM' | Should -Be 'winrm'
24+
Invoke-Formatter 'CertMgr' | Should -Be 'certmgr'
25+
}
26+
27+
It "Preserves extension of applications on Windows" -Skip:($IsLinux -or $IsMacOS) {
28+
Invoke-Formatter 'Cmd.exe' | Should -Be 'cmd.exe'
29+
Invoke-Formatter 'MORE.com' | Should -Be 'more.com'
30+
Invoke-Formatter 'WinRM.cmd' | Should -Be 'winrm.cmd'
31+
Invoke-Formatter 'CertMgr.MSC' | Should -Be 'certmgr.msc'
32+
}
33+
1434
It "corrects case of script function" {
1535
function Invoke-DummyFunction
1636
{
1737

1838
}
1939
Invoke-Formatter 'invoke-dummyFunction' | Should -Be 'Invoke-DummyFunction'
2040
}
21-
}
41+
}

0 commit comments

Comments
 (0)