Skip to content

Commit

Permalink
Code lenses to switch between bicep and JSON module source
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenWeatherford committed Dec 15, 2023
1 parent 5c0d0fe commit 35a9964
Show file tree
Hide file tree
Showing 26 changed files with 724 additions and 81 deletions.
70 changes: 70 additions & 0 deletions src/Bicep.Core.UnitTests/Assertions/CodeLensAssertions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Linq;
using System.Reactive.Subjects;
using Bicep.Core.UnitTests.Registry;
using FluentAssertions;
using FluentAssertions.Primitives;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

namespace Bicep.Core.UnitTests.Assertions;

public static class CodeLensAssertionsExtensions
{
public static CodeLensAssertions Should(this CodeLens codeLens)
{
return new CodeLensAssertions(codeLens);
}
}

public class CodeLensAssertions : ObjectAssertions<CodeLens, CodeLensAssertions>
{
public CodeLensAssertions(CodeLens subject)
: base(subject)
{
}

protected override string Identifier => nameof(CodeLens);

public AndConstraint<CodeLensAssertions> HaveCommandTitle(string title, string because = "", params object[] becauseArgs)
{
Subject.Command.Should().NotBeNull("Code lens command should not be null");
Subject.Command!.Title.Should().Be(title, because, becauseArgs);

return new(this);
}

public AndConstraint<CodeLensAssertions> HaveCommandName(string commandName, string because = "", params object[] becauseArgs)
{
Subject.Command.Should().NotBeNull("Code lens command should not be null");
Subject.Command!.Name.Should().Be(commandName, because, becauseArgs);

return new(this);
}

public AndConstraint<CodeLensAssertions> HaveCommandArguments(params string[] commandArguments)
{
Subject.Command.Should().NotBeNull("Code lens command should not be null");
Subject.Command!.Arguments.Should().NotBeNull("Command args should not be null");
var actualCommandArguments = Subject.CommandArguments();
actualCommandArguments.Should().BeEquivalentTo(commandArguments);

return new(this);
}

public AndConstraint<CodeLensAssertions> HaveNoCommandArguments()
{
Subject.CommandArguments().Should().BeEmpty("Command should have no arguments");

return new(this);
}

public AndConstraint<CodeLensAssertions> HaveRange(Range range, string because = "", params object[] becauseArgs)
{
Subject.Range.Should().Be(range, because, becauseArgs);

return new(this);
}


}
25 changes: 19 additions & 6 deletions src/Bicep.Core.UnitTests/BicepTestConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@
// Licensed under the MIT License.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using Azure.Core.Pipeline;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Bicep.Core.Analyzers.Linter;
using Bicep.Core.Configuration;
using Bicep.Core.Diagnostics;
using Bicep.Core.Extensions;
using Bicep.Core.Features;
using Bicep.Core.FileSystem;
using Bicep.Core.Json;
using Bicep.Core.Registry;
using Bicep.Core.Registry.Oci;
using Bicep.Core.Semantics.Namespaces;
using Bicep.Core.TypeSystem;
using Bicep.Core.SourceCode;
using Bicep.Core.TypeSystem.Providers;
using Bicep.Core.TypeSystem.Providers.Az;
using Bicep.Core.UnitTests.Configuration;
using Bicep.Core.UnitTests.Features;
using Bicep.Core.UnitTests.Mock;
Expand Down Expand Up @@ -85,7 +88,7 @@ public static class BicepTestConstants

public static IEnvironment EmptyEnvironment = new TestEnvironment(ImmutableDictionary<string, string?>.Empty);

public static readonly IModuleRestoreScheduler ModuleRestoreScheduler = CreateMockModuleRestoreScheduler();
public static readonly IModuleRestoreScheduler ModuleRestoreScheduler = CreateMockModuleDispatcherAndRestoreScheduler().moduleRestoreScheduler;

