From 3803bc9c09c1d46f95936554d7babe29c8d6a6c7 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Thu, 1 Oct 2020 13:16:53 +1000 Subject: [PATCH] Further work on making examples --- src/Directory.Build.props | 2 +- .../MyForm.cs | 9 +++- ...veMarbles.ObservableEvents.Example.csproj} | 0 .../EventGeneratorHook.cs | 46 +++++++++---------- .../SyntaxReceiver.cs | 35 ++++++++++++++ src/ReactiveMarbles.ObservableEvents.sln | 2 +- 6 files changed, 66 insertions(+), 28 deletions(-) rename src/{ReactiveMarbles.ObservableEvents.Tests => ReactiveMarbles.ObservableEvents.Example}/MyForm.cs (78%) rename src/{ReactiveMarbles.ObservableEvents.Tests/ReactiveMarbles.ObservableEvents.Test.csproj => ReactiveMarbles.ObservableEvents.Example/ReactiveMarbles.ObservableEvents.Example.csproj} (100%) create mode 100644 src/ReactiveMarbles.ObservableEvents.SourceGenerator/SyntaxReceiver.cs diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 08ea2e5..4dcaa28 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -53,7 +53,7 @@ - + diff --git a/src/ReactiveMarbles.ObservableEvents.Tests/MyForm.cs b/src/ReactiveMarbles.ObservableEvents.Example/MyForm.cs similarity index 78% rename from src/ReactiveMarbles.ObservableEvents.Tests/MyForm.cs rename to src/ReactiveMarbles.ObservableEvents.Example/MyForm.cs index eb49aae..ad30d94 100644 --- a/src/ReactiveMarbles.ObservableEvents.Tests/MyForm.cs +++ b/src/ReactiveMarbles.ObservableEvents.Example/MyForm.cs @@ -11,6 +11,8 @@ using Xamarin.Forms; +[assembly: GenerateStaticEventObservablesAttribute(typeof(StaticTest))] + #pragma warning disable namespace ReactiveMarbles.ObservableEvents { @@ -24,7 +26,7 @@ public partial class MyForm : Page /// public void Test() { - var events = this.Events().PropertyChanged.Subscribe(); + this.Events().PropertyChanged.Subscribe(); } } @@ -35,4 +37,9 @@ public MyNoEventsClass() this.Events(); } } + + public static class StaticTest + { + public static event EventHandler? TestChanged; + } } diff --git a/src/ReactiveMarbles.ObservableEvents.Tests/ReactiveMarbles.ObservableEvents.Test.csproj b/src/ReactiveMarbles.ObservableEvents.Example/ReactiveMarbles.ObservableEvents.Example.csproj similarity index 100% rename from src/ReactiveMarbles.ObservableEvents.Tests/ReactiveMarbles.ObservableEvents.Test.csproj rename to src/ReactiveMarbles.ObservableEvents.Example/ReactiveMarbles.ObservableEvents.Example.csproj diff --git a/src/ReactiveMarbles.ObservableEvents.SourceGenerator/EventGeneratorHook.cs b/src/ReactiveMarbles.ObservableEvents.SourceGenerator/EventGeneratorHook.cs index ff48a0d..76b18e4 100644 --- a/src/ReactiveMarbles.ObservableEvents.SourceGenerator/EventGeneratorHook.cs +++ b/src/ReactiveMarbles.ObservableEvents.SourceGenerator/EventGeneratorHook.cs @@ -48,12 +48,19 @@ public static NullEvents Events(this T eventHost) } } - internal static partial class EventsHelper + internal class GenerateStaticEventObservablesAttribute : Attribute { - public static NullEvents Events() + /// + /// Initializes a new instance of the class. + /// + /// The static type to generate event observable wrappers for. + public GenerateStaticEventObservablesAttribute(Type type) { - return default(NullEvents); + Type = type; } + + /// Gets the Type to generate the static event observable wrappers for. + public Type Type { get; } } internal struct NullEvents @@ -75,6 +82,7 @@ public void Execute(GeneratorExecutionContext context) return; } + ////Debugger.Launch(); var compilation = context.Compilation; var options = (compilation as CSharpCompilation)?.SyntaxTrees[0].Options as CSharpParseOptions; compilation = context.Compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(SourceText.From(ExtensionMethodText, Encoding.UTF8), options)); @@ -122,22 +130,16 @@ private static void GetAvailableTypes( out List<(InvocationExpressionSyntax Invocation, IMethodSymbol Method, INamedTypeSymbol NamedType)> staticNamespaceList) { var observableGeneratorExtensions = compilation.GetTypeByMetadataName("ReactiveMarbles.ObservableEvents.ObservableGeneratorExtensions"); - var staticGeneratorHelper = compilation.GetTypeByMetadataName("ReactiveMarbles.ObservableEvents.EventsHelper"); if (observableGeneratorExtensions == null) { throw new InvalidOperationException("Cannot find ReactiveMarbles.ObservableEvents.ObservableGeneratorExtensions"); } - if (staticGeneratorHelper == null) - { - throw new InvalidOperationException("Cannot find ReactiveMarbles.ObservableEvents.EventsHelper"); - } - instanceNamespaceList = new List<(InvocationExpressionSyntax, IMethodSymbol, INamedTypeSymbol)>(); staticNamespaceList = new List<(InvocationExpressionSyntax, IMethodSymbol, INamedTypeSymbol)>(); - foreach (var invocation in receiver.Candidates) + foreach (var invocation in receiver.InstanceCandidates) { var semanticModel = compilation.GetSemanticModel(invocation.SyntaxTree); var methodSymbol = semanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol; @@ -147,8 +149,7 @@ private static void GetAvailableTypes( continue; } - if (!SymbolEqualityComparer.Default.Equals(methodSymbol.ContainingType, observableGeneratorExtensions) && - !SymbolEqualityComparer.Default.Equals(methodSymbol.ContainingType, staticGeneratorHelper)) + if (!SymbolEqualityComparer.Default.Equals(methodSymbol.ContainingType, observableGeneratorExtensions)) { continue; } @@ -168,6 +169,14 @@ private static void GetAvailableTypes( var list = callingSymbol.IsStatic ? staticNamespaceList : instanceNamespaceList; list.Add((invocation, methodSymbol, callingSymbol)); } + + Debugger.Launch(); + foreach (var attribute in receiver.StaticCandidates) + { + var semanticModel = compilation.GetSemanticModel(attribute.SyntaxTree); + + var attributeSymbol = semanticModel.GetSymbolInfo(attribute.ArgumentList.Arguments[0].Expression).Symbol; + } } private static bool GenerateEvents( @@ -272,18 +281,5 @@ private static bool GenerateEvents( XmlSyntaxFactory.GenerateDocumentationString( "")); } - - private class SyntaxReceiver : ISyntaxReceiver - { - public List Candidates { get; } = new List(); - - public void OnVisitSyntaxNode(SyntaxNode syntaxNode) - { - if (syntaxNode is InvocationExpressionSyntax invocation) - { - Candidates.Add(invocation); - } - } - } } } diff --git a/src/ReactiveMarbles.ObservableEvents.SourceGenerator/SyntaxReceiver.cs b/src/ReactiveMarbles.ObservableEvents.SourceGenerator/SyntaxReceiver.cs new file mode 100644 index 0000000..417deca --- /dev/null +++ b/src/ReactiveMarbles.ObservableEvents.SourceGenerator/SyntaxReceiver.cs @@ -0,0 +1,35 @@ +// Copyright (c) 2020 ReactiveUI Association Inc. All rights reserved. +// ReactiveUI Association Inc licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace ReactiveMarbles.ObservableEvents.SourceGenerator +{ + internal class SyntaxReceiver : ISyntaxReceiver + { + public List InstanceCandidates { get; } = new List(); + + public List StaticCandidates { get; } = new List(); + + public void OnVisitSyntaxNode(SyntaxNode syntaxNode) + { + if (syntaxNode is InvocationExpressionSyntax invocation) + { + InstanceCandidates.Add(invocation); + } + + if (syntaxNode is AttributeSyntax attribute && attribute.Name.ToFullString() == "GenerateStaticEventObservablesAttribute") + { + StaticCandidates.Add(attribute); + } + } + } +} diff --git a/src/ReactiveMarbles.ObservableEvents.sln b/src/ReactiveMarbles.ObservableEvents.sln index 8d9fecf..fcd55a3 100644 --- a/src/ReactiveMarbles.ObservableEvents.sln +++ b/src/ReactiveMarbles.ObservableEvents.sln @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30503.244 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveMarbles.ObservableEvents.Test", "ReactiveMarbles.ObservableEvents.Tests\ReactiveMarbles.ObservableEvents.Test.csproj", "{2AF6CBC6-6EE4-4C99-B769-2A777DE6ADFC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveMarbles.ObservableEvents.Example", "ReactiveMarbles.ObservableEvents.Example\ReactiveMarbles.ObservableEvents.Example.csproj", "{2AF6CBC6-6EE4-4C99-B769-2A777DE6ADFC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ReactiveMarbles.ObservableEvents.SourceGenerator", "ReactiveMarbles.ObservableEvents.SourceGenerator\ReactiveMarbles.ObservableEvents.SourceGenerator.csproj", "{611C5578-EBDB-4B10-81D1-E7CBEC52D8FB}" EndProject