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
9 changes: 4 additions & 5 deletions ClosedGenericInterceptor.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

Expand All @@ -12,7 +11,7 @@ internal sealed class ClosedGenericInterceptor : IEquatable<ClosedGenericInterce
private readonly int hashCode;

public ImplementationClass ImplementationClass { get; }
public ImmutableArray<InterceptedMethodReference> InterceptedMethodReferences { get; }
public ImmutableArray<MethodReference> InterceptedMethodReferences { get; }
public MethodDescriptor InterceptsMethod { get; }
public string SourceText { get; }

Expand All @@ -30,7 +29,7 @@ IReadOnlyList<MethodReference> methodReferences
{
ImplementationClass = implementationClass;
InterceptsMethod = interceptsMethod;
InterceptedMethodReferences = [.. methodReferences.Select(x => new InterceptedMethodReference(x, this))];
InterceptedMethodReferences = [.. methodReferences];
SourceText = GetSourceText();
hashCode = SourceText.GetHashCode();
}
Expand All @@ -42,9 +41,9 @@ IReadOnlyList<MethodReference> methodReferences
private string GetSourceText()
{
var sb = new StringBuilder($"{Constants.NewLineIndent2}");
foreach (var reference in InterceptedMethodReferences.Select(x => x.MethodReference))
foreach (var reference in InterceptedMethodReferences)
{
_ = sb.Append(reference.InterceptorAttributeSourceText).Append($"{Constants.NewLineIndent2}");
_ = sb.Append(reference.Location.AttributeSourceText).Append($"{Constants.NewLineIndent2}");
}
var method = InterceptsMethod;
var typeParameters = Constants.InterceptorTypeParameters[method.ContainingInterface.Arity];
Expand Down
3 changes: 2 additions & 1 deletion ImplementationClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public ImplementationClass
bool isInterfaceOrMethodOpenGeneric,
MarshalInfo marshalInfo,
int invocationArgumentCount,
InterceptedLocation location,
IReadOnlyList<MethodReference> methodReferences
)
{
Expand All @@ -37,7 +38,7 @@ IReadOnlyList<MethodReference> methodReferences
}
else
{
openGenericInterceptorsBuilder.Add(this, methodReferences);
openGenericInterceptorsBuilder.Add(this, location, methodReferences);
}
SourceText = GetSourceText();
hashCode = SourceText.GetHashCode();
Expand Down
11 changes: 2 additions & 9 deletions ImplementationClassCollection.Key.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,11 @@ internal sealed partial class ImplementationClassCollection
public Key(MethodReference methodReference)
{
MethodReference = methodReference;
hashCode = Hash.Combine
(
MethodReference.Method,
MethodReference.InvocationArgumentCount,
MethodReference.MarshalInfo
);
hashCode = MethodReference.GetHashCode();
}

public override bool Equals(object? obj) => obj is Key other && Equals(other);
public bool Equals(Key other) => (MethodReference.Method == other.MethodReference.Method) &&
(MethodReference.InvocationArgumentCount == other.MethodReference.InvocationArgumentCount) &&
(MethodReference.MarshalInfo == other.MethodReference.MarshalInfo);
public bool Equals(Key other) => MethodReference == other.MethodReference;
public override int GetHashCode() => hashCode;
}
}
Expand Down
1 change: 1 addition & 0 deletions ImplementationClassCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ .. dictionary.Select
x.Key.MethodReference.IsInterfaceOrMethodOpenGeneric,
x.Key.MethodReference.MarshalInfo,
x.Key.MethodReference.InvocationArgumentCount,
x.Key.MethodReference.Location,
x.Value.AsReadOnly()
)
)
Expand Down
34 changes: 34 additions & 0 deletions InterceptedLocation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;

namespace Monkeymoto.NativeGenericDelegates
{
internal readonly struct InterceptedLocation : IEquatable<InterceptedLocation>
{
private readonly int hashCode;

public string AttributeSourceText { get; }
public int Character { get; }
public string FilePath { get; }
public int Line { get; }

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

public InterceptedLocation(InvocationExpressionSyntax invocationExpression)
{
var methodNode = ((MemberAccessExpressionSyntax)invocationExpression.Expression).Name;
var linePosition = methodNode.GetLocation().GetLineSpan().Span.Start;
Character = linePosition.Character + 1;
FilePath = invocationExpression.SyntaxTree.FilePath;
Line = linePosition.Line + 1;
AttributeSourceText = $"[InterceptsLocation(@\"{FilePath}\", {Line}, {Character})]";
hashCode = Hash.Combine(Character, FilePath, Line);
}

public override bool Equals(object? obj) => obj is InterceptedLocation other && Equals(other);
public bool Equals(InterceptedLocation other) => (Character == other.Character) &&
(FilePath == other.FilePath) && (Line == other.Line);
public override int GetHashCode() => hashCode;
}
}
30 changes: 0 additions & 30 deletions InterceptedMethodReference.cs

