Skip to content

Commit

Permalink
fix type
Browse files Browse the repository at this point in the history
  • Loading branch information
Poker-sang committed Dec 24, 2024
1 parent a06e253 commit 57a4c34
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ public void PaneOption_GeneratesEnumProperty()
namespace MyApp
{
[ToolkitSampleEnumOption<Windows.UI.Xaml.Controls.Visibility>("MyVisibility", Title = "Visibility")]
[ToolkitSample(id: nameof(Sample), "Test Sample", description: "")]
public partial class Sample : Windows.UI.Xaml.Controls.UserControl
{
Expand Down Expand Up @@ -123,24 +122,35 @@ public enum Visibility { Visible = 3, Collapsed = 7 }
result.AssertDiagnosticsAre();
result.AssertNoCompilationErrors();

Assert.AreEqual(result.Compilation.GetFileContentsByName("ToolkitSampleRegistry.g.cs"), """
Assert.AreEqual("""
#nullable enable
namespace CommunityToolkit.Tooling.SampleGen;
public static class ToolkitSampleRegistry
{
public static System.Collections.Generic.Dictionary<string, CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMetadata> Listing { get; } = new()
{
["Sample"] = new CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMetadata("Sample", "Test Sample", "", typeof(MyApp.Sample), () => new MyApp.Sample(), null, null, new CommunityToolkit.Tooling.SampleGen.Metadata.IGeneratedToolkitSampleOptionViewModel[] { new CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMultiChoiceOptionMetadataViewModel(name: "MyVisibility", options: new[] { new CommunityToolkit.Tooling.SampleGen.Attributes.MultiChoiceOption("Visible", 3),new CommunityToolkit.Tooling.SampleGen.Attributes.MultiChoiceOption("Collapsed", 7) }, title: "Visibility") })
["Sample"] = new CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMetadata("Sample", "Test Sample", "", typeof(MyApp.Sample), () => new MyApp.Sample(), null, null,
new CommunityToolkit.Tooling.SampleGen.Metadata.IGeneratedToolkitSampleOptionViewModel[]
{
new CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMultiChoiceOptionMetadataViewModel(name: "MyVisibility",
options: new[]
{
new CommunityToolkit.Tooling.SampleGen.Attributes.MultiChoiceOption("Visible", Windows.UI.Xaml.Controls.Visibility.Visible),
new CommunityToolkit.Tooling.SampleGen.Attributes.MultiChoiceOption("Collapsed", Windows.UI.Xaml.Controls.Visibility.Collapsed)
}, title: "Visibility")
})
};
}
""", "Unexpected code generated");
""",
result.Compilation.GetFileContentsByName("ToolkitSampleRegistry.g.cs"),
"Unexpected code generated");
}

[TestMethod]
public void PaneOption_GeneratesTitleProperty()
{
// The sample registry is designed to be declared in the sample project, and generated in the project head where its displayed in the UI as data.
// The sample registry is designed to be declared in the sample project, and generated in the project head where it's displayed in the UI as data.
// To test the contents of the generated sample registry, we must replicate this setup.
var sampleProjectAssembly = """
using System.ComponentModel;
Expand All @@ -153,9 +163,7 @@ namespace MyApp
[ToolkitSample(id: nameof(Sample), "Test Sample", description: "")]
public partial class Sample : Windows.UI.Xaml.Controls.UserControl
{
public Sample()
{
}
public Sample() { }
}
}
Expand All @@ -179,18 +187,24 @@ public class UserControl { }
result.AssertDiagnosticsAre();
result.AssertNoCompilationErrors();

Assert.AreEqual(result.Compilation.GetFileContentsByName("ToolkitSampleRegistry.g.cs"), """
#nullable enable
namespace CommunityToolkit.Tooling.SampleGen;
public static class ToolkitSampleRegistry
{
public static System.Collections.Generic.Dictionary<string, CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMetadata> Listing { get; } = new()
Assert.AreEqual("""
#nullable enable
namespace CommunityToolkit.Tooling.SampleGen;
public static class ToolkitSampleRegistry
{
["Sample"] = new CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMetadata("Sample", "Test Sample", "", typeof(MyApp.Sample), () => new MyApp.Sample(), null, null, new CommunityToolkit.Tooling.SampleGen.Metadata.IGeneratedToolkitSampleOptionViewModel[] { new CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleNumericOptionMetadataViewModel(name: "TextSize", initial: 12, min: 8, max: 48, step: 2, showAsNumberBox: false, title: "FontSize") })
};
}
""", "Unexpected code generated");
public static System.Collections.Generic.Dictionary<string, CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMetadata> Listing { get; } = new()
{
["Sample"] = new CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleMetadata("Sample", "Test Sample", "", typeof(MyApp.Sample), () => new MyApp.Sample(), null, null,
new CommunityToolkit.Tooling.SampleGen.Metadata.IGeneratedToolkitSampleOptionViewModel[]
{
new CommunityToolkit.Tooling.SampleGen.Metadata.ToolkitSampleNumericOptionMetadataViewModel(name: "TextSize", initial: 12, min: 8, max: 48, step: 2, showAsNumberBox: false, title: "FontSize")
})
};
}
""",
result.Compilation.GetFileContentsByName("ToolkitSampleRegistry.g.cs"),
"Unexpected code generated");
}

[TestMethod]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,13 @@ public ToolkitSampleMultiChoiceOptionAttribute(string bindingName, params string
/// Creates a new instance of <see cref="ToolkitSampleMultiChoiceOptionAttribute"/>.
/// </summary>
/// <param name="bindingName">The name of the generated property, which you can bind to in XAML.</param>
/// <param name="typeName"></param>
/// <param name="choices">A list of the choices to display to the user. Can be literal values, or labeled values. Use a " : " separator (single colon surrounded by at least 1 whitespace) to separate a label from a value.</param>
public ToolkitSampleMultiChoiceOptionAttribute(string bindingName, List<(string, object)> choices)
internal ToolkitSampleMultiChoiceOptionAttribute(string bindingName, string typeName, MultiChoiceOption[] choices)
: base(bindingName, null)
{
TypeName = "int";
Choices = choices.Select(x => new MultiChoiceOption(x.Item1, x.Item2)).ToArray();
TypeName = typeName;
Choices = choices;
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,12 @@ void Execute(IncrementalValuesProvider<ISymbol> types, bool skipDiagnostics = fa
if (x.AttributeData.AttributeClass.TypeArguments.FirstOrDefault() is { } typeSymbol)
{
var parameters = x.AttributeData.ConstructorArguments.Select(GeneratorExtensions.PrepareParameterTypeForActivator).ToList();
var members = typeSymbol.GetMembers().OfType<IFieldSymbol>().Select(t => (t.Name, t.ConstantValue!)).ToList();
var members = typeSymbol.GetMembers().OfType<IFieldSymbol>().Select(t => new MultiChoiceOption(t.Name, t.ToDisplayString())).ToArray();
parameters.Add(typeSymbol.ToDisplayString());
parameters.Add(members);
var multiChoiceOptionAttribute = (ToolkitSampleMultiChoiceOptionAttribute)Activator.CreateInstance(typeof(ToolkitSampleMultiChoiceOptionAttribute), parameters.ToArray());
var multiChoiceOptionAttribute = (ToolkitSampleMultiChoiceOptionAttribute)Activator.CreateInstance(
typeof(ToolkitSampleMultiChoiceOptionAttribute), BindingFlags.NonPublic | BindingFlags.Instance,
null, parameters.ToArray(), null);
item = (x.Symbol, multiChoiceOptionAttribute);
}
}
Expand Down Expand Up @@ -298,7 +301,7 @@ private static void ReportGeneratedMultiChoiceOptionsPaneDiagnostics(SourceProdu
{
foreach (var item in generatedOptionPropertyData)
{
if (item.Item2 is ToolkitSampleMultiChoiceOptionAttribute multiChoiceAttr && multiChoiceAttr.Choices.Length == 0)
if (item.Item2 is ToolkitSampleMultiChoiceOptionAttribute { Choices.Length: 0 })
{
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.SamplePaneMultiChoiceOptionWithNoChoices, item.Item1.Locations.FirstOrDefault(), item.Item2.Title));
}
Expand All @@ -315,7 +318,7 @@ public static class ToolkitSampleRegistry
{
public static System.Collections.Generic.Dictionary<string, {{typeof(ToolkitSampleMetadata).FullName}}> Listing { get; } = new()
{
{{string.Join(",\n ", sampleMetadata.Select(MetadataToRegistryCall).ToArray())}}
{{string.Join(",\n", sampleMetadata.Select(MetadataToRegistryCall).ToArray())}}
};
}
""";
Expand All @@ -326,11 +329,16 @@ private static string MetadataToRegistryCall(KeyValuePair<string, ToolkitSampleR
var metadata = kvp.Value;
var sampleControlTypeParam = $"typeof({metadata.SampleAssemblyQualifiedName})";
var sampleControlFactoryParam = $"() => new {metadata.SampleAssemblyQualifiedName}()";
var generatedSampleOptionsParam = $"new {typeof(IGeneratedToolkitSampleOptionViewModel).FullName}[] {{ {string.Join(", ", BuildNewGeneratedSampleOptionMetadataSource(metadata).ToArray())} }}";
var sampleOptionsParam = metadata.SampleOptionsAssemblyQualifiedName is null ? "null" : $"typeof({metadata.SampleOptionsAssemblyQualifiedName})";
var sampleOptionsPaneFactoryParam = metadata.SampleOptionsAssemblyQualifiedName is null ? "null" : $"x => new {metadata.SampleOptionsAssemblyQualifiedName}(({metadata.SampleAssemblyQualifiedName})x)";

return @$"[""{kvp.Key}""] = new {typeof(ToolkitSampleMetadata).FullName}(""{metadata.Id}"", ""{metadata.DisplayName}"", ""{metadata.Description}"", {sampleControlTypeParam}, {sampleControlFactoryParam}, {sampleOptionsParam}, {sampleOptionsPaneFactoryParam}, {generatedSampleOptionsParam})";
return $$"""
["{{kvp.Key}}"] = new {{typeof(ToolkitSampleMetadata).FullName}}("{{metadata.Id}}", "{{metadata.DisplayName}}", "{{metadata.Description}}", {{sampleControlTypeParam}}, {{sampleControlFactoryParam}}, {{sampleOptionsParam}}, {{sampleOptionsPaneFactoryParam}},
new {{typeof(IGeneratedToolkitSampleOptionViewModel).FullName}}[]
{
{{string.Join(",\n", BuildNewGeneratedSampleOptionMetadataSource(metadata).ToArray())}}
})
""";
}

private static IEnumerable<string> BuildNewGeneratedSampleOptionMetadataSource(ToolkitSampleRecord sample)
Expand All @@ -340,13 +348,22 @@ private static IEnumerable<string> BuildNewGeneratedSampleOptionMetadataSource(T
yield return item switch
{
ToolkitSampleMultiChoiceOptionAttribute multiChoiceAttr =>
$@"new {typeof(ToolkitSampleMultiChoiceOptionMetadataViewModel).FullName}(name: ""{multiChoiceAttr.Name}"", options: new[] {{ {string.Join(",", multiChoiceAttr.Choices.Select(x => $@"new {typeof(MultiChoiceOption).FullName}(""{x.Label}"", {(x.Value is string ? $"\"{x.Value}\"" : x.Value)})").ToArray())} }}, title: ""{multiChoiceAttr.Title}"")",
$$"""
new {{typeof(ToolkitSampleMultiChoiceOptionMetadataViewModel).FullName}}(name: "{{multiChoiceAttr.Name}}",
options: new[]
{
{{string.Join(",\n", multiChoiceAttr.Choices.Select(x =>
$"""
new {typeof(MultiChoiceOption).FullName}("{x.Label}", {(multiChoiceAttr.TypeName is "string" ? $"\"{x.Value}\"" : x.Value)})
""").ToArray())}}
}, title: "{{multiChoiceAttr.Title}}")
""",
ToolkitSampleBoolOptionAttribute boolAttribute =>
$@"new {typeof(ToolkitSampleBoolOptionMetadataViewModel).FullName}(name: ""{boolAttribute.Name}"", defaultState: {boolAttribute.DefaultState?.ToString().ToLower()}, title: ""{boolAttribute.Title}"")",
$@" new {typeof(ToolkitSampleBoolOptionMetadataViewModel).FullName}(name: ""{boolAttribute.Name}"", defaultState: {boolAttribute.DefaultState?.ToString().ToLower()}, title: ""{boolAttribute.Title}"")",
ToolkitSampleNumericOptionAttribute numericAttribute =>
$@"new {typeof(ToolkitSampleNumericOptionMetadataViewModel).FullName}(name: ""{numericAttribute.Name}"", initial: {numericAttribute.Initial}, min: {numericAttribute.Min}, max: {numericAttribute.Max}, step: {numericAttribute.Step}, showAsNumberBox: {numericAttribute.ShowAsNumberBox.ToString().ToLower()}, title: ""{numericAttribute.Title}"")",
$@" new {typeof(ToolkitSampleNumericOptionMetadataViewModel).FullName}(name: ""{numericAttribute.Name}"", initial: {numericAttribute.Initial}, min: {numericAttribute.Min}, max: {numericAttribute.Max}, step: {numericAttribute.Step}, showAsNumberBox: {numericAttribute.ShowAsNumberBox.ToString().ToLower()}, title: ""{numericAttribute.Title}"")",
ToolkitSampleTextOptionAttribute textAttribute =>
$@"new {typeof(ToolkitSampleTextOptionMetadataViewModel).FullName}(name: ""{textAttribute.Name}"", placeholderText: ""{textAttribute.PlaceholderText}"", title: ""{textAttribute.Title}"")",
$@" new {typeof(ToolkitSampleTextOptionMetadataViewModel).FullName}(name: ""{textAttribute.Name}"", placeholderText: ""{textAttribute.PlaceholderText}"", title: ""{textAttribute.Title}"")",
_ => throw new NotSupportedException($"Unsupported or unhandled type {item.GetType()}.")
};
}
Expand Down
20 changes: 13 additions & 7 deletions CommunityToolkit.Tooling.SampleGen/ToolkitSampleOptionGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,16 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
if (x.AttributeData.AttributeClass?.ContainingNamespace.ToDisplayString() == typeof(ToolkitSampleEnumOptionAttribute<>).Namespace
&& x.AttributeData.AttributeClass?.MetadataName == typeof(ToolkitSampleEnumOptionAttribute<>).Name)
{
var parameters = x.AttributeData.ConstructorArguments.Select(GeneratorExtensions.PrepareParameterTypeForActivator).ToList();
parameters.Add(new List<(string, object)>());
var multiChoiceOptionAttribute = (ToolkitSampleMultiChoiceOptionAttribute)Activator.CreateInstance(typeof(ToolkitSampleMultiChoiceOptionAttribute), parameters.ToArray());
item = (multiChoiceOptionAttribute, x.Symbol, typeof(ToolkitSampleMultiChoiceOptionMetadataViewModel));
if (x.AttributeData.AttributeClass.TypeArguments.FirstOrDefault() is { } typeSymbol)
{
var parameters = x.AttributeData.ConstructorArguments.Select(GeneratorExtensions.PrepareParameterTypeForActivator).ToList();
parameters.Add(typeSymbol.ToDisplayString());
parameters.Add(Array.Empty<MultiChoiceOption>());
var multiChoiceOptionAttribute = (ToolkitSampleMultiChoiceOptionAttribute)Activator.CreateInstance(
typeof(ToolkitSampleMultiChoiceOptionAttribute), BindingFlags.NonPublic | BindingFlags.Instance,
null, parameters.ToArray(), null);
item = (multiChoiceOptionAttribute, x.Symbol, typeof(ToolkitSampleMultiChoiceOptionMetadataViewModel));
}
}
else if (x.AttributeData.TryReconstructAs<ToolkitSampleBoolOptionAttribute>() is { } boolOptionAttribute)
{
Expand Down Expand Up @@ -186,13 +192,13 @@ public partial class {{containingClassSymbol.Name}}
{
public {{typeName}} {{propertyName}}
{
get => (({{typeName}})(({{viewModelType.FullName}})GeneratedPropertyMetadata!.First(x => x.Name == "{{propertyName}}"))!.Value!)!;
get => ({{typeName}})(({{viewModelType.FullName}})GeneratedPropertyMetadata!.First(x => x.Name is "{{propertyName}}"))!.Value!;
set
{
if (GeneratedPropertyMetadata?.FirstOrDefault(x => x.Name == nameof({{propertyName}})) is {{viewModelType.FullName}} metadata)
if (GeneratedPropertyMetadata?.FirstOrDefault(x => x.Name is "{{propertyName}}") is {{viewModelType.FullName}} metadata)
{
metadata.Value = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof({{propertyName}})));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("{{propertyName}}"));
}
}
}
Expand Down

0 comments on commit 57a4c34

Please sign in to comment.