From 32c4b61204d746c30796a3b6d4c436cfcbd003ce Mon Sep 17 00:00:00 2001 From: Rekkonnect Date: Tue, 6 Aug 2024 13:36:51 +0300 Subject: [PATCH 1/2] Highlight attribute values from AttributeData --- .../AnalysisTreeListView.axaml.cs | 18 +- Syndiesis/Core/AttributeDataViewModel.cs | 176 +++++++++++++++ Syndiesis/Core/AttributeTree.cs | 17 +- .../AttributesAnalysisNodeCreator.cs | 210 ++++++++++++++---- .../BaseAnalysisNodeCreator.cs | 6 +- .../SymbolAnalysisNodeCreator.cs | 77 +------ .../Core/ISingleTreeCompilationSource.cs | 1 + Syndiesis/Core/RoslynExtensions.cs | 7 + 8 files changed, 385 insertions(+), 127 deletions(-) create mode 100644 Syndiesis/Core/AttributeDataViewModel.cs diff --git a/Syndiesis/Controls/AnalysisVisualization/AnalysisTreeListView.axaml.cs b/Syndiesis/Controls/AnalysisVisualization/AnalysisTreeListView.axaml.cs index a7dd462..34034cd 100644 --- a/Syndiesis/Controls/AnalysisVisualization/AnalysisTreeListView.axaml.cs +++ b/Syndiesis/Controls/AnalysisVisualization/AnalysisTreeListView.axaml.cs @@ -163,7 +163,7 @@ private void DestroyChildrenFromSecondLevel() if (parentNode is null) return current; - if (current.NodeLine.AnalysisNodeKind != targetKind) + if (MatchesNodeKind(current.NodeLine.AnalysisNodeKind, targetKind)) { goto next; } @@ -182,6 +182,18 @@ private void DestroyChildrenFromSecondLevel() } } + private static bool MatchesNodeKind(AnalysisNodeKind value, AnalysisNodeKind target) + { + if (target is AnalysisNodeKind.Symbol) + { + return value + is AnalysisNodeKind.Attribute + or AnalysisNodeKind.Symbol; + } + + return value == target; + } + protected override void OnPointerExited(PointerEventArgs e) { base.OnPointerExited(e); @@ -408,7 +420,7 @@ private async Task AwaitExpansion(AnalysisTreeListNode node) if (current is null) return null; - if (current.NodeLine.AnalysisNodeKind == TargetAnalysisNodeKind) + if (MatchesNodeKind(current.NodeLine.AnalysisNodeKind, TargetAnalysisNodeKind)) { return current; } @@ -459,7 +471,7 @@ private async Task AwaitExpansion(AnalysisTreeListNode node) .Where(s => { var nodeLine = s.NodeLine; - return nodeLine.AnalysisNodeKind == TargetAnalysisNodeKind + return MatchesNodeKind(nodeLine.AnalysisNodeKind, TargetAnalysisNodeKind) && nodeLine.DisplaySpan.Contains(span); }) .ToArray(); diff --git a/Syndiesis/Core/AttributeDataViewModel.cs b/Syndiesis/Core/AttributeDataViewModel.cs new file mode 100644 index 0000000..6ac22c7 --- /dev/null +++ b/Syndiesis/Core/AttributeDataViewModel.cs @@ -0,0 +1,176 @@ +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.VisualBasic; +using System.Collections.Immutable; +using System.Threading; + +namespace Syndiesis.Core; + +public sealed class AttributeDataViewModel +{ + public required AttributeData AttributeData { get; init; } + public required ImmutableArray ConstructorArguments { get; init; } + public required ImmutableArray NamedArguments { get; init; } + + public ImmutableArray AllArguments + { + get + { + return + [ + .. ConstructorArguments, + .. NamedArguments, + ]; + } + } + + private AttributeDataViewModel() { } + + public static AttributeDataViewModel? Create( + AttributeData data, + CancellationToken cancellationToken = default) + { + var syntax = data.ApplicationSyntaxReference?.GetSyntax(cancellationToken); + if (syntax is null) + return null; + + if (data.HasNoArguments()) + return Empty(data); + + switch (syntax) + { + case CSharpSyntaxNode csAttribute: + return CreateCSharpModel(data, csAttribute); + case VisualBasicSyntaxNode vbAttribute: + return CreateVisualBasicModel(data, vbAttribute); + default: + return null; + } + } + + private static AttributeDataViewModel Empty(AttributeData data) + { + return new() + { + AttributeData = data, + ConstructorArguments = [], + NamedArguments = [], + }; + } + + private static AttributeDataViewModel? CreateCSharpModel( + AttributeData data, CSharpSyntaxNode csAttribute) + { + var attribute = csAttribute as Microsoft.CodeAnalysis.CSharp.Syntax.AttributeSyntax; + if (attribute is null) + return null; + + var argumentList = attribute.ArgumentList; + if (argumentList is null) + return Empty(data); + + var arguments = argumentList.Arguments; + if (arguments is []) + return Empty(data); + + return ConstructFromArguments(data, arguments); + } + + private static AttributeDataViewModel? CreateVisualBasicModel( + AttributeData data, VisualBasicSyntaxNode vbAttribute) + { + var attribute = vbAttribute as Microsoft.CodeAnalysis.VisualBasic.Syntax.AttributeSyntax; + if (attribute is null) + return null; + + var argumentList = attribute.ArgumentList; + if (argumentList is null) + return Empty(data); + + var arguments = argumentList.Arguments; + if (arguments is []) + return Empty(data); + + return ConstructFromArguments(data, arguments); + } + + private static AttributeDataViewModel ConstructFromArguments( + AttributeData data, SeparatedSyntaxList arguments) + where TSyntax : SyntaxNode + { + ImmutableArray regularArguments = []; + ImmutableArray namedArguments = []; + + if (data.ConstructorArguments is not [] and var constructorArgumentsData) + { + var regularArgumentsBuilder = ImmutableArray.CreateBuilder( + constructorArgumentsData.Length); + + // We always have a constructor if we have constructor arguments + // We expect a potential breaking API change that returns a null + // constructor with a non-empty argument list, in which case we show the param order + var constructor = data.AttributeConstructor; + var constructorParameters = constructor?.Parameters; + var mappingKind = + constructorParameters is not null + ? AttributeArgumentNameMappingKind.Parameter + : AttributeArgumentNameMappingKind.ParameterIndex; + for (int i = 0; i < constructorArgumentsData.Length; i++) + { + var argumentSyntax = arguments[i]; + var value = constructorArgumentsData[i]; + var parameter = constructorParameters?[i]; + var displayName = parameter?.Name ?? i.ToString(); + regularArgumentsBuilder.Add(new( + argumentSyntax, + displayName, + value, + mappingKind)); + } + regularArguments = regularArgumentsBuilder.ToImmutable(); + } + + if (data.NamedArguments is not [] and var namedArgumentsData) + { + var namedArgumentsBuilder = ImmutableArray.CreateBuilder( + namedArgumentsData.Length); + + int offset = data.ConstructorArguments.Length; + + for (int i = 0; i < namedArgumentsData.Length; i++) + { + var argumentSyntax = arguments[i + offset]; + var kvp = namedArgumentsData[i]; + var name = kvp.Key; + var value = kvp.Value; + namedArgumentsBuilder.Add(new( + argumentSyntax, + name, + value, + AttributeArgumentNameMappingKind.Named)); + } + namedArguments = namedArgumentsBuilder.ToImmutable(); + } + + return new() + { + AttributeData = data, + ConstructorArguments = regularArguments, + NamedArguments = namedArguments, + }; + } + + public sealed record class LinkedAttributeArgument( + SyntaxNode ArgumentSyntax, + string Name, + TypedConstant Value, + AttributeArgumentNameMappingKind MappingKind) + ; + + public enum AttributeArgumentNameMappingKind + { + Parameter, + ParameterIndex, + Named, + } +} diff --git a/Syndiesis/Core/AttributeTree.cs b/Syndiesis/Core/AttributeTree.cs index 5c8c442..b501c13 100644 --- a/Syndiesis/Core/AttributeTree.cs +++ b/Syndiesis/Core/AttributeTree.cs @@ -1,4 +1,5 @@ -using Microsoft.CodeAnalysis; +using Garyon.Functions; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.VisualBasic; @@ -121,17 +122,21 @@ ImmutableArray DataViews( ImmutableArray data) { return data.Select(FromAttribute) - .ToImmutableArray(); + .Where(Predicates.NotNull) + .ToImmutableArray()!; } - AttributeDataView FromAttribute(AttributeData data) + AttributeDataView? FromAttribute(AttributeData data) { + var model = AttributeDataViewModel.Create(data); + if (model is null) + return null; var syntax = data.ApplicationSyntaxReference?.GetSyntax(cancellationToken); if (syntax is null) - return new(data, null); + return new(model, null); var operation = semanticModel.GetOperation(syntax, cancellationToken); - return new AttributeDataView(data, operation as IAttributeOperation); + return new AttributeDataView(model, operation as IAttributeOperation); } } @@ -220,5 +225,5 @@ public sealed record SymbolContainer( ISymbol Symbol, ImmutableArray Attributes); public sealed record AttributeDataView( - AttributeData Data, IAttributeOperation? AttributeOperation); + AttributeDataViewModel Data, IAttributeOperation? AttributeOperation); } diff --git a/Syndiesis/Core/DisplayAnalysis/AttributesAnalysisNodeCreator.cs b/Syndiesis/Core/DisplayAnalysis/AttributesAnalysisNodeCreator.cs index 4a47912..96190aa 100644 --- a/Syndiesis/Core/DisplayAnalysis/AttributesAnalysisNodeCreator.cs +++ b/Syndiesis/Core/DisplayAnalysis/AttributesAnalysisNodeCreator.cs @@ -1,4 +1,5 @@ using Avalonia.Media; +using Garyon.Functions; using Microsoft.CodeAnalysis; using Syndiesis.Controls.AnalysisVisualization; using Syndiesis.Controls.Inlines; @@ -6,6 +7,7 @@ using Syndiesis.Utilities; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; namespace Syndiesis.Core.DisplayAnalysis; @@ -27,7 +29,9 @@ public sealed partial class AttributesAnalysisNodeCreator private readonly AttributeDataViewRootViewNodeCreator _attributeDataViewCreator; private readonly AttributeDataRootViewNodeCreator _attributeDataCreator; private readonly AttributeDataListRootViewNodeCreator _attributeDataListCreator; - private readonly TypedConstantRootViewNodeCreator _typedConstantCreator; + private readonly LinkedAttributeArgumentRootViewNodeCreator _linkedAttributeArgumentCreator; + private readonly RegularLinkedAttributeArgumentListViewNodeCreator _regularLinkedAttributeArgumentListCreator; + private readonly NamedLinkedAttributeArgumentListViewNodeCreator _namedLinkedAttributeArgumentListCreator; private readonly AttributeTreeSymbolContainerRootViewNodeCreator _symbolContainerCreator; public AttributesAnalysisNodeCreator( @@ -38,7 +42,9 @@ public AttributesAnalysisNodeCreator( _attributeDataViewCreator = new(this); _attributeDataCreator = new(this); _attributeDataListCreator = new(this); - _typedConstantCreator = new(this); + _linkedAttributeArgumentCreator = new(this); + _regularLinkedAttributeArgumentListCreator = new(this); + _namedLinkedAttributeArgumentListCreator = new(this); _symbolContainerCreator = new(this); } @@ -54,14 +60,16 @@ public AttributesAnalysisNodeCreator( case AttributeTree.AttributeDataView view: return CreateRootAttributeView(view, valueSource, includeChildren); - case AttributeData attribute: - return CreateRootAttribute(attribute, valueSource, includeChildren); - case IReadOnlyList attributeList: return CreateRootAttributeList(attributeList, valueSource, includeChildren); - case TypedConstant typedConstant: - return CreateRootTypedConstant(typedConstant, valueSource, includeChildren); + case AttributeDataViewModel attributeDataViewModel: + return CreateRootAttributeDataViewModel( + attributeDataViewModel, valueSource, includeChildren); + + case AttributeDataViewModel.LinkedAttributeArgument linkedAttributeArgument: + return CreateRootLinkedAttributeArgument( + linkedAttributeArgument, valueSource, includeChildren); case SyntaxNode syntaxNode: return CreateRootSyntaxNode(syntaxNode, valueSource); @@ -90,8 +98,17 @@ public AnalysisTreeListNode CreateRootAttributeView( return _attributeDataViewCreator.CreateNode(view, valueSource, includeChildren); } - public AnalysisTreeListNode CreateRootAttribute( - AttributeData attribute, + public AnalysisTreeListNode CreateRootAttributeList( + IReadOnlyList attributeList, + TDisplayValueSource? valueSource, + bool includeChildren = true) + where TDisplayValueSource : IDisplayValueSource + { + return _attributeDataListCreator.CreateNode(attributeList, valueSource, includeChildren); + } + + public AnalysisTreeListNode CreateRootAttributeDataViewModel( + AttributeDataViewModel attribute, TDisplayValueSource? valueSource, bool includeChildren = true) where TDisplayValueSource : IDisplayValueSource @@ -99,22 +116,34 @@ public AnalysisTreeListNode CreateRootAttribute( return _attributeDataCreator.CreateNode(attribute, valueSource, includeChildren); } - public AnalysisTreeListNode CreateRootAttributeList( - IReadOnlyList attributeList, + public AnalysisTreeListNode CreateRootLinkedAttributeArgument( + AttributeDataViewModel.LinkedAttributeArgument linkedAttributeArgument, TDisplayValueSource? valueSource, bool includeChildren = true) where TDisplayValueSource : IDisplayValueSource { - return _attributeDataListCreator.CreateNode(attributeList, valueSource, includeChildren); + return _linkedAttributeArgumentCreator.CreateNode( + linkedAttributeArgument, valueSource, includeChildren); + } + + public AnalysisTreeListNode CreateRootRegularLinkedAttributeArgumentList( + ImmutableArray linkedAttributeArguments, + TDisplayValueSource? valueSource, + bool includeChildren = true) + where TDisplayValueSource : IDisplayValueSource + { + return _regularLinkedAttributeArgumentListCreator.CreateNode( + linkedAttributeArguments, valueSource, includeChildren); } - public AnalysisTreeListNode CreateRootTypedConstant( - TypedConstant typedConstant, + public AnalysisTreeListNode CreateRootNamedLinkedAttributeArgumentList( + ImmutableArray linkedAttributeArguments, TDisplayValueSource? valueSource, bool includeChildren = true) where TDisplayValueSource : IDisplayValueSource { - return _typedConstantCreator.CreateNode(typedConstant, valueSource, includeChildren); + return _namedLinkedAttributeArgumentListCreator.CreateNode( + linkedAttributeArguments, valueSource, includeChildren); } public AnalysisTreeListNode CreateRootAttributeTreeSymbolContainer( @@ -229,7 +258,7 @@ public sealed class AttributeDataViewRootViewNodeCreator( { public override object? AssociatedSyntaxObject(AttributeTree.AttributeDataView value) { - return value.Data; + return value.Data.AttributeData; } public override AnalysisTreeListNodeLine CreateNodeLine( @@ -271,15 +300,20 @@ private IReadOnlyList GetChildren( } public class AttributeDataRootViewNodeCreator(AttributesAnalysisNodeCreator creator) - : AttributeRootViewNodeCreator(creator) + : AttributeRootViewNodeCreator(creator) { + public override object? AssociatedSyntaxObject(AttributeDataViewModel value) + { + return value.AttributeData; + } + public override AnalysisTreeListNodeLine CreateNodeLine( - AttributeData attribute, GroupedRunInlineCollection inlines) + AttributeDataViewModel attribute, GroupedRunInlineCollection inlines) { var inline = TypeDisplayGroupedRun(typeof(AttributeData)); inlines.Add(inline); inlines.Add(NewValueKindSplitterRun()); - var className = attribute.AttributeClass?.Name; + var className = attribute.AttributeData.AttributeClass?.Name; var nameInline = CreateNameInline(className); inlines.Add(nameInline); @@ -312,30 +346,30 @@ protected GroupedRunInline TypeDetailsInline(string name) } public override AnalysisNodeChildRetriever? GetChildRetriever( - AttributeData attribute) + AttributeDataViewModel attribute) { return () => GetChildren(attribute); } - private IReadOnlyList GetChildren(AttributeData attribute) + private IReadOnlyList GetChildren(AttributeDataViewModel attribute) { return [ Creator.ParentContainer.SymbolCreator.CreateRootSymbol( - attribute.AttributeClass!, + attribute.AttributeData.AttributeClass!, Property(nameof(AttributeData.AttributeClass)), false)!, - Creator.CreateRootGeneral( + Creator.CreateRootRegularLinkedAttributeArgumentList( attribute.ConstructorArguments, Property(nameof(AttributeData.ConstructorArguments)))!, - Creator.CreateRootGeneral( + Creator.CreateRootNamedLinkedAttributeArgumentList( attribute.NamedArguments, Property(nameof(AttributeData.NamedArguments)))!, Creator.CreateRootGeneral( - attribute.ApplicationSyntaxReference, + attribute.AttributeData.ApplicationSyntaxReference, Property(nameof(AttributeData.ApplicationSyntaxReference)))!, ]; } @@ -373,54 +407,85 @@ private IReadOnlyList GetChildren( IReadOnlyList attributes) { return attributes - .Select(symbol => Creator.CreateRootAttribute(symbol, default)) + .Select(attribute + => AttributeDataViewModel.Create(attribute, default)) + .Where(Predicates.NotNull) + .Select(attribute + => Creator.CreateRootAttributeDataViewModel(attribute!, default)) .ToList() ; } } - public class TypedConstantRootViewNodeCreator(AttributesAnalysisNodeCreator creator) - : AttributeRootViewNodeCreator(creator) + public class LinkedAttributeArgumentRootViewNodeCreator(AttributesAnalysisNodeCreator creator) + : AttributeRootViewNodeCreator(creator) { public override AnalysisTreeListNodeLine CreateNodeLine( - TypedConstant constant, GroupedRunInlineCollection inlines) + AttributeDataViewModel.LinkedAttributeArgument argument, GroupedRunInlineCollection inlines) { - var inline = NestedTypeDisplayGroupedRun(typeof(TypedConstant)); - inlines.Add(inline); + var nameBrush = BrushForAttributeArgument(argument.MappingKind); + var nameInline = new SingleRunInline(Run(argument.Name, nameBrush)); + var splitterInline = CreateValueSplitterRun(); + var valueInline = TypeDisplayGroupedRun(typeof(TypedConstant)); + inlines.Add(nameInline); + inlines.Add(splitterInline); + inlines.Add(valueInline); inlines.Add(NewValueKindSplitterRun()); - inlines.Add(CreateKindInline(constant)); + inlines.Add(CreateKindInline(argument.Value)); return AnalysisTreeListNodeLine( inlines, Styles.TypedConstantDisplay); } + private static ILazilyUpdatedBrush BrushForAttributeArgument( + AttributeDataViewModel.AttributeArgumentNameMappingKind kind) + { + return kind switch + { + AttributeDataViewModel.AttributeArgumentNameMappingKind.Named + => CommonStyles.PropertyBrush, + AttributeDataViewModel.AttributeArgumentNameMappingKind.Parameter + => CommonStyles.LocalMainBrush, + + _ => CommonStyles.RawValueBrush, + }; + } + + public override object? AssociatedSyntaxObject( + AttributeDataViewModel.LinkedAttributeArgument value) + { + return value.ArgumentSyntax; + } + public override AnalysisNodeChildRetriever? GetChildRetriever( - TypedConstant constant) + AttributeDataViewModel.LinkedAttributeArgument argument) { - return () => GetChildren(constant); + return () => GetChildren(argument); } - private IReadOnlyList GetChildren(TypedConstant constant) + private IReadOnlyList GetChildren( + AttributeDataViewModel.LinkedAttributeArgument argument) { + var value = argument.Value; return [ CreateRootTypeOrNull( - constant.Type, + value.Type, Property(nameof(TypedConstant.Type)))!, Creator.CreateRootBasic( - constant.IsNull, + value.IsNull, Property(nameof(TypedConstant.IsNull))), Creator.CreateGeneralOrThrowsExceptionNode( - constant.Kind is not TypedConstantKind.Array, - () => constant.Value, + value.Kind is not TypedConstantKind.Array, + () => value.Value, Property(nameof(TypedConstant.Value)))!, Creator.CreateGeneralOrThrowsExceptionNode( - constant.Kind is TypedConstantKind.Array, - () => constant.Values, + value.Kind is TypedConstantKind.Array, + () => value.Values, Property(nameof(TypedConstant.Values)))!, ]; } @@ -446,6 +511,69 @@ private static SingleRunInline CreateKindInline(TypedConstant constant) FontStyle.Italic)); } } + + public abstract class LinkedAttributeArgumentListViewNodeCreator(AttributesAnalysisNodeCreator creator) + : AttributeRootViewNodeCreator< + ImmutableArray>(creator) + { + public override AnalysisTreeListNodeLine CreateNodeLine( + ImmutableArray arguments, + GroupedRunInlineCollection inlines) + { + var type = GetDisplayedType(); + var inline = TypeDisplayGroupedRun(type); + inlines.Add(inline); + AppendCountValueDisplay( + inlines, + arguments.Length, + nameof(ImmutableArray.Length)); + + return AnalysisTreeListNodeLine( + inlines, + CommonStyles.MemberAccessValueDisplay); + } + + protected abstract Type GetDisplayedType(); + + public override AnalysisNodeChildRetriever? GetChildRetriever( + ImmutableArray arguments) + { + if (arguments.IsEmpty()) + return null; + + return () => GetChildren(arguments); + } + + private IReadOnlyList GetChildren( + ImmutableArray arguments) + { + return arguments + .Select(argument + => Creator.CreateRootLinkedAttributeArgument(argument, default)) + .ToList() + ; + } + } + + public class RegularLinkedAttributeArgumentListViewNodeCreator( + AttributesAnalysisNodeCreator creator) + : LinkedAttributeArgumentListViewNodeCreator(creator) + { + protected override Type GetDisplayedType() + { + return typeof(ImmutableArray); + } + } + + public class NamedLinkedAttributeArgumentListViewNodeCreator( + AttributesAnalysisNodeCreator creator) + : LinkedAttributeArgumentListViewNodeCreator(creator) + { + protected override Type GetDisplayedType() + { + return typeof(ImmutableArray>); + } + } } partial class AttributesAnalysisNodeCreator diff --git a/Syndiesis/Core/DisplayAnalysis/BaseAnalysisNodeCreator.cs b/Syndiesis/Core/DisplayAnalysis/BaseAnalysisNodeCreator.cs index d3ca6d6..39d63e0 100644 --- a/Syndiesis/Core/DisplayAnalysis/BaseAnalysisNodeCreator.cs +++ b/Syndiesis/Core/DisplayAnalysis/BaseAnalysisNodeCreator.cs @@ -705,7 +705,7 @@ protected static void AppendThisDetail(ComplexGroupedRunInline inlines) inlines.Children!.Add(new(single)); } - private static Run CreateValueSplitterRun() + protected static Run CreateValueSplitterRun() { return Run(": ", CommonStyles.SplitterBrush); } @@ -863,7 +863,7 @@ protected static GroupedRunInline CountValueDisplay( int count, string propertyName) { var propertyGroup = new SingleRunInline(Run(propertyName, CommonStyles.PropertyBrush)); - var separator = Run(": ", CommonStyles.SplitterBrush); + var separator = CreateValueSplitterRun(); var countRun = Run(count.ToString(), CommonStyles.RawValueBrush); return new ComplexGroupedRunInline([ new(propertyGroup), @@ -1311,7 +1311,7 @@ private GroupedRunInline KvpValueInline(KeyValuePair return new ComplexGroupedRunInline([ new(BasicValueInline(key)), - Run(": ", CommonStyles.SplitterBrush), + CreateValueSplitterRun(), new(BasicValueInline(value)), ]); } diff --git a/Syndiesis/Core/DisplayAnalysis/SymbolAnalysisNodeCreator.cs b/Syndiesis/Core/DisplayAnalysis/SymbolAnalysisNodeCreator.cs index eeec66f..ee4121c 100644 --- a/Syndiesis/Core/DisplayAnalysis/SymbolAnalysisNodeCreator.cs +++ b/Syndiesis/Core/DisplayAnalysis/SymbolAnalysisNodeCreator.cs @@ -6,6 +6,7 @@ using Syndiesis.Utilities; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; namespace Syndiesis.Core.DisplayAnalysis; @@ -40,9 +41,6 @@ public sealed partial class SymbolAnalysisNodeCreator : BaseAnalysisNodeCreator private readonly IAliasSymbolRootViewNodeCreator _aliasSymbolCreator; private readonly SymbolListRootViewNodeCreator _symbolListCreator; - private readonly AttributeDataRootViewNodeCreator _attributeDataCreator; - private readonly AttributeDataListRootViewNodeCreator _attributeDataListCreator; - private readonly TypedConstantRootViewNodeCreator _typedConstantCreator; public SymbolAnalysisNodeCreator( BaseAnalysisNodeCreatorContainer parentContainer) @@ -66,9 +64,6 @@ public SymbolAnalysisNodeCreator( _aliasSymbolCreator = new(this); _symbolListCreator = new(this); - _attributeDataCreator = new(this); - _attributeDataListCreator = new(this); - _typedConstantCreator = new(this); } public override AnalysisTreeListNode? CreateRootViewNode( @@ -83,15 +78,6 @@ public SymbolAnalysisNodeCreator( case IReadOnlyList symbolList: return CreateRootSymbolList(symbolList, valueSource, includeChildren); - case AttributeData attribute: - return CreateRootAttribute(attribute, valueSource, includeChildren); - - case IReadOnlyList attributeList: - return CreateRootAttributeList(attributeList, valueSource, includeChildren); - - case TypedConstant typedConstant: - return CreateRootTypedConstant(typedConstant, valueSource, includeChildren); - default: break; } @@ -321,33 +307,6 @@ public AnalysisTreeListNode CreateRootSymbolList( { return _symbolListCreator.CreateNode(symbols, valueSource, includeChildren); } - - public AnalysisTreeListNode CreateRootAttribute( - AttributeData attribute, - TDisplayValueSource? valueSource, - bool includeChildren = true) - where TDisplayValueSource : IDisplayValueSource - { - return _attributeDataCreator.CreateNode(attribute, valueSource, includeChildren); - } - - public AnalysisTreeListNode CreateRootAttributeList( - IReadOnlyList attributeList, - TDisplayValueSource? valueSource, - bool includeChildren = true) - where TDisplayValueSource : IDisplayValueSource - { - return _attributeDataListCreator.CreateNode(attributeList, valueSource, includeChildren); - } - - public AnalysisTreeListNode CreateRootTypedConstant( - TypedConstant typedConstant, - TDisplayValueSource? valueSource, - bool includeChildren = true) - where TDisplayValueSource : IDisplayValueSource - { - return _typedConstantCreator.CreateNode(typedConstant, valueSource, includeChildren); - } } partial class SymbolAnalysisNodeCreator @@ -480,7 +439,7 @@ protected virtual void CreateChildren( { list.AddRange( [ - Creator.CreateRootAttributeList( + Creator.ParentContainer.AttributeCreator.CreateRootAttributeList( symbol.GetAttributes(), MethodSource(nameof(ISymbol.GetAttributes))), @@ -739,7 +698,7 @@ protected override void CreateChildren( symbol.Parameters, Property(nameof(IMethodSymbol.Parameters))), - Creator.CreateRootAttributeList( + Creator.ParentContainer.AttributeCreator.CreateRootAttributeList( symbol.GetReturnTypeAttributes(), MethodSource(nameof(IMethodSymbol.GetReturnTypeAttributes))), ]); @@ -915,36 +874,6 @@ private IReadOnlyList GetChildren( ; } } - - public sealed class AttributeDataRootViewNodeCreator(SymbolAnalysisNodeCreator creator) - : AttributesAnalysisNodeCreator.AttributeDataRootViewNodeCreator( - creator.ParentContainer.AttributeCreator) - { - public override AnalysisNodeKind GetNodeKind(AttributeData value) - { - return AnalysisNodeKind.Symbol; - } - } - - public sealed class AttributeDataListRootViewNodeCreator(SymbolAnalysisNodeCreator creator) - : AttributesAnalysisNodeCreator.AttributeDataListRootViewNodeCreator( - creator.ParentContainer.AttributeCreator) - { - public override AnalysisNodeKind GetNodeKind(IReadOnlyList value) - { - return AnalysisNodeKind.Symbol; - } - } - - public sealed class TypedConstantRootViewNodeCreator(SymbolAnalysisNodeCreator creator) - : AttributesAnalysisNodeCreator.TypedConstantRootViewNodeCreator( - creator.ParentContainer.AttributeCreator) - { - public override AnalysisNodeKind GetNodeKind(TypedConstant value) - { - return AnalysisNodeKind.Symbol; - } - } } partial class SymbolAnalysisNodeCreator diff --git a/Syndiesis/Core/ISingleTreeCompilationSource.cs b/Syndiesis/Core/ISingleTreeCompilationSource.cs index 316cab5..2262af1 100644 --- a/Syndiesis/Core/ISingleTreeCompilationSource.cs +++ b/Syndiesis/Core/ISingleTreeCompilationSource.cs @@ -19,3 +19,4 @@ public interface ISingleTreeCompilationSource public void SetSource(string source, CancellationToken cancellationToken); } + diff --git a/Syndiesis/Core/RoslynExtensions.cs b/Syndiesis/Core/RoslynExtensions.cs index 4dfd61b..9815f6a 100644 --- a/Syndiesis/Core/RoslynExtensions.cs +++ b/Syndiesis/Core/RoslynExtensions.cs @@ -306,4 +306,11 @@ public static ConversionUnion GetConversionUnion( return ConversionUnion.None; } + + public static bool HasNoArguments(this AttributeData attribute) + { + return attribute.ConstructorArguments is [] + && attribute.NamedArguments is [] + ; + } } From 635f5745e62de2dfeefcd54cfbad07b772173b07 Mon Sep 17 00:00:00 2001 From: Rekkonnect Date: Tue, 6 Aug 2024 13:53:03 +0300 Subject: [PATCH 2/2] Enable focusing on typed constant on caret hover --- .../Core/DisplayAnalysis/SyntaxObjectInfo.cs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Syndiesis/Core/DisplayAnalysis/SyntaxObjectInfo.cs b/Syndiesis/Core/DisplayAnalysis/SyntaxObjectInfo.cs index 2725524..7e186fa 100644 --- a/Syndiesis/Core/DisplayAnalysis/SyntaxObjectInfo.cs +++ b/Syndiesis/Core/DisplayAnalysis/SyntaxObjectInfo.cs @@ -113,6 +113,12 @@ private static LinePositionSpan LineSpanOrDefault(SyntaxTree? tree, TextSpan spa case AttributeData attribute: return attribute.GetAttributeApplicationSyntax()?.SyntaxTree; + case AttributeDataViewModel attributeModel: + return GetSyntaxTree(attributeModel.NamedArguments); + + case AttributeDataViewModel.LinkedAttributeArgument attributeArgument: + return GetSyntaxTree(attributeArgument.ArgumentSyntax); + // Operation case IOperation operation: return operation.Syntax.SyntaxTree; @@ -178,6 +184,12 @@ private static TextSpan GetSpan(object x) return attribute.ApplicationSyntaxReference ?.Span ?? InvalidTextSpan; + case AttributeDataViewModel attributeModel: + return GetSpan(attributeModel.NamedArguments); + + case AttributeDataViewModel.LinkedAttributeArgument attributeArgument: + return GetSpan(attributeArgument.ArgumentSyntax); + // Operation case IOperation operation: return operation.Syntax.Span; @@ -244,6 +256,12 @@ private static TextSpan GetFullSpan(object x) return attribute.GetAttributeApplicationSyntax() ?.FullSpan ?? InvalidTextSpan; + case AttributeDataViewModel attributeModel: + return GetFullSpan(attributeModel.NamedArguments); + + case AttributeDataViewModel.LinkedAttributeArgument attributeArgument: + return GetFullSpan(attributeArgument.ArgumentSyntax); + // Operation case IOperation operation: return operation.Syntax.FullSpan;