This file was deleted.

25 changes: 10 additions & 15 deletions MethodReference.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,10 @@ internal sealed class MethodReference : IEquatable<MethodReference>
{
private readonly int hashCode;

public int Character { get; }
public string FilePath { get; }
public string InterceptorAttributeSourceText { get; }
public InterfaceDescriptor Interface { get; }
public int InvocationArgumentCount { get; }
public bool IsInterfaceOrMethodOpenGeneric { get; }
public int Line { get; }
public InterceptedLocation Location { get; }
public MarshalInfo MarshalInfo { get; }
public MethodDescriptor Method { get; }

Expand Down Expand Up @@ -50,6 +47,7 @@ CancellationToken cancellationToken
}
var methodSymbol = invocation.TargetMethod;
var marshallers = new HashSet<INamedTypeSymbol>(SymbolEqualityComparer.Default);
var isOpenGenericMethod = false;
if (methodSymbol.IsGenericMethod)
{
if (methodSymbol.TypeArguments.First() is INamedTypeSymbol namedMarshaller)
Expand All @@ -58,6 +56,7 @@ CancellationToken cancellationToken
}
else
{
isOpenGenericMethod = true;
foreach
(
var marshaller in getGenericMethodReferences(methodSymbol, invocationExpression)
Expand Down Expand Up @@ -91,7 +90,7 @@ MethodReference GetReference(INamedTypeSymbol? marshaller)
methodDescriptor,
invocationExpression,
marshalInfo,
!interfaceReference.IsSyntaxReferenceClosedTypeOrMethod,
!interfaceReference.IsSyntaxReferenceClosedTypeOrMethod || isOpenGenericMethod,
invocationArgumentCount
);
}
Expand Down Expand Up @@ -120,23 +119,19 @@ private MethodReference
int invocationArgumentCount
)
{
var methodNode = ((MemberAccessExpressionSyntax)invocationExpression.Expression).Name;
var linePosition = methodNode.GetLocation().GetLineSpan().Span.Start;
Character = linePosition.Character + 1;
FilePath = invocationExpression.SyntaxTree.FilePath;
Interface = interfaceDescriptor;
InvocationArgumentCount = invocationArgumentCount;
IsInterfaceOrMethodOpenGeneric = isInterfaceOrMethodOpenGeneric;
Line = linePosition.Line + 1;
Location = new InterceptedLocation(invocationExpression);
MarshalInfo = marshalInfo;
Method = methodDescriptor;
InterceptorAttributeSourceText = $"[InterceptsLocation(@\"{FilePath}\", {Line}, {Character})]";
InvocationArgumentCount = invocationArgumentCount;
hashCode = Hash.Combine(Character, FilePath, Line);
hashCode = Hash.Combine(Location, Method, InvocationArgumentCount, MarshalInfo);
}

public override bool Equals(object? obj) => obj is MethodReference other && Equals(other);
public bool Equals(MethodReference? other) => (other is not null) && (Character == other.Character) &&
(FilePath == other.FilePath) && (Line == other.Line);
public bool Equals(MethodReference? other) => (other is not null) && (Location == other.Location) &&
(Method == other.Method) && (InvocationArgumentCount == other.InvocationArgumentCount) &&
(MarshalInfo == other.MarshalInfo);
public override int GetHashCode() => hashCode;
}
}
7 changes: 4 additions & 3 deletions OpenGenericInterceptors.Builder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@ public sealed class Builder
public void Add
(
ImplementationClass implementationClass,
InterceptedLocation location,
IReadOnlyList<MethodReference> methodReferences
)
{
var attributesHashSet = attributes.GetOrCreate
(
new Key(implementationClass),
new Key(location),
ImmutableHashSet.CreateBuilder<string>
);
var implementationClassesList = implementationClasses.GetOrCreate
(
new Key(implementationClass),
new Key(location),
ImmutableList.CreateBuilder<ImplementationClass>
);
attributesHashSet!.UnionWith(methodReferences.Select(static x => x.InterceptorAttributeSourceText));
attributesHashSet!.UnionWith(methodReferences.Select(static x => x.Location.AttributeSourceText));
implementationClassesList!.Add(implementationClass);
}

Expand Down
7 changes: 4 additions & 3 deletions OpenGenericInterceptors.Key.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ namespace Monkeymoto.NativeGenericDelegates
{
internal sealed partial class OpenGenericInterceptors
{
private readonly struct Key(ImplementationClass implementationClass) : IEquatable<Key>
private readonly struct Key(InterceptedLocation location) : IEquatable<Key>
{
private readonly int hashCode = implementationClass.ID.GetHashCode();
private readonly int hashCode = location.GetHashCode();
private readonly InterceptedLocation location = location;

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

public override bool Equals(object? obj) => obj is Key other && Equals(other);
public bool Equals(Key other) => hashCode == other.hashCode;
public bool Equals(Key other) => location == other.location;
public override int GetHashCode() => hashCode;
}
}
Expand Down