Skip to content

Update compatibility profiles for PowerShell 7 #1429

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

Merged
merged 22 commits into from
Mar 31, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,14 @@ public Tuple<string, Version, ModuleData> GetCoreModuleData()
var moduleData = new ModuleData();

IEnumerable<CommandInfo> coreCommands = _pwsh.AddCommand(GcmInfo)
.AddParameter("Module", CORE_MODULE_NAME)
.InvokeAndClear<CommandInfo>();
.AddParameter("Type", CommandTypes.Alias | CommandTypes.Cmdlet | CommandTypes.Function)
.InvokeAndClear<CommandInfo>()
.Where(commandInfo => string.IsNullOrEmpty(commandInfo.ModuleName) || CORE_MODULE_NAME.Equals(commandInfo.ModuleName, StringComparison.OrdinalIgnoreCase));

var cmdletData = new JsonCaseInsensitiveStringDictionary<CmdletData>();
var functionData = new JsonCaseInsensitiveStringDictionary<FunctionData>();
var aliases = new JsonCaseInsensitiveStringDictionary<string>();
var aliasesToRequest = new List<string>();
foreach (CommandInfo command in coreCommands)
{
switch (command)
Expand Down Expand Up @@ -315,6 +318,24 @@ public Tuple<string, Version, ModuleData> GetCoreModuleData()
}
continue;

case AliasInfo alias:
try
{
// Some aliases won't resolve unless specified specifically
if (alias.Definition == null)
{
aliasesToRequest.Add(alias.Name);
continue;
}

aliases.Add(alias.Name, alias.Definition);
}
catch (RuntimeException)
{
// Ignore aliases that have trouble loading
}
continue;

default:
throw new CompatibilityAnalysisException($"Command {command.Name} in core module is of unsupported type {command.CommandType}");
}
Expand All @@ -323,15 +344,31 @@ public Tuple<string, Version, ModuleData> GetCoreModuleData()
moduleData.Cmdlets = cmdletData;
moduleData.Functions = functionData;

if (aliasesToRequest != null && aliasesToRequest.Count > 0)
{
IEnumerable<AliasInfo> resolvedAliases = _pwsh.AddCommand(GcmInfo)
.AddParameter("Name", aliasesToRequest)
.InvokeAndClear<AliasInfo>();

foreach (AliasInfo resolvedAlias in resolvedAliases)
{
if (resolvedAlias?.Definition == null)
{
continue;
}

aliases[resolvedAlias.Name] = resolvedAlias.Definition;
}
}

