AvaloniaUI / Avalonia

Develop Desktop, Embedded, Mobile and WebAssembly apps with C# and XAML. The most popular .NET UI client technology
https://avaloniaui.net
MIT License
25.55k stars 2.21k forks source link

AvaloniaNameGenerator throws XamlTransformException when visiting a property element for parent element with generic type parameters #14370

Open busitech opened 8 months ago

busitech commented 8 months ago

Describe the bug

The AvaloniaNameGenerator uses the TypeReferenceResolver when parsing markup files.

During parsing, when an element is found having an x:TypeArguments attribute and a property element, when the property element is visited the TypeReferenceResolver throws XamlTransformException: Unable to resolve type from namespace.

At the time of the exception, the declaring type for the property is what the TypeReferenceResolver is trying to resolve.

A property element is not allowed to have an x:TypeArguments attribute, so the TypeReferenceResolver naively tries to resolve the declaring class of the property with no type arguments, even when the declaring type on the property element and the type on the node above which has the x:TypeArguments are exactly the same name. This leads to the type not being found and the exception thrown.

To Reproduce

This markup easily reproduces the issue:

       <sandbox:RecordList x:TypeArguments="sandbox:Customer" x:Name="grid">
         <sandbox:RecordList.Columns>
           <sandbox:DataGridTextColumn Header="Name" />  
         </sandbox:RecordList.Columns>
       </sandbox:RecordList>

Expected behavior

The exception should not be thrown, because the x:TypeArguments from the parent node (the declaring type having the property) should be used when resolving the declaring type.

Environment

Additional context

Avalonia.Generators.dll!XamlX.Transform.Transformers.TypeReferenceResolver.ResolveTypeCore(XamlX.Transform.AstTransformationContext context, string xmlns, string name, bool isMarkupExtension, System.Collections.Generic.List<XamlX.Ast.XamlAstXmlTypeReference> typeArguments, XamlX.Ast.IXamlLineInfo lineInfo) Line 107    C#
Avalonia.Generators.dll!XamlX.Transform.Transformers.TypeReferenceResolver.ResolveType(XamlX.Transform.AstTransformationContext context, string xmlns, string name, bool isMarkupExtension, System.Collections.Generic.List<XamlX.Ast.XamlAstXmlTypeReference> typeArguments, XamlX.Ast.IXamlLineInfo lineInfo) Line 34 C#
Avalonia.Generators.dll!XamlX.Transform.Transformers.TypeReferenceResolver.ResolveType(XamlX.Transform.AstTransformationContext context, XamlX.Ast.XamlAstXmlTypeReference xmlref) Line 140 C#
Avalonia.Generators.dll!XamlX.Transform.Transformers.TypeReferenceResolver.Transform(XamlX.Transform.AstTransformationContext context, XamlX.Ast.IXamlAstNode node) Line 128    C#
 Avalonia.Generators.dll!XamlX.Transform.AstTransformationContext.Visitor.VisitCore(XamlX.Transform.AstTransformationContext context, XamlX.Ast.IXamlAstNode node) Line 117 C#
