Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -142,7 +142,7 @@ private static Result<CompositeRegistration> Transform(GeneratorAttributeSyntaxC
ImplementsContract(implementation, contract),
HasPublicParameterlessConstructor(implementation),
ImplementsBuildable(implementation, contract),
context.TargetNode.GetLocation()));
new LocationInfo(context.TargetNode.GetLocation())));
}

return Result<CompositeRegistration>.Empty;
Expand Down Expand Up @@ -202,7 +202,7 @@ private static void ReportDuplicateKeys(SourceProductionContext context, List<Co
{
context.ReportDiagnostic(Diagnostic.Create(
DuplicateKeyDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.Key,
contractName));
}
Expand All @@ -220,7 +220,7 @@ private static void ReportUnknownParentKeys(SourceProductionContext context, Lis
{
context.ReportDiagnostic(Diagnostic.Create(
UnknownParentKeyDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.ParentKey!,
contractName));
}
Expand All @@ -235,7 +235,7 @@ private static void ReportCycles(SourceProductionContext context, List<Composite
{
context.ReportDiagnostic(Diagnostic.Create(
CycleDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.Key,
contractName));
}
Expand All @@ -247,7 +247,7 @@ private static void ReportContractMismatches(SourceProductionContext context, Li
{
context.ReportDiagnostic(Diagnostic.Create(
ContractMismatchDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.ImplementationName,
registration.Contract.FullyQualifiedName));
}
Expand All @@ -259,7 +259,7 @@ private static void ReportMissingConstructors(SourceProductionContext context, L
{
context.ReportDiagnostic(Diagnostic.Create(
MissingParameterlessConstructorDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.ImplementationName));
}
}
Expand All @@ -273,7 +273,7 @@ private static void ReportMissingBuildable(
{
context.ReportDiagnostic(Diagnostic.Create(
MissingBuildableDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.ImplementationName,
contract.FullyQualifiedName));
}
Expand Down Expand Up @@ -446,5 +446,5 @@ private sealed record CompositeRegistration(
bool ImplementsContract,
bool HasPublicParameterlessConstructor,
bool ImplementsBuildable,
Location Location);
LocationInfo Location);
}
16 changes: 8 additions & 8 deletions DesignPatterns.SourceGenerators/Generators/DecoratorGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ private static Result<DecoratorRegistration> Transform(GeneratorAttributeSyntaxC
ImplementsAsyncDecoratorInterface(decoratorType, serviceType),
HasValidAsyncSignature(decoratorType, serviceType),
HasPublicParameterlessConstructor(decoratorType),
context.TargetNode.GetLocation()));
new LocationInfo(context.TargetNode.GetLocation())));
}

return Result<DecoratorRegistration>.Empty;
Expand Down Expand Up @@ -186,7 +186,7 @@ private static void ReportValidationDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
DuplicateOrderDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.Order,
serviceName));
}
Expand All @@ -196,7 +196,7 @@ private static void ReportValidationDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
ContractMismatchDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.DecoratorName,
registration.Service.FullyQualifiedName));
}
Expand All @@ -205,7 +205,7 @@ private static void ReportValidationDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
MissingDecoratorInterfaceDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.DecoratorName,
registration.Service.FullyQualifiedName));
}
Expand All @@ -214,7 +214,7 @@ private static void ReportValidationDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
AsyncSignatureMismatchDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.DecoratorName,
registration.Service.FullyQualifiedName));
}
Expand All @@ -225,14 +225,14 @@ private static void ReportValidationDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
DiNotResolvableDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.DecoratorName));
}
else
{
context.ReportDiagnostic(Diagnostic.Create(
MissingParameterlessConstructorDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.DecoratorName));
}
}
Expand Down Expand Up @@ -398,5 +398,5 @@ private sealed record DecoratorRegistration(
bool ImplementsAsyncDecoratorInterface,
bool HasValidAsyncSignature,
bool HasPublicParameterlessConstructor,
Location Location);
LocationInfo Location);
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private static Result<SingletonTargetInfo> GetTargetInfo(GeneratorAttributeSynta
}
}

var location = classDeclaration.GetLocation();
var location = new LocationInfo(classDeclaration.GetLocation());
var className = symbol.Name;
var isStatic = symbol.IsStatic;
var typeKind = symbol.TypeKind;
Expand Down Expand Up @@ -110,7 +110,7 @@ private static void Execute(SourceProductionContext context, Result<SingletonTar
}

private sealed record SingletonTargetInfo(
Location Location,
LocationInfo Location,
string ClassName,
string? NamespaceName,
bool ThreadSafe,
Expand Down
24 changes: 12 additions & 12 deletions DesignPatterns.SourceGenerators/Generators/HandlerOrderGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,21 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
source.Right));
}

private static List<HandlerRegistration> Transform(GeneratorAttributeSyntaxContext context, bool isGenericAttribute)
private static EquatableArray<HandlerRegistration> Transform(GeneratorAttributeSyntaxContext context, bool isGenericAttribute)
{
var result = new List<HandlerRegistration>();

if (context.TargetSymbol is not INamedTypeSymbol handlerType)
{
return result;
return new EquatableArray<HandlerRegistration>(result.ToArray());
}

if (context.Attributes.IsDefaultOrEmpty)
{
return result;
return new EquatableArray<HandlerRegistration>(result.ToArray());
}

var location = context.TargetNode.GetLocation();
var location = new LocationInfo(context.TargetNode.GetLocation());
var handlerName = handlerType.Name;
var handlerFullyQualifiedDisplayString = handlerType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat);

Expand Down Expand Up @@ -147,7 +147,7 @@ private static List<HandlerRegistration> Transform(GeneratorAttributeSyntaxConte
location));
}

