Skip to content

Commit

Permalink
Refactoring conventions (microsoft#2679)
Browse files Browse the repository at this point in the history
  • Loading branch information
BernieWhite authored Dec 21, 2024
1 parent 5c1fdb9 commit d82c704
Show file tree
Hide file tree
Showing 24 changed files with 886 additions and 675 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"cSpell.words": [
"APPSERVICEMININSTANCECOUNT",
"Arity",
"Authenticode",
"CLIXML",
"cmdlet",
"cmdlets",
Expand Down
61 changes: 61 additions & 0 deletions src/PSRule/Definitions/Baselines/BaselineExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using PSRule.Runtime;

namespace PSRule.Definitions.Baselines;

#nullable enable

/// <summary>
/// Extensions methods for baselines.
/// </summary>
internal static class BaselineExtensions
{
/// <summary>
/// Convert any baseline language blocks into <see cref="Baseline"/> resources.
/// </summary>
public static Baseline[] ToBaselineV1(this IEnumerable<ILanguageBlock> blocks, RunspaceContext context)
{
if (blocks == null) return [];

// Index baselines by BaselineId
var results = new Dictionary<string, Baseline>(StringComparer.OrdinalIgnoreCase);

foreach (var block in blocks.OfType<Baseline>().ToArray())
{
context.EnterLanguageScope(block.Source);
try
{
// Ignore baselines that don't match
if (!Match(context, block))
continue;

if (!results.ContainsKey(block.BaselineId))
results[block.BaselineId] = block;

}
finally
{
context.ExitLanguageScope(block.Source);
}
}
return [.. results.Values];
}

private static bool Match(RunspaceContext context, Baseline resource)
{
try
{
context.EnterLanguageScope(resource.Source);
var filter = context.LanguageScope!.GetFilter(ResourceKind.Baseline);
return filter == null || filter.Match(resource);
}
finally
{
context.ExitLanguageScope(resource.Source);
}
}
}

#nullable restore
10 changes: 4 additions & 6 deletions src/PSRule/Definitions/Conventions/ConventionComparer.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using PSRule.Runtime;

namespace PSRule.Definitions.Conventions;

/// <summary>
/// Orders conventions by the order they are specified.
/// </summary>
internal sealed class ConventionComparer : IComparer<IConventionV1>
{
private readonly RunspaceContext _Context;
private readonly Func<IConventionV1, int> _GetOrder;

internal ConventionComparer(RunspaceContext context)
internal ConventionComparer(Func<IConventionV1, int> getOrder)
{
_Context = context;
_GetOrder = getOrder;
}

public int Compare(IConventionV1 x, IConventionV1 y)
{
return _Context.Pipeline.GetConventionOrder(x) - _Context.Pipeline.GetConventionOrder(y);
return _GetOrder(x) - _GetOrder(y);
}
}
62 changes: 62 additions & 0 deletions src/PSRule/Definitions/Conventions/ConventionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using PSRule.Runtime;

namespace PSRule.Definitions.Conventions;

#nullable enable

/// <summary>
/// Extensions for conventions.
/// </summary>
internal static class ConventionExtensions
{
/// <summary>
/// Convert any convention language blocks into <see cref="IConventionV1"/> resources.
/// </summary>
public static IConventionV1[] ToConventionsV1(this IEnumerable<ILanguageBlock> blocks, RunspaceContext context)
{
if (blocks == null) return [];

// Index by Id.
var index = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var results = new List<IConventionV1>();

foreach (var block in blocks.OfType<ScriptBlockConvention>().ToArray())
{
context.EnterLanguageScope(block.Source);
try
{
// Ignore blocks that don't match.
if (!Match(context, block))
continue;

if (!index.Contains(block.Id.Value))
results.Add(block);

}
finally
{
context.ExitLanguageScope(block.Source);
}
}
return [.. results];
}

private static bool Match(RunspaceContext context, ScriptBlockConvention block)
{
try
{
context.EnterLanguageScope(block.Source);
var filter = context.LanguageScope.GetFilter(ResourceKind.Convention);
return filter == null || filter.Match(block);
}
finally
{
context.ExitLanguageScope(block.Source);
}
}
}

#nullable restore
33 changes: 33 additions & 0 deletions src/PSRule/Definitions/ModuleConfigs/ModuleConfigExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using PSRule.Runtime;

namespace PSRule.Definitions.ModuleConfigs;

#nullable enable

/// <summary>
/// Extensions methods for module configurations.
/// </summary>
internal static class ModuleConfigExtensions
{
/// <summary>
/// Convert any selector language blocks into <see cref="ModuleConfigV1"/> resources.
/// </summary>
public static ModuleConfigV1[] ToModuleConfigV1(this IEnumerable<ILanguageBlock> blocks, RunspaceContext context)
{
if (blocks == null) return [];

// Index configurations by Name.
var results = new Dictionary<string, ModuleConfigV1>(StringComparer.OrdinalIgnoreCase);
foreach (var block in blocks.OfType<ModuleConfigV1>().ToArray())
{
if (!results.ContainsKey(block.Name))
results[block.Name] = block;
}
return [.. results.Values];
}
}

#nullable restore
Loading

0 comments on commit d82c704

Please sign in to comment.