UfcppSample icon indicating copy to clipboard operation
UfcppSample copied to clipboard

Interceptors

Open ufcpp opened this issue 2 years ago • 7 comments

C# 12 時点で preview feature。オプション指定必須。

https://github.com/ufcpp-live/UfcppLiveAgenda/issues/74#issuecomment-1633665906

using System.Runtime.CompilerServices;

var c = new C();
c.InterceptableMethod(1); // (L1,C1): prints "interceptor 1"
c.InterceptableMethod(1); // (L2,C2): prints "other interceptor 1"
c.InterceptableMethod(2); // (L3,C3): prints "other interceptor 2"
c.InterceptableMethod(1); // prints "interceptable 1"

class C
{
    public void InterceptableMethod(int param)
    {
        Console.WriteLine($"interceptable {param}");
    }
}

// generated code
static class D
{
    [InterceptsLocation(@"[full path to Program]\Program.cs", 4, 3) ]
    public static void InterceptorMethod(this C c, int param)
    {
        Console.WriteLine($"interceptor {param}");
    }

    [InterceptsLocation(@"[full path to Program]\Program.cs", 5, 3)]
    [InterceptsLocation(@"[full path to Program]\Program.cs", 6, 3)]
    public static void OtherInterceptorMethod(this C c, int param)
    {
        Console.WriteLine($"other interceptor {param}");
    }
}
namespace System.Runtime.CompilerServices;

[Diagnostics.Conditional("CompileTimeOnly")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
internal sealed class InterceptsLocationAttribute : Attribute
{
    public InterceptsLocationAttribute(string path, int lineNumber, int columnNumber)
    {
        _ = path;
        _ = lineNumber;
        _ = columnNumber;
    }
}

ufcpp avatar Oct 17 '23 12:10 ufcpp

https://ufcpp.net/blog/2024/2/interceptors/ ブログにはした。 プレビューの間はこれでいいや。

ufcpp avatar Feb 18 '24 09:02 ufcpp

https://ufcpp.net/blog/2024/2/interceptors/

実際、パスを使うのはやめるっぽい。 location specifier を使う路線になった。

ufcpp avatar May 29 '24 15:05 ufcpp

location specifier 使う路線、いまだ Experimental だった。 なんか、C# 13 でも正式リリースに至らないんじゃないかという気がしてきてる。

using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

var code = /* lang=c#-test */"""
var x = int.Parse("123");

""";

var tree = CSharpSyntaxTree.ParseText(code, path: "a.cs");

var compilation = CSharpCompilation.Create("", [tree]);
var sem = compilation.GetSemanticModel(tree);

var root = await tree.GetRootAsync();
var parse = root.FindNode(new(13, 1));

var x = (InvocationExpressionSyntax)parse.Parent.Parent;

#pragma warning disable RSEXPERIMENTAL002
var loc = sem.GetInterceptableLocation(x);
#pragma warning restore RSEXPERIMENTAL002

Console.WriteLine(loc.Version);
Console.WriteLine(loc.Data);

var decoded = Convert.FromBase64String(loc.Data);

foreach (var b in decoded)
{
    Console.Write($"{b:X2} ");
}

Console.WriteLine();

ufcpp avatar Sep 03 '24 14:09 ufcpp

だいぶ前からだけども、global な型には Interceptor メソッド定義できない。

ufcpp avatar Sep 04 '24 11:09 ufcpp