return result;
return new EquatableArray<HandlerRegistration>(result.ToArray());
}

private static void Execute(
Expand Down Expand Up @@ -218,7 +218,7 @@ private static void ReportValidationDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
DuplicateOrderDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.Order,
contextName));
}
Expand All @@ -228,7 +228,7 @@ private static void ReportValidationDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
HandlerContractMismatchDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.HandlerName,
registration.Context.FullyQualifiedName));
}
Expand All @@ -237,7 +237,7 @@ private static void ReportValidationDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
MissingParameterlessConstructorDescriptor,
registration.Location,
registration.Location.ToLocation(),
registration.HandlerName));
}

Expand All @@ -262,7 +262,7 @@ private static void ReportGuardDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
DesignPatternsDiagnosticDescriptors.HandlerOrderGuardMethodNotFound,
registration.Location,
registration.Location.ToLocation(),
guard.Name,
registration.HandlerName,
contextTypeDisplay));
Expand All @@ -273,7 +273,7 @@ private static void ReportGuardDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
DesignPatternsDiagnosticDescriptors.HandlerOrderGuardMethodNotStatic,
registration.Location,
registration.Location.ToLocation(),
guard.Name,
registration.HandlerName));
continue;
Expand All @@ -283,7 +283,7 @@ private static void ReportGuardDiagnostics(
{
context.ReportDiagnostic(Diagnostic.Create(
DesignPatternsDiagnosticDescriptors.HandlerOrderGuardMethodWrongSignature,
registration.Location,
registration.Location.ToLocation(),
guard.Name,
registration.HandlerName,
contextTypeDisplay));
Expand Down Expand Up @@ -346,5 +346,5 @@ private sealed record HandlerRegistration(
bool ImplementsHandler,
bool HasPublicParameterlessConstructor,
GuardResolution Guard,
Location Location);
LocationInfo Location);
}
74 changes: 74 additions & 0 deletions DesignPatterns.SourceGenerators/Generators/LocationInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;

namespace DesignPatterns.SourceGenerators.Generators;

/// <summary>
/// A value-equatable representation of a <see cref="Location"/>. Used in
/// incremental generator models to ensure correct caching by the Roslyn
/// incremental pipeline — <see cref="Location"/> uses reference equality,
/// which breaks model value equality when <see cref="Compilation.Clone"/>
/// creates new <see cref="Location"/> objects.
/// </summary>
internal readonly struct LocationInfo : IEquatable<LocationInfo>
{
public string? FilePath { get; }
public TextSpan TextSpan { get; }
public LinePositionSpan LineSpan { get; }

public LocationInfo(Location? location)
{
if (location is null)
{
FilePath = null;
TextSpan = default;
LineSpan = default;
return;
}

var lineSpan = location.GetLineSpan();
FilePath = location.SourceTree?.FilePath ?? lineSpan.Path;
TextSpan = location.SourceSpan;
LineSpan = lineSpan.Span;
}

/// <summary>
/// Reconstructs a <see cref="Location"/> suitable for diagnostic reporting.
/// The returned location is an <see cref="ExternalFileLocation"/> that does
/// not reference a <see cref="SyntaxTree"/>, which is sufficient for
/// <see cref="Diagnostic.Create(DiagnosticDescriptor, Location, object[])"/>.
/// </summary>
public Location? ToLocation()
{
if (FilePath is null)
{
return null;
}

return Location.Create(FilePath, TextSpan, LineSpan);
}

public bool Equals(LocationInfo other)
{
return string.Equals(FilePath, other.FilePath, StringComparison.Ordinal)
&& TextSpan == other.TextSpan
&& LineSpan == other.LineSpan;
}

public override bool Equals(object? obj) => obj is LocationInfo other && Equals(other);

public override int GetHashCode()
{
unchecked
{
return (StringComparer.Ordinal.GetHashCode(FilePath ?? string.Empty) * 397)
^ TextSpan.GetHashCode()
^ LineSpan.GetHashCode();
}
}

public static bool operator ==(LocationInfo left, LocationInfo right) => left.Equals(right);

public static bool operator !=(LocationInfo left, LocationInfo right) => !left.Equals(right);
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal sealed record EventHandlerRegistration(
string HandlerFullyQualifiedDisplayString,
bool ImplementsHandlerInterface,
bool HasPublicParameterlessConstructor,
Location Location);
LocationInfo Location);

/// <summary>
/// Generates <c>{Event}EventHandlerRegistry</c> static classes for
Expand Down Expand Up @@ -122,7 +122,7 @@ private static List<EventHandlerRegistration> Transform(
: eventType.ContainingNamespace.ToDisplayString(),
eventType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat));

var location = context.TargetNode.GetLocation();
var location = new LocationInfo(context.TargetNode.GetLocation());
result.Add(new EventHandlerRegistration(
eventInfo,
handler.Name,
Expand Down Expand Up @@ -152,7 +152,7 @@ private static void Execute(
{
context.ReportDiagnostic(Diagnostic.Create(
DesignPatternsDiagnosticDescriptors.RegisterEventHandlerContractMismatch,
registration.Location,
registration.Location.ToLocation(),
registration.HandlerName,
registration.Event.FullyQualifiedName));
}
Expand All @@ -169,7 +169,7 @@ private static void Execute(
{
context.ReportDiagnostic(Diagnostic.Create(
DesignPatternsDiagnosticDescriptors.RegisterEventHandlerDuplicateOnSameClass,
registration.Location,
registration.Location.ToLocation(),
registration.HandlerName,
registration.Event.FullyQualifiedName));
}
Expand Down
Loading
Loading