Refactor DiagnosticProvider to DiagnosticsFactory.

This commit is contained in:
Mohammadreza Taikandi 2021-04-17 08:13:08 +01:00
parent 3d0f9e5bbb
commit 2f8a897676
6 changed files with 53 additions and 48 deletions

View File

@ -1,37 +0,0 @@
using System.Collections.Immutable;
using System.Linq;
using MapTo.Sources;
using Microsoft.CodeAnalysis;
using static MapTo.Sources.Constants;
namespace MapTo
{
internal static class DiagnosticProvider
{
private const string UsageCategory = "Usage";
private const string ErrorId = "MT0";
private const string InfoId = "MT1";
private const string WarningId = "MT2";
internal static Diagnostic TypeNotFoundError(Location location, string syntaxName) =>
Create($"{ErrorId}010", location, "Type not found.", $"Unable to find '{syntaxName}' type.");
internal static Diagnostic MapFromAttributeNotFoundError(Location location) =>
Create($"{ErrorId}020", location, "Attribute Not Available", $"Unable to find {MapFromAttributeSource.AttributeName} type.");
internal static Diagnostic NoMatchingPropertyFoundError(Location location, INamedTypeSymbol classType, INamedTypeSymbol sourceType) =>
Create($"{ErrorId}030", location, "Type Mismatch", $"No matching properties found between '{classType.ToDisplayString()}' and '{sourceType.ToDisplayString()}' types.");
internal static Diagnostic NoMatchingPropertyTypeFoundError(IPropertySymbol property) =>
Create($"{ErrorId}031", property.Locations.FirstOrDefault(), "Type Mismatch", $"Cannot create a map for '{property.ToDisplayString()}' property because source and destination types are not implicitly convertible. Consider using '{MapTypeConverterAttributeSource.FullyQualifiedName}' to provide a type converter or ignore the property using '{IgnorePropertyAttributeSource.FullyQualifiedName}'.");
internal static Diagnostic InvalidTypeConverterGenericTypesError(IPropertySymbol property, IPropertySymbol sourceProperty) =>
Create($"{ErrorId}032", property.Locations.FirstOrDefault(), "Type Mismatch", $"Cannot map '{property.ToDisplayString()}' property because the annotated converter does not implement '{RootNamespace}.{ITypeConverterSource.InterfaceName}<{sourceProperty.Type.ToDisplayString()}, {property.Type.ToDisplayString()}>'.");
internal static Diagnostic ConfigurationParseError(string error) =>
Create($"{ErrorId}040", Location.None, "Incorrect Configuration", error);
private static Diagnostic Create(string id, Location? location, string title, string message, DiagnosticSeverity severity = DiagnosticSeverity.Error) =>
Diagnostic.Create(new DiagnosticDescriptor(id, title, message, UsageCategory, severity, true), location ?? Location.None);
}
}

View File

@ -0,0 +1,42 @@
using System.Collections.Immutable;
using System.Linq;
using MapTo.Sources;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using static MapTo.Sources.Constants;
namespace MapTo
{
internal static class DiagnosticsFactory
{
private const string UsageCategory = "Usage";
private const string CodePrefix = "MT";
private const string ErrorId = CodePrefix + "0";
private const string InfoId = CodePrefix + "1";
private const string WarningId = CodePrefix + "2";
internal static Diagnostic TypeNotFoundError(Location location, string syntaxName) =>
Create($"{ErrorId}010", location, $"Unable to find '{syntaxName}' type.");
internal static Diagnostic MapFromAttributeNotFoundError(Location location) =>
Create($"{ErrorId}020", location, $"Unable to find {MapFromAttributeSource.AttributeName} type.");
internal static Diagnostic NoMatchingPropertyFoundError(Location location, INamedTypeSymbol classType, INamedTypeSymbol sourceType) =>
Create($"{ErrorId}030", location, $"No matching properties found between '{classType.ToDisplayString()}' and '{sourceType.ToDisplayString()}' types.");
internal static Diagnostic NoMatchingPropertyTypeFoundError(IPropertySymbol property) =>
Create($"{ErrorId}031", property.Locations.FirstOrDefault(), $"Cannot create a map for '{property.ToDisplayString()}' property because source and destination types are not implicitly convertible. Consider using '{MapTypeConverterAttributeSource.FullyQualifiedName}' to provide a type converter or ignore the property using '{IgnorePropertyAttributeSource.FullyQualifiedName}'.");
internal static Diagnostic InvalidTypeConverterGenericTypesError(IPropertySymbol property, IPropertySymbol sourceProperty) =>
Create($"{ErrorId}032", property.Locations.FirstOrDefault(), $"Cannot map '{property.ToDisplayString()}' property because the annotated converter does not implement '{RootNamespace}.{ITypeConverterSource.InterfaceName}<{sourceProperty.Type.ToDisplayString()}, {property.Type.ToDisplayString()}>'.");
internal static Diagnostic ConfigurationParseError(string error) =>
Create($"{ErrorId}040", Location.None, error);
internal static Diagnostic MissingConstructorArgument(ConstructorDeclarationSyntax constructorSyntax) =>
Create($"{ErrorId}050", constructorSyntax.GetLocation(), "There are no argument given that corresponds to the required formal parameter.");
private static Diagnostic Create(string id, Location? location, string message, DiagnosticSeverity severity = DiagnosticSeverity.Error) =>
Diagnostic.Create(new DiagnosticDescriptor(id, null, message, UsageCategory, severity, true), location ?? Location.None);
}
}

