Skip to content

Commit 2cd42b2

Browse files
authored
Fixed compilation errors caused by sample IDs not being transformed by the project template (#185)
* Added safety and diagnostics for detecting duplicate sample ids * Renamed to prevent name conflicts * Completed rename to prevent name conflicts
1 parent c003a5d commit 2cd42b2

11 files changed

+42
-16
lines changed

common/CommunityToolkit.Labs.Core.SourceGenerators/Diagnostics/DiagnosticDescriptors.cs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public static class DiagnosticDescriptors
1919
/// </summary>
2020
public static readonly DiagnosticDescriptor SamplePaneOptionAttributeOnNonSample = new(
2121
id: "TKSMPL0001",
22-
title: $"Invalid sample option delaration",
22+
title: $"Invalid sample option declaration",
2323
messageFormat: $"Cannot generate sample pane options for type {{0}} as it does not use {nameof(Attributes.ToolkitSampleAttribute)}",
2424
category: typeof(ToolkitSampleMetadataGenerator).FullName,
2525
defaultSeverity: DiagnosticSeverity.Error,
@@ -34,7 +34,7 @@ public static class DiagnosticDescriptors
3434
/// </summary>
3535
public static readonly DiagnosticDescriptor SamplePaneOptionWithBadName = new(
3636
id: "TKSMPL0002",
37-
title: $"Invalid sample option delaration",
37+
title: $"Invalid sample option declaration",
3838
messageFormat: $"Cannot generate sample pane options for type {{0}} as the provided name is empty or invalid",
3939
category: typeof(ToolkitSampleMetadataGenerator).FullName,
4040
defaultSeverity: DiagnosticSeverity.Error,
@@ -205,4 +205,19 @@ public static class DiagnosticDescriptors
205205
defaultSeverity: DiagnosticSeverity.Warning,
206206
isEnabledByDefault: true,
207207
description: $"Document contains no interactive sample code.");
208+
209+
/// <summary>
210+
/// Gets a <see cref="DiagnosticDescriptor"/> indicating a sample ID is already in use by another sample.
211+
/// <para>
212+
/// Format: <c>"Cannot generate sample with id {0} as the provided id is already in use by another sample"</c>.
213+
/// </para>
214+
/// </summary>
215+
public static readonly DiagnosticDescriptor SampleIdAlreadyInUse = new(
216+
id: "TKSMPL0015",
217+
title: $"Sample ID already in use",
218+
messageFormat: $"Cannot generate sample with id {{0}} as the provided id is already in use by another sample",
219+
category: typeof(ToolkitSampleMetadataGenerator).FullName,
220+
defaultSeverity: DiagnosticSeverity.Error,
221+
isEnabledByDefault: true,
222+
description: $"Cannot generate sample as the id is already in use by another sample.");
208223
}

common/CommunityToolkit.Labs.Core.SourceGenerators/ToolkitSampleMetadataGenerator.Sample.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ void Execute(IncrementalValuesProvider<ISymbol> types, bool skipDiagnostics = fa
104104

105105
// Reconstruct sample metadata from attributes
106106
var sampleMetadata = toolkitSampleAttributeData
107+
.GroupBy(x => x.Attribute.Id).Select(x => x.First()) // Filter out non-unique Ids. Diagnostics happen below.
107108
.ToDictionary(
108109
sample => sample.Attribute.Id,
109110
sample =>
@@ -129,6 +130,9 @@ void Execute(IncrementalValuesProvider<ISymbol> types, bool skipDiagnostics = fa
129130
{
130131
CreateDocumentRegistry(ctx, docFrontMatter);
131132
CreateSampleRegistry(ctx, sampleMetadata);
133+
134+
// These diagnostics need to scan all symbols referenced from a sample head.
135+
ReportDiagnosticsForConflictingSampleId(ctx, toolkitSampleAttributeData);
132136
}
133137
});
134138
}
@@ -177,6 +181,16 @@ private static void ReportDiagnosticsForInvalidAttributeUsage(SourceProductionCo
177181

178182
}
179183

184+
private static void ReportDiagnosticsForConflictingSampleId(SourceProductionContext ctx,
185+
IEnumerable<(ToolkitSampleAttribute Attribute, string AttachedQualifiedTypeName, ISymbol Symbol)> toolkitSampleAttributeData)
186+
{
187+
foreach (var sampleIdGroup in toolkitSampleAttributeData.GroupBy(x => x.Attribute.Id))
188+
{
189+
if (sampleIdGroup.Count() > 1)
190+
ctx.ReportDiagnostic(Diagnostic.Create(DiagnosticDescriptors.SampleIdAlreadyInUse, null, sampleIdGroup.Key));
191+
}
192+
}
193+
180194
private static void ReportDiagnosticsForLinkedOptionsPane(SourceProductionContext ctx,
181195
IEnumerable<(ToolkitSampleAttribute Attribute, string AttachedQualifiedTypeName, ISymbol Symbol)> toolkitSampleAttributeData,
182196
IEnumerable<(ToolkitSampleOptionsPaneAttribute?, ISymbol)> optionsPaneAttribute)
@@ -212,7 +226,6 @@ private static void ReportDiagnosticsGeneratedOptionsPane(SourceProductionContex
212226
// Check for generated options with duplicate names.
213227
var generatedOptionsWithDuplicateName = generatedOptionPropertyData.GroupBy(x => x.Item1, SymbolEqualityComparer.Default) // Group by containing symbol (allow reuse across samples)
214228
.SelectMany(y => y.GroupBy(x => x.Item2.Name) // In this symbol, group options by name.
215-
.Where(x => x.Any(x => x.Item2 is not ToolkitSampleMultiChoiceOptionAttribute)) // Exclude Multichoice.
216229
.Where(x => x.Count() > 1)); // Options grouped by name should only contain 1 item.
217230

218231
foreach (var item in generatedOptionsWithDuplicateName)
@@ -245,9 +258,7 @@ public static class ToolkitSampleRegistry
245258
{{
246259
public static System.Collections.Generic.Dictionary<string, {typeof(ToolkitSampleMetadata).FullName}> Listing
247260
{{ get; }} = new() {{
248-
{
249-
string.Join(",\n ", sampleMetadata.Select(MetadataToRegistryCall).ToArray())
250-
}
261+
{string.Join(",\n ", sampleMetadata.Select(MetadataToRegistryCall).ToArray())}
251262
}};
252263
}}";
253264
}

template/lab/samples/ProjectTemplate.Sample/ProjectTemplate.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ TODO: Fill in information about this experiment and how to get started here...
3131
3232
### Custom style
3333

34-
> [!SAMPLE TemplatedControlWithCustomStyleSample]
34+
> [!SAMPLE ProjectTemplateCustomStyleSample]
3535
3636
# Templated Controls with x:Bind
3737
### Implict style
@@ -40,5 +40,5 @@ TODO: Fill in information about this experiment and how to get started here...
4040
4141
### Custom style
4242

43-
> [!SAMPLE BackedTemplatedControlWithCustomStyleSample]
43+
> [!SAMPLE ProjectTemplateCustomStyleBackedSample]
4444

template/lab/samples/ProjectTemplate.Sample/BackedTemplatedControlWithCustomStyleSample.xaml renamed to template/lab/samples/ProjectTemplate.Sample/ProjectTemplateCustomStyleBackedSample.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
2-
<Page x:Class="ProjectTemplate.Sample.BackedTemplatedControlWithCustomStyleSample"
2+
<Page x:Class="ProjectTemplate.Sample.ProjectTemplateCustomStyleBackedSample"
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
55
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ namespace ProjectTemplate.Sample;
1414
"Sand : #e7a676",
1515
"Dull green : #5d7577")]
1616

