Skip to content

Commit

Permalink
Start Implementing Settings
Browse files Browse the repository at this point in the history
  • Loading branch information
justindbaur committed Dec 4, 2023
1 parent 7670f69 commit 3485768
Show file tree
Hide file tree
Showing 16 changed files with 229 additions and 135 deletions.
16 changes: 11 additions & 5 deletions src/Pretender.SourceGenerator/Emitter/GrandEmitter.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Pretender.SourceGenerator.Emitter
{
internal class GrandEmitter
{
public GrandEmitter()
private readonly ImmutableArray<PretendEmitter> _pretendEmitters;

public GrandEmitter(ImmutableArray<PretendEmitter> pretendEmitters)
{
_pretendEmitters = pretendEmitters;
}

public CompilationUnitSyntax Emit(CancellationToken cancellationToken)
{

throw new NotImplementedException();
}
}
}
10 changes: 10 additions & 0 deletions src/Pretender.SourceGenerator/Fakes/IKnownFake.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Microsoft.CodeAnalysis;
using Pretender.SourceGenerator.Parser;

namespace Pretender.SourceGenerator.Fakes
{
internal interface IKnownFake
{
bool TryConstruct(INamedTypeSymbol typeSymbol, KnownTypeSymbols knownTypeSymbols, CancellationToken cancellationToken, out ITypeSymbol? fakeType);
}
}
19 changes: 19 additions & 0 deletions src/Pretender.SourceGenerator/Fakes/ILoggerFake.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Microsoft.CodeAnalysis;
using Pretender.SourceGenerator.Parser;

namespace Pretender.SourceGenerator.Fakes
{
internal class ILoggerFake : IKnownFake
{
public bool TryConstruct(INamedTypeSymbol typeSymbol, KnownTypeSymbols knownTypeSymbols, CancellationToken cancellationToken, out ITypeSymbol? fakeType)
{
fakeType = null;
if (SymbolEqualityComparer.Default.Equals(typeSymbol, knownTypeSymbols.MicrosoftExtensionsLoggingILogger))
{
// TODO: Support this
}

return false;
}
}
}
15 changes: 4 additions & 11 deletions src/Pretender.SourceGenerator/Parser/CreateParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using Microsoft.CodeAnalysis;
using Pretender.SourceGenerator.Emitter;
using Pretender.SourceGenerator.Invocation;
using static Pretender.SourceGenerator.PretenderSourceGenerator;

