diff --git a/InterfaceGenerator.Tests/AccessorsGenerationTests.cs b/InterfaceGenerator.Tests/AccessorsGenerationTests.cs index dfe68e8..75b0c25 100644 --- a/InterfaceGenerator.Tests/AccessorsGenerationTests.cs +++ b/InterfaceGenerator.Tests/AccessorsGenerationTests.cs @@ -32,7 +32,7 @@ namespace InterfaceGenerator.Tests public void PublicProperty_IsImplemented() { var prop = typeof(IAccessorsTestsService) - .GetProperty(nameof(IAccessorsTestsService.PublicProperty)); + .GetProperty(nameof(IAccessorsTestsService.PublicProperty))!; prop.Should().NotBeNull(); @@ -47,14 +47,14 @@ namespace InterfaceGenerator.Tests public void InitProperty_IsImplemented() { var prop = typeof(IAccessorsTestsService) - .GetProperty(nameof(IAccessorsTestsService.InitOnlyProperty)); + .GetProperty(nameof(IAccessorsTestsService.InitOnlyProperty))!; prop.Should().NotBeNull(); prop.GetMethod.Should().NotBeNull(); prop.SetMethod.Should().NotBeNull(); - prop.SetMethod.ReturnParameter.GetRequiredCustomModifiers().Should().Contain(typeof(IsExternalInit)); + prop.SetMethod!.ReturnParameter!.GetRequiredCustomModifiers().Should().Contain(typeof(IsExternalInit)); string _ = _sut.InitOnlyProperty; } @@ -63,7 +63,7 @@ namespace InterfaceGenerator.Tests public void PrivateSetter_IsOmitted() { var prop = typeof(IAccessorsTestsService) - .GetProperty(nameof(IAccessorsTestsService.PropertyWithPrivateSetter)); + .GetProperty(nameof(IAccessorsTestsService.PropertyWithPrivateSetter))!; prop.Should().NotBeNull(); @@ -77,7 +77,7 @@ namespace InterfaceGenerator.Tests public void PrivateGetter_IsOmitted() { var prop = typeof(IAccessorsTestsService) - .GetProperty(nameof(IAccessorsTestsService.PropertyWithPrivateGetter)); + .GetProperty(nameof(IAccessorsTestsService.PropertyWithPrivateGetter))!; prop.Should().NotBeNull(); @@ -91,7 +91,7 @@ namespace InterfaceGenerator.Tests public void ProtectedSetter_IsOmitted() { var prop = typeof(IAccessorsTestsService) - .GetProperty(nameof(IAccessorsTestsService.PropertyWithProtectedSetter)); + .GetProperty(nameof(IAccessorsTestsService.PropertyWithProtectedSetter))!; prop.Should().NotBeNull(); @@ -105,7 +105,7 @@ namespace InterfaceGenerator.Tests public void ProtectedGetter_IsOmitted() { var prop = typeof(IAccessorsTestsService) - .GetProperty(nameof(IAccessorsTestsService.PropertyWithProtectedGetter)); + .GetProperty(nameof(IAccessorsTestsService.PropertyWithProtectedGetter))!; prop.Should().NotBeNull(); diff --git a/InterfaceGenerator.Tests/MethodGenerationTests.cs b/InterfaceGenerator.Tests/MethodGenerationTests.cs index 34a55eb..05edbd9 100644 --- a/InterfaceGenerator.Tests/MethodGenerationTests.cs +++ b/InterfaceGenerator.Tests/MethodGenerationTests.cs @@ -20,7 +20,7 @@ namespace InterfaceGenerator.Tests public void VoidMethod_IsImplemented() { var method = typeof(IMethodsTestService).GetMethod( - nameof(MethodsTestService.VoidMethod)); + nameof(MethodsTestService.VoidMethod))!; method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -35,7 +35,7 @@ namespace InterfaceGenerator.Tests public void VoidMethodWithKeywordParam_IsImplemented() { var method = typeof(IMethodsTestService).GetMethod( - nameof(MethodsTestService.VoidMethodWithKeywordParam)); + nameof(MethodsTestService.VoidMethodWithKeywordParam))!; method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -54,7 +54,7 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService).GetMethod( nameof(MethodsTestService.VoidMethodWithParams), - new[] { typeof(string), typeof(string) }); + new[] { typeof(string), typeof(string) })!; method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -71,7 +71,7 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService).GetMethod( nameof(MethodsTestService.VoidMethodWithOutParam), - new[] { typeof(string).MakeByRefType() }); + new[] { typeof(string).MakeByRefType() })!; method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -89,7 +89,7 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService).GetMethod( nameof(MethodsTestService.VoidMethodWithInParam), - new[] { typeof(string).MakeByRefType() }); + new[] { typeof(string).MakeByRefType() })!; method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -108,7 +108,7 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService).GetMethod( nameof(MethodsTestService.VoidMethodWithRefParam), - new[] { typeof(string).MakeByRefType() }); + new[] { typeof(string).MakeByRefType() })!; method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -127,7 +127,7 @@ namespace InterfaceGenerator.Tests public void StringMethod_IsImplemented() { var method = typeof(IMethodsTestService).GetMethod( - nameof(MethodsTestService.StringMethod)); + nameof(MethodsTestService.StringMethod))!; method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(string)); @@ -143,7 +143,7 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService) .GetMethods() - .FirstOrDefault(x => x.Name == nameof(MethodsTestService.GenericVoidMethod)); + .First(x => x.Name == nameof(MethodsTestService.GenericVoidMethod)); method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -161,7 +161,7 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService) .GetMethods() - .FirstOrDefault(x => x.Name == nameof(MethodsTestService.GenericVoidMethodWithGenericParam)); + .First(x => x.Name == nameof(MethodsTestService.GenericVoidMethodWithGenericParam)); method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -181,7 +181,7 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService) .GetMethods() - .FirstOrDefault(x => x.Name == nameof(MethodsTestService.GenericVoidMethodWithConstraints)); + .First(x => x.Name == nameof(MethodsTestService.GenericVoidMethodWithConstraints)); method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -206,7 +206,7 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService) .GetMethods() - .FirstOrDefault(x => x.Name == nameof(MethodsTestService.VoidMethodWithOptionalParams)); + .First(x => x.Name == nameof(MethodsTestService.VoidMethodWithOptionalParams)); method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); @@ -231,9 +231,8 @@ namespace InterfaceGenerator.Tests { var method = typeof(IMethodsTestService) .GetMethods() - .FirstOrDefault(x => x.Name == nameof(MethodsTestService.VoidMethodWithExpandingParam)); + .First(x => x.Name == nameof(MethodsTestService.VoidMethodWithExpandingParam)); - method.Should().NotBeNull(); method.ReturnType.Should().Be(typeof(void)); var parameters = method.GetParameters(); diff --git a/InterfaceGenerator.Tests/RecordInterfaceGenerationTests.cs b/InterfaceGenerator.Tests/RecordInterfaceGenerationTests.cs index b69bc15..161bd80 100644 --- a/InterfaceGenerator.Tests/RecordInterfaceGenerationTests.cs +++ b/InterfaceGenerator.Tests/RecordInterfaceGenerationTests.cs @@ -17,13 +17,13 @@ namespace InterfaceGenerator.Tests public void RecordProperty_IsGenerated() { var prop = typeof(ITestRecord) - .GetProperty(nameof(TestRecord.RecordProperty)); + .GetProperty(nameof(TestRecord.RecordProperty))!; prop.Should().NotBeNull(); prop.GetMethod.Should().NotBeNull(); prop.SetMethod.Should().NotBeNull(); - prop.SetMethod.ReturnParameter.GetRequiredCustomModifiers().Should().Contain(typeof(IsExternalInit)); + prop.SetMethod!.ReturnParameter!.GetRequiredCustomModifiers().Should().Contain(typeof(IsExternalInit)); _sut.RecordProperty.Should().Be(420); } @@ -35,7 +35,7 @@ namespace InterfaceGenerator.Tests nameof(TestRecord.RecordMethod)); method.Should().NotBeNull(); - method.ReturnType.Should().Be(typeof(void)); + method!.ReturnType.Should().Be(typeof(void)); var parameters = method.GetParameters(); parameters.Should().BeEmpty(); @@ -50,7 +50,7 @@ namespace InterfaceGenerator.Tests nameof(TestRecord.Deconstruct)); method.Should().NotBeNull(); - method.ReturnType.Should().Be(typeof(void)); + method!.ReturnType.Should().Be(typeof(void)); var parameters = method.GetParameters(); parameters.Length.Should().Be(1); diff --git a/InterfaceGenerator/AttributeDataExtensions.cs b/InterfaceGenerator/AttributeDataExtensions.cs new file mode 100644 index 0000000..084842a --- /dev/null +++ b/InterfaceGenerator/AttributeDataExtensions.cs @@ -0,0 +1,14 @@ +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace InterfaceGenerator +{ + internal static class AttributeDataExtensions + { + public static string? GetNamedParamValue(this AttributeData attributeData, string paramName) + { + var pair = attributeData.NamedArguments.FirstOrDefault(x => x.Key == paramName); + return pair.Value.Value?.ToString(); + } + } +} \ No newline at end of file diff --git a/InterfaceGenerator/AutoInterfaceGenerator.cs b/InterfaceGenerator/AutoInterfaceGenerator.cs index 2eedb83..376448b 100644 --- a/InterfaceGenerator/AutoInterfaceGenerator.cs +++ b/InterfaceGenerator/AutoInterfaceGenerator.cs @@ -8,7 +8,6 @@ using System.Text; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; namespace InterfaceGenerator @@ -47,7 +46,9 @@ namespace InterfaceGenerator private void GenerateInterfaces(GeneratorExecutionContext context) { if (context.SyntaxReceiver is not SyntaxReceiver receiver) + { return; + } var compilation = GetCompilation(context); InitAttributes(compilation); @@ -67,45 +68,35 @@ namespace InterfaceGenerator } } - private string GetVisibilityModifier(INamedTypeSymbol implTypeSymbol, AttributeData attributeData) + private static string InferVisibilityModifier(ISymbol implTypeSymbol, AttributeData attributeData) { - var pair = attributeData.NamedArguments.FirstOrDefault(x => x.Key == Attributes.VisibilityModifierPropName); - string? result = pair.Value.Value?.ToString(); - + string? result = attributeData.GetNamedParamValue(Attributes.VisibilityModifierPropName); if (!string.IsNullOrEmpty(result)) { - return result; + return result!; } return implTypeSymbol.DeclaredAccessibility switch { Accessibility.Public => "public", - var _ => "internal", + _ => "internal", }; } - private string GetInterfaceName(INamedTypeSymbol implTypeSymbol, AttributeData attributeData) + private static string InferInterfaceName(ISymbol implTypeSymbol, AttributeData attributeData) { - var pair = attributeData.NamedArguments.FirstOrDefault(x => x.Key == Attributes.InterfaceNamePropName); - string? result = pair.Value.Value?.ToString(); - - if (!string.IsNullOrEmpty(result)) - { - return result; - } - - return "I" + implTypeSymbol.Name; + return attributeData.GetNamedParamValue(Attributes.InterfaceNamePropName) ?? $"I{implTypeSymbol.Name}"; } private string GenerateInterfaceCode(INamedTypeSymbol implTypeSymbol, AttributeData attributeData) { using var stream = new MemoryStream(); var streamWriter = new StreamWriter(stream, Encoding.UTF8); - var codeWriter = new IndentedTextWriter(streamWriter, GeneratorConsts.Indent); + var codeWriter = new IndentedTextWriter(streamWriter, " "); var namespaceName = implTypeSymbol.ContainingNamespace.ToDisplayString(); - var interfaceName = GetInterfaceName(implTypeSymbol, attributeData); - var visibilityModifier = GetVisibilityModifier(implTypeSymbol, attributeData); + var interfaceName = InferInterfaceName(implTypeSymbol, attributeData); + var visibilityModifier = InferVisibilityModifier(implTypeSymbol, attributeData); codeWriter.WriteLine("namespace {0}", namespaceName); codeWriter.WriteLine("{"); @@ -132,7 +123,7 @@ namespace InterfaceGenerator return reader.ReadToEnd(); } - private void WriteTypeGenericsIfNeeded(IndentedTextWriter writer, INamedTypeSymbol implTypeSymbol) + private static void WriteTypeGenericsIfNeeded(TextWriter writer, INamedTypeSymbol implTypeSymbol) { if (!implTypeSymbol.IsGenericType) { @@ -146,16 +137,12 @@ namespace InterfaceGenerator WriteTypeParameterConstraints(writer, implTypeSymbol.TypeParameters); } - private void GenerateInterfaceMemberDefinitions(IndentedTextWriter writer, INamedTypeSymbol implTypeSymbol) + private void GenerateInterfaceMemberDefinitions(TextWriter writer, INamespaceOrTypeSymbol implTypeSymbol) { foreach (var member in implTypeSymbol.GetMembers()) { - if (member.DeclaredAccessibility != Accessibility.Public) - { - continue; - } - - if (member.HasAttribute(_ignoreAttribute)) + if (member.DeclaredAccessibility != Accessibility.Public || + member.HasAttribute(_ignoreAttribute)) { continue; } @@ -164,7 +151,7 @@ namespace InterfaceGenerator } } - private static void GenerateInterfaceMemberDefinition(IndentedTextWriter writer, ISymbol member) + private static void GenerateInterfaceMemberDefinition(TextWriter writer, ISymbol member) { switch (member) { @@ -177,7 +164,7 @@ namespace InterfaceGenerator } } - private static void WriteSymbolDocsIfPresent(IndentedTextWriter writer, ISymbol symbol) + private static void WriteSymbolDocsIfPresent(TextWriter writer, ISymbol symbol) { var xml = symbol.GetDocumentationCommentXml(); if (string.IsNullOrWhiteSpace(xml)) @@ -208,13 +195,12 @@ namespace InterfaceGenerator } } - private static bool IsPublicOrInternal(IMethodSymbol methodSymbol) + private static bool IsPublicOrInternal(ISymbol symbol) { - return methodSymbol.DeclaredAccessibility == Accessibility.Public || - methodSymbol.DeclaredAccessibility == Accessibility.Internal; + return symbol.DeclaredAccessibility is Accessibility.Public or Accessibility.Internal; } - private static void GeneratePropertyDefinition(IndentedTextWriter writer, IPropertySymbol propertySymbol) + private static void GeneratePropertyDefinition(TextWriter writer, IPropertySymbol propertySymbol) { if (propertySymbol.IsStatic) { @@ -267,7 +253,7 @@ namespace InterfaceGenerator writer.WriteLine("}"); } - private static void GenerateMethodDefinition(IndentedTextWriter writer, IMethodSymbol methodSymbol) + private static void GenerateMethodDefinition(TextWriter writer, IMethodSymbol methodSymbol) { if (methodSymbol.MethodKind != MethodKind.Ordinary || methodSymbol.IsStatic) { @@ -374,7 +360,7 @@ namespace InterfaceGenerator } private static void WriteTypeParameterConstraints( - IndentedTextWriter writer, + TextWriter writer, IEnumerable typeParameters) { foreach (var typeParameter in typeParameters) @@ -404,10 +390,10 @@ namespace InterfaceGenerator return receiver.CandidateTypes.Select(candidate => GetTypeSymbol(compilation, candidate)); } - private static INamedTypeSymbol GetTypeSymbol(Compilation compilation, TypeDeclarationSyntax type) + private static INamedTypeSymbol GetTypeSymbol(Compilation compilation, SyntaxNode type) { var model = compilation.GetSemanticModel(type.SyntaxTree); - var typeSymbol = ModelExtensions.GetDeclaredSymbol(model, type)!; + var typeSymbol = model.GetDeclaredSymbol(type)!; return (INamedTypeSymbol)typeSymbol; } diff --git a/InterfaceGenerator/GeneratorConsts.cs b/InterfaceGenerator/GeneratorConsts.cs deleted file mode 100644 index a4b56f3..0000000 --- a/InterfaceGenerator/GeneratorConsts.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace InterfaceGenerator -{ - internal class GeneratorConsts - { - public const string Indent = " "; - } -} \ No newline at end of file