View File

@ -30,7 +30,7 @@ namespace MapTo.Extensions
}
catch (Exception)
{
context.ReportDiagnostic(DiagnosticProvider.ConfigurationParseError($"'{optionValue}' is not a valid value for {PropertyNameSuffix}{propertyName} property."));
context.ReportDiagnostic(DiagnosticsFactory.ConfigurationParseError($"'{optionValue}' is not a valid value for {PropertyNameSuffix}{propertyName} property."));
return defaultValue;
}
}

View File

@ -66,7 +66,7 @@ namespace MapTo.Tests.Extensions
Assert.False(true, builder.ToString());
}
internal static void ShouldBeUnsuccessful(this ImmutableArray<Diagnostic> diagnostics, Diagnostic expectedError)
internal static void ShouldNotBeSuccessful(this ImmutableArray<Diagnostic> diagnostics, Diagnostic expectedError)
{
var actualDiagnostics = diagnostics.SingleOrDefault(d => d.Id == expectedError.Id);
var compilationDiagnostics = actualDiagnostics == null ? diagnostics : diagnostics.Except(new[] { actualDiagnostics });

View File

@ -56,9 +56,9 @@ namespace MapTo
var (compilation, diagnostics) = CSharpGenerator.GetOutputCompilation(source, analyzerConfigOptions: DefaultAnalyzerOptions);
// Assert
var expectedError = DiagnosticProvider.NoMatchingPropertyTypeFoundError(GetSourcePropertySymbol("Prop4", compilation));
var expectedError = DiagnosticsFactory.NoMatchingPropertyTypeFoundError(GetSourcePropertySymbol("Prop4", compilation));
diagnostics.ShouldBeUnsuccessful(expectedError);
diagnostics.ShouldNotBeSuccessful(expectedError);
}
[Fact]
@ -178,7 +178,7 @@ namespace Test
var bazType = compilation.GetTypeByMetadataName("Test.Baz");
bazType.ShouldNotBeNull();
var expectedDiagnostic = DiagnosticProvider.NoMatchingPropertyFoundError(fooType.Locations.Single(), fooType, bazType);
var expectedDiagnostic = DiagnosticsFactory.NoMatchingPropertyFoundError(fooType.Locations.Single(), fooType, bazType);
var error = diagnostics.FirstOrDefault(d => d.Id == expectedDiagnostic.Id);
error.ShouldNotBeNull();
}
@ -425,8 +425,8 @@ namespace Test
var (compilation, diagnostics) = CSharpGenerator.GetOutputCompilation(source, analyzerConfigOptions: DefaultAnalyzerOptions);
// Assert
var expectedError = DiagnosticProvider.NoMatchingPropertyTypeFoundError(GetSourcePropertySymbol("InnerProp1", compilation));
diagnostics.ShouldBeUnsuccessful(expectedError);
var expectedError = DiagnosticsFactory.NoMatchingPropertyTypeFoundError(GetSourcePropertySymbol("InnerProp1", compilation));
diagnostics.ShouldNotBeSuccessful(expectedError);
}
[Fact]
@ -454,8 +454,8 @@ namespace Test
var (compilation, diagnostics) = CSharpGenerator.GetOutputCompilation(source, analyzerConfigOptions: DefaultAnalyzerOptions);
// Assert
var expectedError = DiagnosticProvider.NoMatchingPropertyTypeFoundError(GetSourcePropertySymbol("InnerProp1", compilation));
diagnostics.ShouldBeUnsuccessful(expectedError);
var expectedError = DiagnosticsFactory.NoMatchingPropertyTypeFoundError(GetSourcePropertySymbol("InnerProp1", compilation));
diagnostics.ShouldNotBeSuccessful(expectedError);
}
[Fact]

View File

@ -276,8 +276,8 @@ namespace Test
var (compilation, diagnostics) = CSharpGenerator.GetOutputCompilation(source, analyzerConfigOptions: DefaultAnalyzerOptions);
// Assert
var expectedError = DiagnosticProvider.InvalidTypeConverterGenericTypesError(GetSourcePropertySymbol("Prop4", compilation), GetSourcePropertySymbol("Prop4", compilation, "Baz"));
diagnostics.ShouldBeUnsuccessful(expectedError);
var expectedError = DiagnosticsFactory.InvalidTypeConverterGenericTypesError(GetSourcePropertySymbol("Prop4", compilation), GetSourcePropertySymbol("Prop4", compilation, "Baz"));
diagnostics.ShouldNotBeSuccessful(expectedError);
}
}
}