From 3e3e48880ffcd53380c3e5b2fb0cb76050ccc227 Mon Sep 17 00:00:00 2001 From: Nikolay Pianikov Date: Fri, 3 Nov 2023 17:02:40 +0300 Subject: [PATCH] Makes warnings and errors more accurate when specifying a source --- .../Core/ApiInvocationProcessor.cs | 30 +++++++++---------- src/Pure.DI.Core/Core/MetadataBuilder.cs | 2 +- src/Pure.DI.Core/Core/MetadataValidator.cs | 2 +- .../Core/Models/CompositionName.cs | 12 +++++++- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/Pure.DI.Core/Core/ApiInvocationProcessor.cs b/src/Pure.DI.Core/Core/ApiInvocationProcessor.cs index f7fc6474..77f98a12 100644 --- a/src/Pure.DI.Core/Core/ApiInvocationProcessor.cs +++ b/src/Pure.DI.Core/Core/ApiInvocationProcessor.cs @@ -61,7 +61,7 @@ public void ProcessInvocation( case nameof(IBinding.As): if (invocation.ArgumentList.Arguments is [{ Expression: { } lifetimeExpression }]) { - metadataVisitor.VisitLifetime(new MdLifetime(semanticModel, invocation, semanticModel.GetRequiredConstantValue(lifetimeExpression))); + metadataVisitor.VisitLifetime(new MdLifetime(semanticModel, invocation.ArgumentList, semanticModel.GetRequiredConstantValue(lifetimeExpression))); } break; @@ -88,8 +88,8 @@ public void ProcessInvocation( case [{ Expression: { } publicCompositionType }]: metadataVisitor.VisitSetup( new MdSetup( - invocation, - CreateCompositionName(semanticModel.GetRequiredConstantValue(publicCompositionType), @namespace), + invocation.ArgumentList, + CreateCompositionName(semanticModel.GetRequiredConstantValue(publicCompositionType), @namespace, invocation.ArgumentList), ImmutableArray.Empty, CompositionKind.Public, GetSettings(invocation), @@ -104,8 +104,8 @@ public void ProcessInvocation( case [{ Expression: { } publicCompositionType }, { Expression: { } kindExpression }]: metadataVisitor.VisitSetup( new MdSetup( - invocation, - CreateCompositionName(semanticModel.GetRequiredConstantValue(publicCompositionType), @namespace), + invocation.ArgumentList, + CreateCompositionName(semanticModel.GetRequiredConstantValue(publicCompositionType), @namespace, invocation.ArgumentList), ImmutableArray.Empty, semanticModel.GetRequiredConstantValue(kindExpression), GetSettings(invocation), @@ -127,7 +127,7 @@ public void ProcessInvocation( case nameof(IConfiguration.DefaultLifetime): if (invocation.ArgumentList.Arguments is [{ Expression: { } defaultLifetimeSyntax }]) { - metadataVisitor.VisitDefaultLifetime(new MdDefaultLifetime(new MdLifetime(semanticModel, invocation, semanticModel.GetRequiredConstantValue(defaultLifetimeSyntax)))); + metadataVisitor.VisitDefaultLifetime(new MdDefaultLifetime(new MdLifetime(semanticModel, invocation.ArgumentList, semanticModel.GetRequiredConstantValue(defaultLifetimeSyntax)))); } break; @@ -135,7 +135,7 @@ public void ProcessInvocation( case nameof(IConfiguration.DependsOn): if (BuildConstantArgs(semanticModel, invocation.ArgumentList.Arguments) is [..] compositionTypeNames) { - metadataVisitor.VisitDependsOn(new MdDependsOn(semanticModel, invocation, compositionTypeNames.Select(i => CreateCompositionName(i, @namespace)).ToImmutableArray())); + metadataVisitor.VisitDependsOn(new MdDependsOn(semanticModel, invocation.ArgumentList, compositionTypeNames.Select(i => CreateCompositionName(i, @namespace, invocation.ArgumentList)).ToImmutableArray())); } break; @@ -152,7 +152,7 @@ public void ProcessInvocation( metadataVisitor.VisitContract( new MdContract( semanticModel, - invocation, + invocation.ArgumentList, semanticModel.GetTypeSymbol(contractType, _cancellationToken), BuildTags(semanticModel, invocation.ArgumentList.Arguments).ToImmutable())); } @@ -212,7 +212,7 @@ public void ProcessInvocation( tag = new MdTag(0, semanticModel.GetConstantValue(rootArgs[1].Expression)); } - metadataVisitor.VisitRoot(new MdRoot(invocation, semanticModel, rootSymbol, name, tag)); + metadataVisitor.VisitRoot(new MdRoot(rootType, semanticModel, rootSymbol, name, tag)); } break; @@ -220,7 +220,7 @@ public void ProcessInvocation( case nameof(IConfiguration.TypeAttribute): if (genericName.TypeArgumentList.Arguments is [{ } typeAttributeType]) { - metadataVisitor.VisitTypeAttribute(new MdTypeAttribute(semanticModel, invocation, semanticModel.GetTypeSymbol(typeAttributeType, _cancellationToken), BuildConstantArgs(semanticModel, invocation.ArgumentList.Arguments) is [int positionVal] ? positionVal : 0)); + metadataVisitor.VisitTypeAttribute(new MdTypeAttribute(semanticModel, invocation.ArgumentList, semanticModel.GetTypeSymbol(typeAttributeType, _cancellationToken), BuildConstantArgs(semanticModel, invocation.ArgumentList.Arguments) is [int positionVal] ? positionVal : 0)); } break; @@ -228,7 +228,7 @@ public void ProcessInvocation( case nameof(IConfiguration.TagAttribute): if (genericName.TypeArgumentList.Arguments is [{ } tagAttributeType]) { - metadataVisitor.VisitTagAttribute(new MdTagAttribute(semanticModel, invocation, semanticModel.GetTypeSymbol(tagAttributeType, _cancellationToken), BuildConstantArgs(semanticModel, invocation.ArgumentList.Arguments) is [int positionVal] ? positionVal : 0)); + metadataVisitor.VisitTagAttribute(new MdTagAttribute(semanticModel, invocation.ArgumentList, semanticModel.GetTypeSymbol(tagAttributeType, _cancellationToken), BuildConstantArgs(semanticModel, invocation.ArgumentList.Arguments) is [int positionVal] ? positionVal : 0)); } break; @@ -236,7 +236,7 @@ public void ProcessInvocation( case nameof(IConfiguration.OrdinalAttribute): if (genericName.TypeArgumentList.Arguments is [{ } ordinalAttributeType]) { - metadataVisitor.VisitOrdinalAttribute(new MdOrdinalAttribute(semanticModel, invocation, semanticModel.GetTypeSymbol(ordinalAttributeType, _cancellationToken), BuildConstantArgs(semanticModel, invocation.ArgumentList.Arguments) is [int positionVal] ? positionVal : 0)); + metadataVisitor.VisitOrdinalAttribute(new MdOrdinalAttribute(semanticModel, invocation.ArgumentList, semanticModel.GetTypeSymbol(ordinalAttributeType, _cancellationToken), BuildConstantArgs(semanticModel, invocation.ArgumentList.Arguments) is [int positionVal] ? positionVal : 0)); } break; @@ -267,7 +267,7 @@ private void VisitArg( var argType = semanticModel.GetTypeSymbol(argTypeSyntax, _cancellationToken); metadataVisitor.VisitContract(new MdContract(semanticModel, invocation, argType, tags.ToImmutableArray())); - metadataVisitor.VisitArg(new MdArg(semanticModel, invocation, argType, name, kind)); + metadataVisitor.VisitArg(new MdArg(semanticModel, argTypeSyntax, argType, name, kind)); } } @@ -418,7 +418,7 @@ private static ImmutableArray.Builder BuildTags(SemanticModel semanticMod return builder; } - private static CompositionName CreateCompositionName(string name, string ns) + private static CompositionName CreateCompositionName(string name, string ns, SyntaxNode source) { string className; string newNamespace; @@ -439,6 +439,6 @@ private static CompositionName CreateCompositionName(string name, string ns) newNamespace = ns; } - return new CompositionName(className, newNamespace); + return new CompositionName(className, newNamespace, source); } } \ No newline at end of file diff --git a/src/Pure.DI.Core/Core/MetadataBuilder.cs b/src/Pure.DI.Core/Core/MetadataBuilder.cs index b051c1a4..6b8e208f 100644 --- a/src/Pure.DI.Core/Core/MetadataBuilder.cs +++ b/src/Pure.DI.Core/Core/MetadataBuilder.cs @@ -105,7 +105,7 @@ private IEnumerable ResolveDependencies( private void MergeSetups(IEnumerable setups, out MdSetup mergedSetup, bool resolveDependsOn) { SyntaxNode? source = default; - var name = new CompositionName("Composition", ""); + var name = new CompositionName("Composition", "", default); var kind = CompositionKind.Global; var settings = new Hints(); var bindingsBuilder = ImmutableArray.CreateBuilder(64); diff --git a/src/Pure.DI.Core/Core/MetadataValidator.cs b/src/Pure.DI.Core/Core/MetadataValidator.cs index bf5c4bb4..cad59dcd 100644 --- a/src/Pure.DI.Core/Core/MetadataValidator.cs +++ b/src/Pure.DI.Core/Core/MetadataValidator.cs @@ -29,7 +29,7 @@ public bool Validate(in MdSetup setup) && (!SyntaxFacts.IsValidIdentifier(setup.Name.ClassName) || !IsValidOrEmptyIdentifier(setup.Name.Namespace.Replace('.', '_')))) { - _logger.CompileError($"Invalid composition type name \"{setup.Name}\".", setup.Source.GetLocation(), LogId.ErrorInvalidMetadata); + _logger.CompileError($"Invalid composition type name \"{setup.Name}\".", (setup.Name.Source ?? setup.Source).GetLocation(), LogId.ErrorInvalidMetadata); isValid = false; } diff --git a/src/Pure.DI.Core/Core/Models/CompositionName.cs b/src/Pure.DI.Core/Core/Models/CompositionName.cs index 46b8ce72..76b6e2cd 100644 --- a/src/Pure.DI.Core/Core/Models/CompositionName.cs +++ b/src/Pure.DI.Core/Core/Models/CompositionName.cs @@ -1,7 +1,17 @@ namespace Pure.DI.Core.Models; -public readonly record struct CompositionName(string ClassName, string Namespace) +public readonly record struct CompositionName(string ClassName, string Namespace, SyntaxNode? Source) { + public bool Equals(CompositionName other) => ClassName == other.ClassName && Namespace == other.Namespace; + + public override int GetHashCode() + { + unchecked + { + return (ClassName.GetHashCode() * 397) ^ Namespace.GetHashCode(); + } + } + public string FullName => string.IsNullOrWhiteSpace(Namespace) ? ClassName : Namespace + "." + ClassName;