namespace Pretender.SourceGenerator.Parser
{
Expand All @@ -11,26 +10,20 @@ internal class CreateParser
private readonly CreateInvocation _createInvocation;
private readonly ImmutableArray<InterceptsLocationInfo> _locations;
private readonly int _index;
private readonly bool _isLanguageVersionSupported;
private readonly KnownTypeSymbols _knownTypeSymbols;

public CreateParser(CreateInvocation createInvocation, ImmutableArray<InterceptsLocationInfo> locations, int index, CompilationData compilationData)
public CreateParser(CreateInvocation createInvocation, ImmutableArray<InterceptsLocationInfo> locations, int index, KnownTypeSymbols knownTypeSymbols)
{
_createInvocation = createInvocation;
_locations = locations;
_index = index;
_isLanguageVersionSupported = compilationData.LanguageVersionIsSupported;
_knownTypeSymbols = compilationData.TypeSymbols!;
_knownTypeSymbols = knownTypeSymbols;
}

public (CreateEmitter? Emitter, ImmutableArray<Diagnostic>? Diagnostics) Parse(CancellationToken cancellationToken)
{
if (!_isLanguageVersionSupported)
{
return (null, ImmutableArray.Create(Diagnostic.Create(DiagnosticDescriptors.UnsupportedLanguageVersion, null)));
}

// TODO:Do deeper introspection to make sure the supplied args match with supplied type arguments
cancellationToken.ThrowIfCancellationRequested();
// TODO: Do deeper introspection to make sure the supplied args match with supplied type arguments
// and we should provide the constructor to use to the emitter maybe
var emitter = new CreateEmitter(
_createInvocation.Operation,
Expand Down
27 changes: 25 additions & 2 deletions src/Pretender.SourceGenerator/Parser/KnownTypeSymbols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Pretender.SourceGenerator.Parser
{
internal sealed class KnownTypeSymbols
{
public CSharpCompilation Compilation { get; }
public Compilation Compilation { get; }

// INamedTypeSymbols
public INamedTypeSymbol? Pretend { get; }
Expand All @@ -17,9 +17,16 @@ internal sealed class KnownTypeSymbols
public INamedTypeSymbol? ValueTask { get; }
public INamedTypeSymbol? ValueTaskOfT_Unbound { get; }

// Known abstractions with fakes
public INamedTypeSymbol? MicrosoftExtensionsLoggingILogger { get; }
public INamedTypeSymbol? MicrosoftExtensionsLoggingTestingFakeLogger { get; }
public INamedTypeSymbol? MicrosoftExtensionsLoggingAbstractionsNullLogger { get; }

public INamedTypeSymbol? MicrosoftExtensionsLoggingILoggerOfT { get; }

public KnownTypeSymbols(CSharpCompilation compilation)


public KnownTypeSymbols(Compilation compilation)
{
Compilation = compilation;

Expand All @@ -32,6 +39,22 @@ public KnownTypeSymbols(CSharpCompilation compilation)
TaskOfT_Unbound = compilation.GetTypeByMetadataName("System.Threading.Tasks.Task`1")?.ConstructUnboundGenericType();
ValueTask = compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask");
ValueTaskOfT_Unbound = compilation.GetTypeByMetadataName("System.Threading.Tasks.ValueTask`1")?.ConstructUnboundGenericType();

// Fakes
// ILogger
MicrosoftExtensionsLoggingILogger = compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.ILogger");
MicrosoftExtensionsLoggingTestingFakeLogger = compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.Testing.FakeLogger");
MicrosoftExtensionsLoggingAbstractionsNullLogger = compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.Abstractions.NullLogger");

// ILogger<T>
MicrosoftExtensionsLoggingILoggerOfT = compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.ILogger`1");
MicrosoftExtensionsLoggingTestingFakeLogger = compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.Testing.FakeLogger`1");
MicrosoftExtensionsLoggingAbstractionsNullLogger = compilation.GetTypeByMetadataName("Microsoft.Extensions.Logging.Abstractions.NullLogger`1");

// ILoggerProvider

// TODO: data protection
// TODO: FakeTimeProvider
}

public static bool IsPretend(INamedTypeSymbol type)
Expand Down
29 changes: 25 additions & 4 deletions src/Pretender.SourceGenerator/Parser/PretendParser.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Pretender.Settings;
using Pretender.SourceGenerator.Emitter;
using Pretender.SourceGenerator.Fakes;
using Pretender.SourceGenerator.Invocation;
using static Pretender.SourceGenerator.PretenderSourceGenerator;

namespace Pretender.SourceGenerator.Parser
{
internal class PretendParser
{
private static readonly List<IKnownFake> _knownFakes =
[
new ILoggerFake(),
];

public PretendParser(PretendInvocation pretendInvocation, CompilationData compilationData)
private readonly KnownTypeSymbols _knownTypeSymbols;
private readonly PretenderSettings _settings;

public PretendParser(PretendInvocation pretendInvocation, KnownTypeSymbols knownTypeSymbols, PretenderSettings settings)
{
PretendInvocation = pretendInvocation;
_knownTypeSymbols = knownTypeSymbols;
_settings = settings;
}

public PretendInvocation PretendInvocation { get; }

public (PretendEmitter? Emitter, ImmutableArray<Diagnostic>? Diagnostics) Parse(CancellationToken cancellationToken)
{
if (PretendInvocation.PretendType.IsSealed)
var pretendType = PretendInvocation.PretendType;
if (pretendType.IsSealed)
{
var sealedError = Diagnostic.Create(
DiagnosticDescriptors.UnableToPretendSealedType,
Expand All @@ -30,7 +41,17 @@ public PretendParser(PretendInvocation pretendInvocation, CompilationData compil

// TODO: Do more error diagnostics

// TODO: Warn about well known good fakes
if (_settings.Behavior == PretendBehavior.PreferFakes)
{
foreach (var fake in _knownFakes)
{
cancellationToken.ThrowIfCancellationRequested();
if (fake.TryConstruct((INamedTypeSymbol)pretendType, _knownTypeSymbols, cancellationToken, out var fakeType))
{
// TODO: Do something
}
}
}

// TODO: Do a larger amount of parsing

Expand Down
12 changes: 2 additions & 10 deletions src/Pretender.SourceGenerator/Parser/SetupParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,22 @@
using Microsoft.CodeAnalysis;
using Pretender.SourceGenerator.Emitter;
using Pretender.SourceGenerator.Invocation;
using static Pretender.SourceGenerator.PretenderSourceGenerator;

namespace Pretender.SourceGenerator.Parser
{
internal class SetupParser
{
private readonly SetupInvocation _setupInvocation;
private readonly bool _isLanguageVersionSupported;
private readonly KnownTypeSymbols _knownTypeSymbols;

public SetupParser(SetupInvocation setupInvocation, CompilationData compilationData)
public SetupParser(SetupInvocation setupInvocation, KnownTypeSymbols knownTypeSymbols)
{
_setupInvocation = setupInvocation;
_isLanguageVersionSupported = compilationData.LanguageVersionIsSupported;
_knownTypeSymbols = compilationData.TypeSymbols!;
_knownTypeSymbols = knownTypeSymbols;
}

public (SetupEmitter? Emitter, ImmutableArray<Diagnostic>? Diagnostics) Parse(CancellationToken cancellationToken)
{
if (!_isLanguageVersionSupported)
{
return (null, ImmutableArray.Create(Diagnostic.Create(DiagnosticDescriptors.UnsupportedLanguageVersion, null)));
}

var operation = _setupInvocation.Operation;

// Setup calls are expected to have a single argument, being the setup action argument
Expand Down
14 changes: 3 additions & 11 deletions src/Pretender.SourceGenerator/Parser/VerifyParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,22 @@
using Microsoft.CodeAnalysis;
using Pretender.SourceGenerator.Emitter;
using Pretender.SourceGenerator.Invocation;
using static Pretender.SourceGenerator.PretenderSourceGenerator;

namespace Pretender.SourceGenerator.Parser
{
internal class VerifyParser
{
private readonly bool _isLanguageVersionSupported;
private readonly KnownTypeSymbols _knownTypeSymbols;
private readonly VerifyInvocation _verifyInvocation;
private readonly KnownTypeSymbols _knownTypeSymbols;

public VerifyParser(VerifyInvocation verifyInvocation, CompilationData compilationData)
public VerifyParser(VerifyInvocation verifyInvocation, KnownTypeSymbols knownTypeSymbols)
{
_isLanguageVersionSupported = compilationData.LanguageVersionIsSupported;
_knownTypeSymbols = compilationData.TypeSymbols!;
_verifyInvocation = verifyInvocation;
_knownTypeSymbols = knownTypeSymbols;
}

public (VerifyEmitter? VerifyEmitter, ImmutableArray<Diagnostic>? Diagnostics) Parse(CancellationToken cancellationToken)
{
if (!_isLanguageVersionSupported)
{
return (null, ImmutableArray.Create(Diagnostic.Create(DiagnosticDescriptors.UnsupportedLanguageVersion, null)));
}

cancellationToken.ThrowIfCancellationRequested();

var operation = _verifyInvocation.Operation;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0-1.final" />
</ItemGroup>

<ItemGroup>
<!--Include all the settings classes-->
<Compile Include="../Pretender/Settings/*.cs" LinkBase="Shared/Settings" />
</ItemGroup>
</Project>
40 changes: 40 additions & 0 deletions src/Pretender.SourceGenerator/PretenderSettings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using Microsoft.CodeAnalysis;
using Pretender.Settings;

namespace Pretender.SourceGenerator
{
internal class PretenderSettings
{
public static PretenderSettings Default { get; } = new PretenderSettings(
PretendBehavior.PreferFakes
);

public static PretenderSettings FromAttribute(AttributeData attributeData)
{
PretendBehavior? behavior = null;

foreach (var namedArg in attributeData.NamedArguments)
{
switch (namedArg.Key)
{
case nameof(Behavior):
behavior = (PretendBehavior)namedArg.Value.Value!;
break;
default:
throw new InvalidOperationException();
}
}

return new PretenderSettings(
behavior.GetValueOrDefault(PretendBehavior.PreferFakes)
);
}

public PretenderSettings(PretendBehavior behavior)
{
Behavior = behavior;
}

public PretendBehavior Behavior { get; }
}
}
Loading

0 comments on commit 3485768

Please sign in to comment.