Skip to content
This repository has been archived by the owner on Jun 28, 2023. It is now read-only.

fix: Don't break when one form is invalid #95

Merged
merged 1 commit into from
Nov 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 4 additions & 36 deletions src/Avalonia.NameGenerator/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void Execute(GeneratorExecutionContext context)
}
catch (Exception exception)
{
ReportUnhandledError(context, exception);
context.ReportUnhandledError(exception);
}
}

Expand All @@ -44,42 +44,10 @@ private static INameGenerator CreateNameGenerator(GeneratorExecutionContext cont
options.AvaloniaNameGeneratorViewFileNamingStrategy,
new GlobPatternGroup(options.AvaloniaNameGeneratorFilterByPath),
new GlobPatternGroup(options.AvaloniaNameGeneratorFilterByNamespace),
new XamlXViewResolver(types, compiler, true, type => ReportInvalidType(context, type)),
new XamlXViewResolver(types, compiler, true,
type => context.ReportInvalidType(type),
error => context.ReportUnhandledError(error)),
new XamlXNameResolver(options.AvaloniaNameGeneratorDefaultFieldModifier),
generator);
}

private static void ReportUnhandledError(GeneratorExecutionContext context, Exception error)
{
const string message =
"Unhandled exception occured while generating typed Name references. " +
"Please file an issue: https://github.com/avaloniaui/avalonia.namegenerator";
context.ReportDiagnostic(
Diagnostic.Create(
new DiagnosticDescriptor(
"AXN0002",
message,
error.ToString(),
"Usage",
DiagnosticSeverity.Error,
true),
Location.None));
}

private static void ReportInvalidType(GeneratorExecutionContext context, string typeName)
{
var message =
$"Avalonia x:Name generator was unable to generate names for type '{typeName}'. " +
$"The type '{typeName}' does not exist in the assembly.";
context.ReportDiagnostic(
Diagnostic.Create(
new DiagnosticDescriptor(
"AXN0001",
message,
message,
"Usage",
DiagnosticSeverity.Error,
true),
Location.None));
}
}
29 changes: 20 additions & 9 deletions src/Avalonia.NameGenerator/Generator/XamlXViewResolver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal class XamlXViewResolver : IViewResolver, IXamlAstVisitor
private readonly MiniCompiler _compiler;
private readonly bool _checkTypeValidity;
private readonly Action<string> _onTypeInvalid;
private readonly Action<Exception> _onUnhandledError;

private ResolvedView _resolvedClass;
private XamlDocument _xaml;
Expand All @@ -23,26 +24,36 @@ public XamlXViewResolver(
RoslynTypeSystem typeSystem,
MiniCompiler compiler,
bool checkTypeValidity = false,
Action<string> onTypeInvalid = null)
Action<string> onTypeInvalid = null,
Action<Exception> onUnhandledError = null)
{
_checkTypeValidity = checkTypeValidity;
_onTypeInvalid = onTypeInvalid;
_onUnhandledError = onUnhandledError;
_typeSystem = typeSystem;
_compiler = compiler;
}

public ResolvedView ResolveView(string xaml)
{
_resolvedClass = null;
_xaml = XDocumentXamlParser.Parse(xaml, new Dictionary<string, string>
try
{
{XamlNamespaces.Blend2008, XamlNamespaces.Blend2008}
});
_resolvedClass = null;
_xaml = XDocumentXamlParser.Parse(xaml, new Dictionary<string, string>
{
{XamlNamespaces.Blend2008, XamlNamespaces.Blend2008}
});

_compiler.Transform(_xaml);
_xaml.Root.Visit(this);
_xaml.Root.VisitChildren(this);
return _resolvedClass;
_compiler.Transform(_xaml);
_xaml.Root.Visit(this);
_xaml.Root.VisitChildren(this);
return _resolvedClass;
}
catch (Exception exception)
{
_onUnhandledError?.Invoke(exception);
return null;
}
}

IXamlAstNode IXamlAstVisitor.Visit(IXamlAstNode node)
Expand Down
32 changes: 19 additions & 13 deletions src/Avalonia.NameGenerator/GeneratorContextExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System.Linq;
using System;
using Microsoft.CodeAnalysis;

namespace Avalonia.NameGenerator;

internal static class GeneratorContextExtensions
{
private const string SourceItemGroupMetadata = "build_metadata.AdditionalFiles.SourceItemGroup";
private const string UnhandledErrorDescriptorId = "AXN0002";
private const string InvalidTypeDescriptorId = "AXN0001";

public static string GetMsBuildProperty(
this GeneratorExecutionContext context,
Expand All @@ -16,15 +17,20 @@ public static string GetMsBuildProperty(
return value ?? defaultValue;
}

public static string[] GetMsBuildItems(this GeneratorExecutionContext context, string name)
=> context
.AdditionalFiles
.Where(f =>
context
.AnalyzerConfigOptions
.GetOptions(f)
.TryGetValue(SourceItemGroupMetadata, out var sourceItemGroup)
&& sourceItemGroup == name)
.Select(f => f.Path)
.ToArray();
public static void ReportUnhandledError(this GeneratorExecutionContext context, Exception error) =>
context.Report(UnhandledErrorDescriptorId,
"Unhandled exception occured while generating typed Name references. " +
"Please file an issue: https://github.com/avaloniaui/avalonia.namegenerator",
error.ToString());

public static void ReportInvalidType(this GeneratorExecutionContext context, string typeName) =>
context.Report(InvalidTypeDescriptorId,
$"Avalonia x:Name generator was unable to generate names for type '{typeName}'. " +
$"The type '{typeName}' does not exist in the assembly.");

private static void Report(this GeneratorExecutionContext context, string id, string title, string message = null) =>
context.ReportDiagnostic(
Diagnostic.Create(
new DiagnosticDescriptor(id, title, message ?? title, "Usage", DiagnosticSeverity.Error, true),
Location.None));
}