17-
[ToolkitSample(id: nameof(BackedTemplatedControlWithCustomStyleSample), "Backed templated control (restyled)", description: "A sample for showing how to create and use a templated control with a backed resource dictionary and a custom style.")]
18-
public sealed partial class BackedTemplatedControlWithCustomStyleSample : Page
17+
[ToolkitSample(id: nameof(ProjectTemplateCustomStyleBackedSample), "Backed templated control (restyled)", description: "A sample for showing how to create and use a templated control with a backed resource dictionary and a custom style.")]
18+
public sealed partial class ProjectTemplateCustomStyleBackedSample : Page
1919
{
20-
public BackedTemplatedControlWithCustomStyleSample()
20+
public ProjectTemplateCustomStyleBackedSample()
2121
{
2222
this.InitializeComponent();
2323
}

template/lab/samples/ProjectTemplate.Sample/TemplatedControlWithCustomStyleSample.xaml renamed to template/lab/samples/ProjectTemplate.Sample/ProjectTemplateCustomStyleSample.xaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
2-
<Page x:Class="ProjectTemplate.Sample.TemplatedControlWithCustomStyleSample"
2+
<Page x:Class="ProjectTemplate.Sample.ProjectTemplateCustomStyleSample"
33
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
44
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
55
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

template/lab/samples/ProjectTemplate.Sample/TemplatedControlWithCustomStyleSample.xaml.cs renamed to template/lab/samples/ProjectTemplate.Sample/ProjectTemplateCustomStyleSample.xaml.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ namespace ProjectTemplate.Sample;
1414
"Sand : #e7a676",
1515
"Dull green : #5d7577")]
1616

17-
[ToolkitSample(id: nameof(TemplatedControlWithCustomStyleSample), "Templated control (restyled)", description: "A sample for showing how to create a use and templated control with a custom style.")]
18-
public sealed partial class TemplatedControlWithCustomStyleSample : Page
17+
[ToolkitSample(id: nameof(ProjectTemplateCustomStyleSample), "Templated control (restyled)", description: "A sample for showing how to create a use and templated control with a custom style.")]
18+
public sealed partial class ProjectTemplateCustomStyleSample : Page
1919
{
20-
public TemplatedControlWithCustomStyleSample()
20+
public ProjectTemplateCustomStyleSample()
2121
{
2222
this.InitializeComponent();
2323
}

0 commit comments

Comments
 (0)