From 1aa193874b6aa48949615da9da547041ea5f11b2 Mon Sep 17 00:00:00 2001 From: max-ieremenko <> Date: Fri, 11 Mar 2022 18:14:25 +0100 Subject: [PATCH 1/2] update version to 1.4.4 --- Sources/Versions.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Versions.props b/Sources/Versions.props index 2f8ba4ac..8ed7f015 100644 --- a/Sources/Versions.props +++ b/Sources/Versions.props @@ -1,6 +1,6 @@ - 1.4.3 + 1.4.4 2.43.0 2.42.0 From 57a0f20f75b74a2c8add0186c1763d8a7e5568e6 Mon Sep 17 00:00:00 2001 From: max-ieremenko <> Date: Fri, 11 Mar 2022 18:36:41 +0100 Subject: [PATCH 2/2] DesignTime handle FileScopedNamespaceDeclarationSyntax --- Sources/Directory.Build.props | 2 +- .../GrpcServices.cs | 25 ++++--- .../Generator/CompilationUnit.cs | 17 +++-- .../Generator/SyntaxFactoryExtensions.cs | 69 ++++++++++++++----- 4 files changed, 71 insertions(+), 42 deletions(-) diff --git a/Sources/Directory.Build.props b/Sources/Directory.Build.props index 73786840..67c7cb75 100644 --- a/Sources/Directory.Build.props +++ b/Sources/Directory.Build.props @@ -11,7 +11,7 @@ ..\StyleCope.ruleset - 8.0 + 10.0 enable diff --git a/Sources/ServiceModel.Grpc.DesignTime.Generator.Test/GrpcServices.cs b/Sources/ServiceModel.Grpc.DesignTime.Generator.Test/GrpcServices.cs index bc5caaf8..c27acd46 100644 --- a/Sources/ServiceModel.Grpc.DesignTime.Generator.Test/GrpcServices.cs +++ b/Sources/ServiceModel.Grpc.DesignTime.Generator.Test/GrpcServices.cs @@ -16,18 +16,17 @@ using ServiceModel.Grpc.TestApi.Domain; -namespace ServiceModel.Grpc.DesignTime.Generator.Test +namespace ServiceModel.Grpc.DesignTime.Generator.Test; + +[ImportGrpcService(typeof(IMultipurposeService))] +[ExportGrpcService(typeof(IMultipurposeService))] +[ImportGrpcService(typeof(IContract))] +[ImportGrpcService(typeof(IGenericContract))] +[ImportGrpcService(typeof(IGenericContract))] +[ImportGrpcService(typeof(IInvalidContract))] +[ImportGrpcService(typeof(ISomeService))] +[ImportGrpcService(typeof(IFilteredService))] +[ExportGrpcService(typeof(TrackedFilteredService), GenerateAspNetExtensions = true, GenerateSelfHostExtensions = true)] +public static partial class GrpcServices { - [ImportGrpcService(typeof(IMultipurposeService))] - [ExportGrpcService(typeof(IMultipurposeService))] - [ImportGrpcService(typeof(IContract))] - [ImportGrpcService(typeof(IGenericContract))] - [ImportGrpcService(typeof(IGenericContract))] - [ImportGrpcService(typeof(IInvalidContract))] - [ImportGrpcService(typeof(ISomeService))] - [ImportGrpcService(typeof(IFilteredService))] - [ExportGrpcService(typeof(TrackedFilteredService), GenerateAspNetExtensions = true, GenerateSelfHostExtensions = true)] - public static partial class GrpcServices - { - } } diff --git a/Sources/ServiceModel.Grpc.DesignTime/Generator/CompilationUnit.cs b/Sources/ServiceModel.Grpc.DesignTime/Generator/CompilationUnit.cs index 68a25a71..35ec8e72 100644 --- a/Sources/ServiceModel.Grpc.DesignTime/Generator/CompilationUnit.cs +++ b/Sources/ServiceModel.Grpc.DesignTime/Generator/CompilationUnit.cs @@ -20,6 +20,7 @@ using System.Linq; using System.Text; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using ServiceModel.Grpc.DesignTime.Generator.Internal.CSharp; @@ -93,17 +94,15 @@ private void DeclareClass(ClassDeclarationSyntax node) { var owners = ImmutableArray.Empty; - foreach (var ancestor in node.Ancestors()) + foreach (var ancestor in node.AncestorMembers()) { - switch (ancestor) + if (ancestor.Kind == SyntaxKind.NamespaceDeclaration) { - case NamespaceDeclarationSyntax ns: - owners = owners.Insert(0, "namespace " + ns.Name.WithoutTrivia()); - break; - - case ClassDeclarationSyntax c: - owners = owners.Insert(0, "partial class " + c.Identifier.WithoutTrivia()); - break; + owners = owners.Insert(0, "namespace " + ancestor.Name); + } + else + { + owners = owners.Insert(0, "partial class " + ancestor.Name); } } diff --git a/Sources/ServiceModel.Grpc.DesignTime/Generator/SyntaxFactoryExtensions.cs b/Sources/ServiceModel.Grpc.DesignTime/Generator/SyntaxFactoryExtensions.cs index ee64eb41..12204da6 100644 --- a/Sources/ServiceModel.Grpc.DesignTime/Generator/SyntaxFactoryExtensions.cs +++ b/Sources/ServiceModel.Grpc.DesignTime/Generator/SyntaxFactoryExtensions.cs @@ -1,5 +1,5 @@ // -// Copyright 2020 Max Ieremenko +// Copyright 2020-2022 Max Ieremenko // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,9 +15,12 @@ // using System; +using System.Collections.Generic; using System.Linq; +using System.Reflection; using System.Text; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace ServiceModel.Grpc.DesignTime.Generator @@ -27,25 +30,10 @@ internal static class SyntaxFactoryExtensions public static string GetFullName(this ClassDeclarationSyntax node) { var result = new StringBuilder(node.Identifier.WithoutTrivia().ToString()); - foreach (var ancestor in node.Ancestors()) + foreach (var ancestor in node.AncestorMembers()) { - string? name = null; - switch (ancestor) - { - case NamespaceDeclarationSyntax ns: - name = ns.Name.WithoutTrivia().ToString(); - break; - - case ClassDeclarationSyntax c: - name = c.Identifier.WithoutTrivia().ToString(); - break; - } - - if (!string.IsNullOrEmpty(name)) - { - result.Insert(0, "."); - result.Insert(0, name); - } + result.Insert(0, "."); + result.Insert(0, ancestor.Name); } return result.ToString(); @@ -55,5 +43,48 @@ public static bool IsStatic(this ClassDeclarationSyntax node) { return node.Modifiers.Any(i => "static".Equals(i.ToString(), StringComparison.Ordinal)); } + + public static IEnumerable<(SyntaxKind Kind, string Name)> AncestorMembers(this ClassDeclarationSyntax node) + { + foreach (var ancestor in node.Ancestors().OfType()) + { + string? name = null; + var kind = default(SyntaxKind); + + if (ancestor is NamespaceDeclarationSyntax ns) + { + kind = SyntaxKind.NamespaceDeclaration; + name = ns.Name.WithoutTrivia().ToString(); + } + else if (ancestor is ClassDeclarationSyntax c) + { + kind = SyntaxKind.ClassDeclaration; + name = c.Identifier.WithoutTrivia().ToString(); + } + else + { + var type = ancestor.GetType(); + + // see #73, more elegant fix requires roslyn4.0 + // roslyn4.0 does not work on pure .netcore 3.1 sdk + // TODO: support roslyn4.0 and roslyn3.11 + if ("FileScopedNamespaceDeclarationSyntax".Equals(type.Name, StringComparison.Ordinal)) + { + var nameSyntax = (NameSyntax)ancestor + .GetType() + .GetProperty(nameof(NamespaceDeclarationSyntax.Name), BindingFlags.Public | BindingFlags.Instance)! + .GetValue(ancestor); + + kind = SyntaxKind.NamespaceDeclaration; + name = nameSyntax.WithoutTrivia().ToString(); + } + } + + if (name != null) + { + yield return (kind, name); + } + } + } } }