Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UseCorrectCasing: Fix wildcard lookups for command lookup and do not append .exe for applications on Windows #1210

Merged
4 changes: 4 additions & 0 deletions Engine/CommandInfoCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ public CommandInfo GetCommandInfoLegacy(string commandOrAliasName, CommandTypes?
/// <returns>Returns null if command does not exists</returns>
private static CommandInfo GetCommandInfoInternal(string cmdName, CommandTypes? commandType)
{
// 'Get-Command ?' would return % for example due to PowerShell interpreting is a single-character-wildcard search and not just the ? alias.
// For more details see https://github.com/PowerShell/PowerShell/issues/9308
cmdName = WildcardPattern.Escape(cmdName);

using (var ps = System.Management.Automation.PowerShell.Create())
{
ps.AddCommand("Get-Command")
Expand Down
16 changes: 15 additions & 1 deletion Rules/UseCorrectCasing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
using System.Collections.Generic;
using System.Management.Automation.Language;
using Microsoft.Windows.PowerShell.ScriptAnalyzer.Generic;
using System.Management.Automation;
using System.IO;
using System.Runtime.InteropServices;
#if !CORECLR
using System.ComponentModel.Composition;
#endif
Expand All @@ -29,6 +32,11 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file

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

bool isWindows = true;
#if CORECLR
isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
#endif

// Iterates all CommandAsts and check the command name.
foreach (CommandAst commandAst in commandAsts)
{
Expand All @@ -52,6 +60,12 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file
var fullyqualifiedName = $"{commandInfo.ModuleName}\\{shortName}";
var isFullyQualified = commandName.Equals(fullyqualifiedName, StringComparison.OrdinalIgnoreCase);
var correctlyCasedCommandName = isFullyQualified ? fullyqualifiedName : shortName;
if (isWindows && commandInfo.CommandType == CommandTypes.Application && !Path.HasExtension(commandName))
{
// For binaries that could exist on both Windows and Linux like e.g. git we do not want to expand
// git to git.exe to keep the script cross-platform compliant
correctlyCasedCommandName = Path.GetFileNameWithoutExtension(correctlyCasedCommandName);
bergmeister marked this conversation as resolved.
Show resolved Hide resolved
}

if (!commandName.Equals(correctlyCasedCommandName, StringComparison.Ordinal))
{
Expand Down Expand Up @@ -158,4 +172,4 @@ public override string GetSourceName()
return string.Format(CultureInfo.CurrentCulture, Strings.SourceName);
}
}
}
}
22 changes: 21 additions & 1 deletion Tests/Rules/UseCorrectCasing.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,31 @@ Describe "UseCorrectCasing" {
Invoke-Formatter '"$(get-childitem)"' | Should -Be '"$(get-childitem)"'
}

It "Corrects alias correctly" {
Invoke-Formatter 'Gci' | Should -Be 'gci'
Invoke-Formatter '?' | Should -Be '?'
}

It "Corrects applications on Windows to not end in .exe" -Skip:($IsLinux -or $IsMacOS) {
Invoke-Formatter 'Cmd' | Should -Be 'cmd'
bergmeister marked this conversation as resolved.
Show resolved Hide resolved
Invoke-Formatter 'Cmd' | Should -Be 'cmd'
Invoke-Formatter 'MORE' | Should -Be 'more'
Invoke-Formatter 'WinRM' | Should -Be 'winrm'
Invoke-Formatter 'CertMgr' | Should -Be 'certmgr'
}

It "Preserves extension of applications on Windows" -Skip:($IsLinux -or $IsMacOS) {
Invoke-Formatter 'Cmd.exe' | Should -Be 'cmd.exe'
bergmeister marked this conversation as resolved.
Show resolved Hide resolved
Invoke-Formatter 'MORE.com' | Should -Be 'more.com'
Invoke-Formatter 'WinRM.cmd' | Should -Be 'winrm.cmd'
Invoke-Formatter 'CertMgr.MSC' | Should -Be 'certmgr.msc'
}

It "corrects case of script function" {
function Invoke-DummyFunction
{

}
Invoke-Formatter 'invoke-dummyFunction' | Should -Be 'Invoke-DummyFunction'
}
}
}