Avalonia.Generators.dll!XamlX.Transform.AstTransformationContext.ContextXamlAstVisitor.Visit(XamlX.Ast.IXamlAstNode node) Line 64   C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.Visit(XamlX.Ast.IXamlAstVisitor visitor) Line 101 C#  Avalonia.Generators.dll!XamlX.Ast.XamlAstNamePropertyReference.VisitChildren(XamlX.Ast.IXamlAstVisitor visitor) Line 151    C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.Visit(XamlX.Ast.IXamlAstVisitor visitor) Line 111 C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstXamlPropertyValueNode.VisitChildren(XamlX.Ast.IXamlAstVisitor visitor) Line 59 C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.Visit(XamlX.Ast.IXamlAstVisitor visitor) Line 111 C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.VisitList<XamlX.Ast.IXamlAstNode>(System.Collections.Generic.IList<XamlX.Ast.IXamlAstNode> list, XamlX.Ast.IXamlAstVisitor visitor) Line 125  C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstObjectNode.VisitChildren(XamlX.Ast.IXamlAstVisitor visitor) Line 88    C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.Visit(XamlX.Ast.IXamlAstVisitor visitor) Line 111 C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.VisitList<XamlX.Ast.IXamlAstNode>(System.Collections.Generic.IList<XamlX.Ast.IXamlAstNode> list, XamlX.Ast.IXamlAstVisitor visitor) Line 125  C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstObjectNode.VisitChildren(XamlX.Ast.IXamlAstVisitor visitor) Line 88    C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.Visit(XamlX.Ast.IXamlAstVisitor visitor) Line 111 C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.VisitList<XamlX.Ast.IXamlAstNode>(System.Collections.Generic.IList<XamlX.Ast.IXamlAstNode> list, XamlX.Ast.IXamlAstVisitor visitor) Line 125  C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstObjectNode.VisitChildren(XamlX.Ast.IXamlAstVisitor visitor) Line 88    C#
Avalonia.Generators.dll!XamlX.Ast.XamlAstNode.Visit(XamlX.Ast.IXamlAstVisitor visitor) Line 111 C#
Avalonia.Generators.dll!XamlX.Transform.AstTransformationContext.Visit(XamlX.Ast.IXamlAstNode root, XamlX.Transform.IXamlAstTransformer transformer) Line 122   C#
Avalonia.Generators.dll!XamlX.Compiler.XamlCompiler<object, XamlX.Emit.IXamlEmitResult>.Transform(XamlX.Ast.XamlDocument doc) Line 73   C#
Avalonia.Generators.dll!Avalonia.Generators.Common.XamlXViewResolver.ResolveView(string xaml) Line 47   C#
Avalonia.Generators.dll!Avalonia.Generators.NameGenerator.AvaloniaNameGenerator.GenerateNameReferences.AnonymousMethod__4(<>f__AnonymousType1<<>f__AnonymousType0<Microsoft.CodeAnalysis.AdditionalText, string>, string> <>h__TransparentIdentifier1) Line 46  C#
System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<<>f__AnonymousType1<<>f__AnonymousType0<Microsoft.CodeAnalysis.AdditionalText, string>, string>, <>f__AnonymousType2<<>f__AnonymousType1<<>f__AnonymousType0<Microsoft.CodeAnalysis.AdditionalText, string>, string>, Avalonia.Generators.Common.Domain.ResolvedView>>.MoveNext()  Unknown
System.Core.dll!System.Linq.Enumerable.WhereSelectEnumerableIterator<<>f__AnonymousType2<<>f__AnonymousType1<<>f__AnonymousType0<Microsoft.CodeAnalysis.AdditionalText, string>, string>, Avalonia.Generators.Common.Domain.ResolvedView>, Avalonia.Generators.NameGenerator.GeneratedPartialClass>.MoveNext()  Unknown
Avalonia.Generators.dll!Avalonia.Generators.NameGenerator.AvaloniaNameSourceGenerator.Execute(Microsoft.CodeAnalysis.GeneratorExecutionContext context) Line 31 C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.SourceGeneratorAdaptor.Initialize.AnonymousMethod__5_5(Microsoft.CodeAnalysis.SourceProductionContext productionContext, Microsoft.CodeAnalysis.SourceGeneratorAdaptor.GeneratorContextBuilder contextBuilder) Line 58    C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.UserFunctionExtensions.WrapUserAction.AnonymousMethod__0(Microsoft.CodeAnalysis.SourceProductionContext input1, System.__Canon input2, System.Threading.CancellationToken token) Line 101 C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.SourceOutputNode<Microsoft.CodeAnalysis.SourceGeneratorAdaptor.GeneratorContextBuilder>.UpdateStateTable(Microsoft.CodeAnalysis.DriverStateTable.Builder graphState, Microsoft.CodeAnalysis.NodeStateTable<(System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.GeneratedSourceText>, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Diagnostic>)> previousTable, System.Threading.CancellationToken cancellationToken) Line 70  C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.DriverStateTable.Builder.GetLatestStateTableForNode<(System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.GeneratedSourceText>, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Diagnostic>)>(Microsoft.CodeAnalysis.IIncrementalGeneratorNode<(System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.GeneratedSourceText>, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.Diagnostic>)> source) Line 60    C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.SourceOutputNode<System.__Canon>.AppendOutputs(Microsoft.CodeAnalysis.IncrementalExecutionContext context, System.Threading.CancellationToken cancellationToken) Line 100 C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.GeneratorDriver.UpdateOutputs(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.IIncrementalGeneratorOutputNode> outputNodes, Microsoft.CodeAnalysis.IncrementalGeneratorOutputKind outputKind, Microsoft.CodeAnalysis.GeneratorRunStateTable.Builder generatorRunStateBuilder, System.Threading.CancellationToken cancellationToken, Microsoft.CodeAnalysis.DriverStateTable.Builder driverStateBuilder) Line 318   C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.GeneratorDriver.RunGeneratorsCore(Microsoft.CodeAnalysis.Compilation compilation, Microsoft.CodeAnalysis.DiagnosticBag diagnosticsBag, System.Threading.CancellationToken cancellationToken) Line 299 C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.GeneratorDriver.RunGeneratorsAndUpdateCompilation(Microsoft.CodeAnalysis.Compilation compilation, out Microsoft.CodeAnalysis.Compilation outputCompilation, out System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostic> diagnostics, System.Threading.CancellationToken cancellationToken) Line 57 C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.CommonCompiler.RunGenerators(Microsoft.CodeAnalysis.Compilation input, Microsoft.CodeAnalysis.ParseOptions parseOptions, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ISourceGenerator> generators, Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptionsProvider analyzerConfigOptionsProvider, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.AdditionalText> additionalTexts, Microsoft.CodeAnalysis.DiagnosticBag generatorDiagnostics) Line 822 C#
 Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.CommonCompiler.CompileAndEmit(Microsoft.CodeAnalysis.TouchedFileLogger touchedFilesLogger, ref Microsoft.CodeAnalysis.Compilation compilation, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer> analyzers, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.ISourceGenerator> generators, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.AdditionalText> additionalTextFiles, Microsoft.CodeAnalysis.AnalyzerConfigSet analyzerConfigSet, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.AnalyzerConfigOptionsResult> sourceFileAnalyzerConfigOptions, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.EmbeddedText> embeddedTexts, Microsoft.CodeAnalysis.DiagnosticBag diagnostics, Microsoft.CodeAnalysis.ErrorLogger errorLogger, System.Threading.CancellationToken cancellationToken, out System.Threading.CancellationTokenSource analyzerCts, out Microsoft.CodeAnalysis.Diagnostics.AnalyzerDriver analyzerDriver, out Microsoft.CodeAnalysis.GeneratorDriverTimingInfo? generatorTimingInfo) Line 1098  C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.CommonCompiler.RunCore(System.IO.TextWriter consoleOutput, Microsoft.CodeAnalysis.ErrorLogger errorLogger, System.Threading.CancellationToken cancellationToken) Line 960 C#
Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.CommonCompiler.Run(System.IO.TextWriter consoleOutput, System.Threading.CancellationToken cancellationToken) Line 769 C#
csc.exe!Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.Run.AnonymousMethod__0(System.IO.TextWriter tw) Line 28   C#
csc.exe!Microsoft.CodeAnalysis.CommandLine.ConsoleUtil.RunWithUtf8Output<int>(System.Func<System.IO.TextWriter, int> func) Line 26  C#
csc.exe!Microsoft.CodeAnalysis.CSharp.CommandLine.Csc.Run(string[] args, Microsoft.CodeAnalysis.BuildPaths buildPaths, System.IO.TextWriter textWriter, Microsoft.CodeAnalysis.IAnalyzerAssemblyLoader analyzerLoader) Line 28  C#
csc.exe!Microsoft.CodeAnalysis.CommandLine.BuildClient.RunLocalCompilation(string[] arguments, Microsoft.CodeAnalysis.BuildPaths buildPaths, System.IO.TextWriter textWriter) Line 196  C#
csc.exe!Microsoft.CodeAnalysis.CommandLine.BuildClient.RunCompilation(System.Collections.Generic.IEnumerable<string> originalArguments, Microsoft.CodeAnalysis.BuildPaths buildPaths, System.IO.TextWriter textWriter, string pipeName) Line 162    C#
csc.exe!Microsoft.CodeAnalysis.CommandLine.BuildClient.Run(System.Collections.Generic.IEnumerable<string> arguments, Microsoft.CodeAnalysis.CommandLine.RequestLanguage language, Microsoft.CodeAnalysis.CommandLine.CompileFunc compileFunc, Microsoft.CodeAnalysis.CommandLine.CompileOnServerFunc compileOnServerFunc, Microsoft.CodeAnalysis.CommandLine.ICompilerServerLogger logger) Line 117 C#
csc.exe!Microsoft.CodeAnalysis.CSharp.CommandLine.Program.MainCore(string[] args) Line 37   C#
csc.exe!Microsoft.CodeAnalysis.CSharp.CommandLine.Program.Main(string[] args) Line 18   C#
maxkatz6 commented 8 months ago

Can you test with nightly builds? It shouldn't be reproducible there.

busitech commented 8 months ago

The above test was run from a fresh checkout of the master branch, from within the Avalonia solution, by modifying the Generators.Sandbox project. The commit I used was fea57b920a3c835b4bada7dc409af619517e93e7

Let me know if there is a better branch to use for my test, or if that is equivalent with the nightly build.

timunie commented 8 months ago

fyi: https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed

busitech commented 8 months ago

In case there was any doubt, using a pre-built nightly package produces the same error as when I built from source.

busitech commented 8 months ago

I have added two PRs for debugging and fixing:

https://github.com/AvaloniaUI/Avalonia/pull/14448

https://github.com/kekekeks/XamlX/pull/103