// Get default variables and core aliases out of a fresh runspace
using (SMA.PowerShell freshPwsh = SMA.PowerShell.Create(RunspaceMode.NewRunspace))
{
Collection<PSObject> varsAndAliases = freshPwsh.AddCommand("Get-ChildItem")
.AddParameter("Path", "variable:,alias:")
.AddParameter("Path", "variable:")
.InvokeAndClear();

var variables = new List<string>();
var aliases = new JsonCaseInsensitiveStringDictionary<string>();

foreach (PSObject returnedObject in varsAndAliases)
{
Expand All @@ -341,10 +378,6 @@ public Tuple<string, Version, ModuleData> GetCoreModuleData()
variables.Add(variable.Name);
continue;

case AliasInfo alias:
aliases.Add(alias.Name, GetSingleAliasData(alias));
continue;

// Skip over other objects we get back, since there's no reason to throw
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,30 @@ namespace Microsoft.PowerShell.CrossCompatibility.Query
/// </summary>
public class CommonPowerShellData
{
private readonly Lazy<Tuple<IReadOnlyDictionary<string, ParameterData>, IReadOnlyDictionary<string, ParameterData>>> _parameters;

/// <summary>
/// Create a new query object for common PowerShell data.
/// </summary>
/// <param name="commonPowerShellData">The mutable data object holding common data information.</param>
public CommonPowerShellData(Data.CommonPowerShellData commonPowerShellData)
{
_parameters = new Lazy<Tuple<IReadOnlyDictionary<string, ParameterData>, IReadOnlyDictionary<string, ParameterData>>>(() => CreateParameterTable(commonPowerShellData.Parameters, commonPowerShellData.ParameterAliases));
Parameters = CreateParameterTable(commonPowerShellData.Parameters, commonPowerShellData.ParameterAliases, out IReadOnlyDictionary<string, ParameterData> parameterAliases);
ParameterAliases = parameterAliases;
}

/// <summary>
/// Common parameters, present on all commands bound with the cmdlet binding.
/// </summary>
public IReadOnlyDictionary<string, ParameterData> Parameters => _parameters.Value.Item1;
public IReadOnlyDictionary<string, ParameterData> Parameters { get; }

/// <summary>
/// Aliases for common parameters.
/// </summary>
public IReadOnlyDictionary<string, ParameterData> ParameterAliases => _parameters.Value.Item2;
public IReadOnlyDictionary<string, ParameterData> ParameterAliases { get; }

private Tuple<IReadOnlyDictionary<string, ParameterData>, IReadOnlyDictionary<string, ParameterData>> CreateParameterTable(
private IReadOnlyDictionary<string, ParameterData> CreateParameterTable(
IReadOnlyDictionary<string, Data.ParameterData> parameters,
IReadOnlyDictionary<string, string> parameterAliases)
IReadOnlyDictionary<string, string> parameterAliases,
out IReadOnlyDictionary<string, ParameterData> queryAliases)
{
var parameterDict = new Dictionary<string, ParameterData>(parameters.Count + parameterAliases.Count, StringComparer.OrdinalIgnoreCase);
var parameterAliasDict = new Dictionary<string, ParameterData>(parameterAliases.Count, StringComparer.OrdinalIgnoreCase);
Expand All @@ -52,9 +52,8 @@ private Tuple<IReadOnlyDictionary<string, ParameterData>, IReadOnlyDictionary<st
parameterDict[parameterAlias.Key] = aliasedParameter;
}

return new Tuple<IReadOnlyDictionary<string, ParameterData>, IReadOnlyDictionary<string, ParameterData>>(
parameterDict,
parameterAliasDict);
queryAliases = parameterAliasDict;
return parameterDict;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,32 @@ namespace Microsoft.PowerShell.CrossCompatibility.Query
/// </summary>
public abstract class CommandData
{
protected readonly Data.CommandData _commandData;

/// <summary>
/// Create a new command data query object from the data object.
/// </summary>
/// <param name="name">The name of the command.</param>
/// <param name="commandData">The command data object describing the command.</param>
protected CommandData(string name, Data.CommandData commandData)
{
_commandData = commandData;
Name = name;
DefaultParameterSet = commandData.DefaultParameterSet;

if (commandData.OutputType != null)
{
OutputType = new List<string>(commandData.OutputType);
}

if (commandData.ParameterSets != null)
{
ParameterSets = new List<string>(commandData.ParameterSets);
}

var parameters = new Dictionary<string, ParameterData>(StringComparer.OrdinalIgnoreCase);
var paramAliases = new Dictionary<string, ParameterData>(StringComparer.OrdinalIgnoreCase);

if (commandData.Parameters != null)
{
foreach (KeyValuePair<string, Microsoft.PowerShell.CrossCompatibility.Data.ParameterData> parameter in commandData.Parameters)
foreach (KeyValuePair<string, Data.ParameterData> parameter in commandData.Parameters)
{
parameters.Add(parameter.Key, new ParameterData(parameter.Key, parameter.Value));
}
Expand Down Expand Up @@ -59,17 +67,17 @@ protected CommandData(string name, Data.CommandData commandData)
/// <summary>
/// The output types of the command, if any.
/// </summary>
public IReadOnlyList<string> OutputType => _commandData.OutputType;
public IReadOnlyList<string> OutputType { get; }

/// <summary>
/// The parameter sets of the command, if any.
/// </summary>
public IReadOnlyList<string> ParameterSets => _commandData.ParameterSets;
public IReadOnlyList<string> ParameterSets { get; }

/// <summary>
/// The default parameter set of the command, if any.
/// </summary>
public string DefaultParameterSet => _commandData.DefaultParameterSet;
public string DefaultParameterSet { get; }

/// <summary>
/// Parameter aliases of the command.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ public class FunctionData : CommandData
public FunctionData(string name, Data.FunctionData functionData)
: base(name, functionData)
{
IsCmdletBinding = functionData.CmdletBinding;
}

/// <summary>
/// True if this is an advanced function (has a cmdlet binding), false otherwise.
/// </summary>
public override bool IsCmdletBinding => ((Data.FunctionData)_commandData).CmdletBinding;
public override bool IsCmdletBinding { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Data = Microsoft.PowerShell.CrossCompatibility.Data;

namespace Microsoft.PowerShell.CrossCompatibility.Query
Expand All @@ -13,30 +14,24 @@ namespace Microsoft.PowerShell.CrossCompatibility.Query
/// </summary>
public class ModuleData
{
private readonly RuntimeData _parent;

private readonly Data.ModuleData _moduleData;

private readonly Lazy<Tuple<IReadOnlyDictionary<string, FunctionData>, IReadOnlyDictionary<string, CmdletData>>> _lazyCommands;

private readonly Lazy<IReadOnlyDictionary<string, IReadOnlyList<CommandData>>> _lazyAliases;

/// <summary>
/// Create a query object around a module data object.
/// </summary>
/// <param name="name">The name of the module.</param>
/// <param name="version">The version of the module.</param>
/// <param name="moduleData">The module data object.</param>
public ModuleData(string name, Version version, RuntimeData parent, Data.ModuleData moduleData)
public ModuleData(string name, Version version, Data.ModuleData moduleData)
{
_moduleData = moduleData;
_parent = parent;

Name = name;
Version = version;

_lazyCommands = new Lazy<Tuple<IReadOnlyDictionary<string, FunctionData>, IReadOnlyDictionary<string, CmdletData>>>(() => CreateCommandTables(moduleData.Functions, moduleData.Cmdlets));
_lazyAliases = new Lazy<IReadOnlyDictionary<string, IReadOnlyList<CommandData>>>(() => CreateAliasTable(_moduleData.Aliases));
Guid = moduleData.Guid;
Tuple<IReadOnlyDictionary<string, FunctionData>, IReadOnlyDictionary<string, CmdletData>> commands = CreateCommandTables(moduleData.Functions, moduleData.Cmdlets);
Functions = commands.Item1;
Cmdlets = commands.Item2;
if (moduleData.Variables != null)
{
Variables = new List<string>(moduleData.Variables);
}
}

/// <summary>
Expand All @@ -52,45 +47,47 @@ public ModuleData(string name, Version version, RuntimeData parent, Data.ModuleD
/// <summary>
/// The GUID of the module.
/// </summary>
public Guid Guid => _moduleData.Guid;
public Guid Guid { get; }

/// <summary>
/// Functions exported by the module.
/// </summary>
public IReadOnlyDictionary<string, FunctionData> Functions => _lazyCommands.Value.Item1;
public IReadOnlyDictionary<string, FunctionData> Functions { get; }

/// <summary>
/// Cmdlets exported by the module.
/// </summary>
public IReadOnlyDictionary<string, CmdletData> Cmdlets => _lazyCommands.Value.Item2;
public IReadOnlyDictionary<string, CmdletData> Cmdlets { get; }

/// <summary>
/// Variables exported by the module.
/// </summary>
public IReadOnlyList<string> Variables => _moduleData.Variables;
public IReadOnlyList<string> Variables { get; }

/// <summary>
/// Aliases exported by the module.
/// </summary>
public IReadOnlyDictionary<string, IReadOnlyList<CommandData>> Aliases => _lazyAliases.Value;
public IReadOnlyDictionary<string, IReadOnlyList<CommandData>> Aliases { get; private set; }

private IReadOnlyDictionary<string, IReadOnlyList<CommandData>> CreateAliasTable(IReadOnlyDictionary<string, string> aliases)
internal void SetAliasTable(
RuntimeData runtimeData,
IReadOnlyDictionary<string, string> aliases)
{
if (aliases == null || aliases.Count == 0)
{
return null;
return;
}

var aliasTable = new Dictionary<string, IReadOnlyList<CommandData>>(StringComparer.OrdinalIgnoreCase);
foreach (KeyValuePair<string, string> alias in aliases)
{
if (_parent.Aliases.TryGetValue(alias.Key, out IReadOnlyList<CommandData> aliasedCommands))
if (runtimeData.Aliases.TryGetValue(alias.Key, out IReadOnlyList<CommandData> aliasedCommands))
{
aliasTable[alias.Key] = aliasedCommands;
}
}

return aliasTable;
Aliases = aliasTable;
}

private static Tuple<IReadOnlyDictionary<string, FunctionData>, IReadOnlyDictionary<string, CmdletData>> CreateCommandTables(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,37 +12,37 @@ namespace Microsoft.PowerShell.CrossCompatibility.Query
/// </summary>
public class ParameterData
{
private readonly Data.ParameterData _parameterData;

private readonly Lazy<IReadOnlyDictionary<string, ParameterSetData>> _parameterSets;

/// <summary>
/// Create a new parameter query object from the parameter name and its data object.
/// </summary>
/// <param name="name">The name of the parameter.</param>
/// <param name="parameterData">The parameter data object.</param>
public ParameterData(string name, Data.ParameterData parameterData)
{
_parameterData = parameterData;
_parameterSets = new Lazy<IReadOnlyDictionary<string, ParameterSetData>>(() => CreateParameterSetDictionary(_parameterData.ParameterSets));
Name = name;
Type = parameterData.Type;
IsDynamic = parameterData.Dynamic;
if (parameterData.ParameterSets != null)
{
ParameterSets = CreateParameterSetDictionary(parameterData.ParameterSets);
}
}

/// <summary>
/// The parameter sets of the object.
/// </summary>
/// <value></value>
public IReadOnlyDictionary<string, ParameterSetData> ParameterSets => _parameterSets.Value;
public IReadOnlyDictionary<string, ParameterSetData> ParameterSets { get; }

/// <summary>
/// The name of the type of the object.
/// </summary>
public string Type => _parameterData.Type;
public string Type { get; }

/// <summary>
/// True if this is a dynamic parameter, false otherwise.
/// </summary>
public bool IsDynamic => _parameterData.Dynamic;
public bool IsDynamic { get; }

/// <summary>
/// The name of the parameter.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ namespace Microsoft.PowerShell.CrossCompatibility.Query
/// </summary>
public class ParameterSetData
{
private readonly Modules.ParameterSetData _parameterSet;

/// <summary>
/// Create a parameter set query object from the parameter set name and data object.
/// </summary>
Expand All @@ -21,7 +19,8 @@ public class ParameterSetData
public ParameterSetData(string name, Modules.ParameterSetData parameterSetData)
{
Name = name;
_parameterSet = parameterSetData;
Flags = parameterSetData.Flags;
Position = parameterSetData.Position;
}

/// <summary>
Expand All @@ -32,12 +31,12 @@ public ParameterSetData(string name, Modules.ParameterSetData parameterSetData)
/// <summary>
/// Parameter set flags that are set.
/// </summary>
public IReadOnlyCollection<ParameterSetFlag> Flags => _parameterSet.Flags;
public IReadOnlyCollection<ParameterSetFlag> Flags { get; }

/// <summary>
/// The position of the parameter.
/// A negative position means no position is specified.
/// </summary>
public int Position => _parameterSet.Position;
public int Position { get; }
}
}
Loading