Skip to content

Commit

Permalink
UseCorrectCasing: Do not use CommandInfoCache when CommandInfoParamet…
Browse files Browse the repository at this point in the history
…ers property throws due to runspace affinity problem of PowerShell engine (#1523)

* UseCorrectCasing: Do not use CommandInfoCache because Parameters property has runspace affinity problems

* Catch exception and only bypass cache then

* Add test

Co-authored-by: Christoph Bergmeister <[email protected]>
  • Loading branch information
bergmeister and Christoph Bergmeister authored Jun 30, 2020
1 parent 562b8c3 commit d04c039
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 4 deletions.
7 changes: 6 additions & 1 deletion Engine/CommandInfoCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,20 @@ protected virtual void Dispose(bool disposing)
/// </summary>
/// <param name="commandName">Name of the command to get a commandinfo object for.</param>
/// <param name="commandTypes">What types of command are needed. If omitted, all types are retrieved.</param>
/// <param name="bypassCache">When needed due to runspace affinity problems of some PowerShell objects.</param>
/// <returns></returns>
public CommandInfo GetCommandInfo(string commandName, CommandTypes? commandTypes = null)
public CommandInfo GetCommandInfo(string commandName, CommandTypes? commandTypes = null, bool bypassCache = false)
{
if (string.IsNullOrWhiteSpace(commandName))
{
return null;
}

var key = new CommandLookupKey(commandName, commandTypes);
if (bypassCache)
{
return GetCommandInfoInternal(commandName, commandTypes);
}
// Atomically either use PowerShell to query a command info object, or fetch it from the cache
return _commandInfoCache.GetOrAdd(key, new Lazy<CommandInfo>(() => GetCommandInfoInternal(commandName, commandTypes))).Value;
}
Expand Down
5 changes: 3 additions & 2 deletions Engine/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -673,10 +673,11 @@ public bool PositionalParameterUsed(CommandAst cmdAst, bool moreThanTwoPositiona
/// </summary>
/// <param name="name"></param>
/// <param name="commandType"></param>
/// <param name="bypassCache"></param>
/// <returns></returns>
public CommandInfo GetCommandInfo(string name, CommandTypes? commandType = null)
public CommandInfo GetCommandInfo(string name, CommandTypes? commandType = null, bool bypassCache = false)
{
return CommandInfoCache.GetCommandInfo(name, commandTypes: commandType);
return CommandInfoCache.GetCommandInfo(name, commandTypes: commandType, bypassCache: bypassCache);
}

/// <summary>
Expand Down
14 changes: 13 additions & 1 deletion Rules/UseCorrectCasing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,19 @@ public override IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string file

var commandParameterAsts = commandAst.FindAll(
testAst => testAst is CommandParameterAst, true).Cast<CommandParameterAst>();
var availableParameters = commandInfo.Parameters;
Dictionary<string, ParameterMetadata> availableParameters;
try
{
availableParameters = commandInfo.Parameters;
}
// It's a known issue that objects from PowerShell can have a runspace affinity,
// therefore if that happens, we query a fresh object instead of using the cache.
// https://github.com/PowerShell/PowerShell/issues/4003
catch (InvalidOperationException)
{
commandInfo = Helper.Instance.GetCommandInfo(commandName, bypassCache: true);
availableParameters = commandInfo.Parameters;
}
foreach (var commandParameterAst in commandParameterAsts)
{
var parameterName = commandParameterAst.ParameterName;
Expand Down
9 changes: 9 additions & 0 deletions Tests/Rules/UseCorrectCasing.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,13 @@ Describe "UseCorrectCasing" {
Invoke-Formatter 'Get-Process -NonExistingParameterName' -ErrorAction Stop
}

It "Does not throw when correcting certain cmdlets (issue 1516)" {
$scriptDefinition = 'Get-Content;Test-Path;Get-ChildItem;Get-Content;Test-Path;Get-ChildItem'
$settings = @{ 'Rules' = @{ 'PSUseCorrectCasing' = @{ 'Enable' = $true } } }
{
1..100 |
ForEach-Object { $null = Invoke-ScriptAnalyzer -ScriptDefinition $scriptDefinition -Settings $settings -ErrorAction Stop }
} |
Should -Not -Throw
}
}

0 comments on commit d04c039

Please sign in to comment.