public static RootConfiguration CreateMockConfiguration(Dictionary<string, object>? customConfigurationData = null, string? configurationPath = null)
{
Expand Down Expand Up @@ -128,10 +131,20 @@ public static IConfigurationManager CreateConfigurationManager(Func<RootConfigur
public static IFeatureProviderFactory CreateFeatureProviderFactory(FeatureProviderOverrides featureOverrides, IConfigurationManager? configurationManager = null)
=> new OverriddenFeatureProviderFactory(new FeatureProviderFactory(configurationManager ?? CreateFilesystemConfigurationManager()), featureOverrides);

private static IModuleRestoreScheduler CreateMockModuleRestoreScheduler()
public static (IModuleDispatcher moduleDispatcher, IModuleRestoreScheduler moduleRestoreScheduler) CreateMockModuleDispatcherAndRestoreScheduler(IArtifactRegistry[]? artifactRegistries = null)
{
var moduleDispatcher = StrictMock.Of<IModuleDispatcher>();
return new ModuleRestoreScheduler(moduleDispatcher.Object);
moduleDispatcher.Setup(x => x.RestoreModules(It.IsAny<ImmutableArray<ArtifactReference>>(), It.IsAny<bool>())).
ReturnsAsync(true);
moduleDispatcher.Setup(x => x.PruneRestoreStatuses());

MockRepository repository = new(MockBehavior.Strict);
var provider = repository.Create<IArtifactRegistryProvider>();

moduleDispatcher.Setup(m => m.TryGetModuleSources(It.IsAny<ArtifactReference>())).Returns((ArtifactReference reference) =>
(artifactRegistries ?? new IArtifactRegistry[] { }).Select(r => r.TryGetSource(reference)).FirstOrDefault(s => s is not null));

return (moduleDispatcher.Object, new ModuleRestoreScheduler(moduleDispatcher.Object));
}

public static Mock<ITelemetryProvider> CreateMockTelemetryProvider()
Expand Down
15 changes: 15 additions & 0 deletions src/Bicep.Core.UnitTests/Extensions/CodeLensExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Linq;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;

namespace Bicep.Core.UnitTests.Assertions;

public static class CodeLensExtensions
{
public static string[]? CommandArguments(this CodeLens codeLens)
{
return codeLens.Command?.Arguments?.Children().Select(token => token.ToString()).ToArray();
}
}
2 changes: 1 addition & 1 deletion src/Bicep.Core.UnitTests/Utils/OciModuleRegistryHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public static OciArtifactReference CreateModuleReference(string registry, string
}
}

// public a new (real) OciArtifactRegistry instance with an empty on-disk cache that can push and pull modules
// create a new (real) OciArtifactRegistry instance with an empty on-disk cache that can push and pull modules
public static (OciArtifactRegistry, MockRegistryBlobClient) CreateModuleRegistry(
Uri parentModuleUri,
IFeatureProvider featureProvider)
Expand Down
2 changes: 1 addition & 1 deletion src/Bicep.Core/Navigation/IArtifactReferenceSyntax.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace Bicep.Core.Navigation;

/// <summary>
/// Objects that implement IArtifactReferenceSyntax, contain syntax that can reference a foregin artifact, the artifact address
/// Objects that implement IArtifactReferenceSyntax, contain syntax that can reference a foreign artifact, the artifact address
/// is returned by `TryGetPath` and `SourceSyntax` contains the source syntax object to use for error propagation.
/// </summary>
public interface IArtifactReferenceSyntax
Expand Down
7 changes: 6 additions & 1 deletion src/Bicep.Core/Registry/DefaultArtifactRegistryProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ public DefaultArtifactRegistryProvider(IServiceProvider serviceProvider, IFileRe
this.serviceProvider = serviceProvider;
}

// NOTE: The templateUri affects how module aliases are resolved, by determining how the bicepconfig.json is located, which contains alias definitions
/// <summary>
/// Gets the registries available for module references inside a given template URI.
/// </summary>
/// <param name="templateUri">URI of the Bicep template source code which contains the module references.
/// This is needed to determine the appropriate bicepconfig.json (which contains module alias definitions) and features provider to bind to</param>
/// <returns></returns>
public ImmutableArray<IArtifactRegistry> Registries(Uri templateUri)
{
var configuration = configurationManager.GetConfiguration(templateUri);
Expand Down
2 changes: 1 addition & 1 deletion src/Bicep.Core/Utils/Result.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public bool IsSuccess([NotNullWhen(true)] out TSuccess? success, [NotNullWhen(fa

/// <summary>
/// Returns the succcessful result, assuming success. Throws an exception if not.
/// This should only be called if you'e already verified that the result is successful.
/// This should only be called if you've already verified that the result is successful.
/// </summary>
public TSuccess Unwrap()
=> TryUnwrap() ?? throw new InvalidOperationException("Cannot unwrap a failed result.");
Expand Down
Loading

0 comments on commit 35a9964

Please sign in to comment.