Skip to content
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
25 changes: 25 additions & 0 deletions src/Controls/src/SourceGen/AnalyzerConfigOptionsExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using System;
using Microsoft.CodeAnalysis.Diagnostics;

namespace Microsoft.Maui.Controls.SourceGen;

public static class AnalyzerConfigOptionsExtensions
{
public static bool IsEnabled(this AnalyzerConfigOptions options, string key)
=> options.TryGetValue(key, out var value) && string.Compare(value, "enable", StringComparison.OrdinalIgnoreCase) == 0;

public static bool IsDisabled(this AnalyzerConfigOptions options, string key)
=> options.TryGetValue(key, out var value) && string.Compare(value, "disable", StringComparison.OrdinalIgnoreCase) == 0;

public static bool IsTrue(this AnalyzerConfigOptions options, string key)
=> options.TryGetValue(key, out var value) && string.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0;

public static bool IsFalse(this AnalyzerConfigOptions options, string key)
=> options.TryGetValue(key, out var value) && string.Compare(value, "false", StringComparison.OrdinalIgnoreCase) == 0;

public static string GetValueOrDefault(this AnalyzerConfigOptions options, string key, string defaultValue)
=> options.TryGetValue(key, out var value) ? value : defaultValue;

public static string? GetValueOrNull(this AnalyzerConfigOptions options, string key)
=> options.TryGetValue(key, out var value) ? value : null;
}
2 changes: 1 addition & 1 deletion src/Controls/src/SourceGen/CompiledBindingMarkup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public CompiledBindingMarkup(IElementNode node, string path, LocalVariable bindi
}

private Location GetLocation(INode node)
=> LocationHelpers.LocationCreate(_context.FilePath!, (IXmlLineInfo)node, "x:DataType");
=> LocationHelpers.LocationCreate(_context.ProjectItem.RelativePath!, (IXmlLineInfo)node, "x:DataType");

public bool TryCompileBinding(ITypeSymbol sourceType, bool isTemplateBinding, out string? newBindingExpression)
{
Expand Down
65 changes: 5 additions & 60 deletions src/Controls/src/SourceGen/GeneratorHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,71 +36,16 @@ public static string EscapeIdentifier(string identifier)
: $"@{identifier}";
}

public static ProjectItem? ComputeProjectItem((AdditionalText, AnalyzerConfigOptionsProvider) tuple, CancellationToken cancellationToken)
public static ProjectItem? ComputeProjectItem((AdditionalText additionalText, AnalyzerConfigOptionsProvider optionsProvider) tuple, CancellationToken cancellationToken)
{
var (additionalText, optionsProvider) = tuple;
var fileOptions = optionsProvider.GetOptions(additionalText);
if (!fileOptions.TryGetValue("build_metadata.additionalfiles.GenKind", out string? kind) || kind is null)
if (cancellationToken.IsCancellationRequested)
return null;

fileOptions.TryGetValue("build_metadata.additionalfiles.TargetPath", out var targetPath);
fileOptions.TryGetValue("build_metadata.additionalfiles.ManifestResourceName", out var manifestResourceName);
fileOptions.TryGetValue("build_metadata.additionalfiles.RelativePath", out var relativePath);
fileOptions.TryGetValue("build_property.targetframework", out var targetFramework);
fileOptions.TryGetValue("build_property.Configuration", out var configuration);

bool enableDiagnostics = false;
if (fileOptions.TryGetValue("build_property.EnableMauiXamlDiagnostics", out var enDiag) && string.Compare(enDiag, "true", StringComparison.OrdinalIgnoreCase) == 0)
enableDiagnostics = true;
if (fileOptions.TryGetValue("build_property.additionalfiles.EnableDiagnostics", out enDiag) && string.Compare(enDiag, "true", StringComparison.OrdinalIgnoreCase) == 0)
enableDiagnostics = true;
if (fileOptions.TryGetValue("build_property.additionalfiles.EnableDiagnostics", out enDiag) && string.Compare(enDiag, "false", StringComparison.OrdinalIgnoreCase) == 0)
enableDiagnostics = false;

var xamlinflator = 0;
if (fileOptions.TryGetValue("build_metadata.additionalfiles.Inflator", out var inflator) && !string.IsNullOrEmpty(inflator))
{
var parts = inflator!.Split(',');
for (int i = 0; i < parts.Length; i++)
{
var trimmed = parts[i].Trim();
if (!Enum.TryParse<XamlInflator>(trimmed, true, out var xinfl))
throw new InvalidOperationException($"Invalid inflator '{trimmed}' for {additionalText.Path}.");
xamlinflator |= (int)xinfl;
}
}

var enableLineInfo = true;
if (fileOptions.TryGetValue("build_property.MauiXamlLineInfo", out var lineInfo) && string.Compare(lineInfo, "disable", StringComparison.OrdinalIgnoreCase) == 0)
enableLineInfo = false;
if (fileOptions.TryGetValue("build_metadata.additionalfiles.LineInfo", out lineInfo) && string.Compare(lineInfo, "enable", StringComparison.OrdinalIgnoreCase) == 0)
enableLineInfo = true;
if (fileOptions.TryGetValue("build_metadata.additionalfiles.LineInfo", out lineInfo) && string.Compare(lineInfo, "disable", StringComparison.OrdinalIgnoreCase) == 0)
enableLineInfo = false;

string noWarn = "";
if (fileOptions.TryGetValue("build_property.MauiXamlNoWarn", out var noWarnValue))
noWarn = noWarnValue;
if (fileOptions.TryGetValue("build_metadata.additionalfiles.NoWarn", out noWarnValue))
noWarn = noWarnValue;

return new ProjectItem
{
AdditionalText = additionalText,
TargetPath = targetPath,
RelativePath = relativePath,
ManifestResourceName = manifestResourceName,
Kind = kind,
Inflator = (XamlInflator)xamlinflator,
EnableLineInfo = enableLineInfo,
EnableDiagnostics = enableDiagnostics,
NoWarn = noWarn,
TargetFramework = targetFramework,
Configuration = configuration!,
};
var projectItem = new ProjectItem(tuple.additionalText, tuple.optionsProvider.GetOptions(tuple.additionalText));
return projectItem.Kind == "None" ? null : projectItem;
}
Comment on lines +39 to 46
Copy link

Copilot AI Sep 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method parameter name tuple doesn't match the usage inside the method. Line 44 uses tuple.optionsProvider but the parameter is destructured as (AdditionalText additionalText, AnalyzerConfigOptionsProvider optionsProvider), so it should be optionsProvider.GetOptions(additionalText).

Copilot uses AI. Check for mistakes.

public static XamlProjectItemForIC? ComputeXamlProjectItemForIC((ProjectItem?, AssemblyCaches) itemAdnCaches, CancellationToken cancellationToken)
public static XamlProjectItemForIC? ComputeXamlProjectItemForIC((ProjectItem?, AssemblyCaches) itemAdnCaches, CancellationToken cancellationToken)
{
var (projectItem, assemblyCaches) = itemAdnCaches;
var text = projectItem?.AdditionalText.GetText(cancellationToken);
Expand Down
12 changes: 3 additions & 9 deletions src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,7 @@ PrePost newblock() =>
var methodName = genSwitch ? "InitializeComponentSourceGen" : "InitializeComponent";
codeWriter.WriteLine($"private partial void {methodName}()");
xamlItem.Root!.XmlType.TryResolveTypeSymbol(null, compilation, xmlnsCache, out var baseType);
var sgcontext = new SourceGenContext(codeWriter, compilation, sourceProductionContext, xmlnsCache, typeCache, rootType!, baseType)
{
FilePath = xamlItem.ProjectItem.RelativePath,
EnableLineInfo = xamlItem.ProjectItem.EnableLineInfo,
EnableDiagnostics = xamlItem.ProjectItem.EnableDiagnostics,
TargetFramework = xamlItem.ProjectItem.TargetFramework ?? "",
};
var sgcontext = new SourceGenContext(codeWriter, compilation, sourceProductionContext, xmlnsCache, typeCache, rootType!, baseType, xamlItem.ProjectItem);
using (newblock())
{
Visit(root, sgcontext);
Expand Down Expand Up @@ -124,8 +118,8 @@ static void Visit(RootNode rootnode, SourceGenContext visitorContext, bool useDe
if (useDesignProperties)
rootnode.Accept(new RemoveDuplicateDesignNodes(), null);
rootnode.Accept(new SimplifyTypeExtensionVisitor(), null);
if (!string.IsNullOrEmpty(visitorContext.TargetFramework))
rootnode.Accept(new SimplifyOnPlatformVisitor(visitorContext.TargetFramework), null);
if (!string.IsNullOrEmpty(visitorContext.ProjectItem.TargetFramework))
rootnode.Accept(new SimplifyOnPlatformVisitor(visitorContext.ProjectItem.TargetFramework), null);
rootnode.Accept(new CreateValuesVisitor(visitorContext), null);
rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null); //set namescopes for {x:Reference} and FindByName
rootnode.Accept(new SetFieldsForXNamesVisitor(visitorContext), null);
Expand Down
4 changes: 2 additions & 2 deletions src/Controls/src/SourceGen/KnownMarkups.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ static bool TryGetXDataType(IElementNode node, SourceGenContext context, out ITy
return false;
}

var location = LocationHelpers.LocationCreate(context.FilePath!, (IXmlLineInfo)node, "x:DataType");
var location = LocationHelpers.LocationCreate(context.ProjectItem.RelativePath!, (IXmlLineInfo)node, "x:DataType");

if (xDataTypeIsInOuterScope)
{
Expand Down Expand Up @@ -502,7 +502,7 @@ internal static bool ProvideValueForStaticResourceExtension(IElementNode node, S

if (keyNode is not ValueNode keyValueNode)
{
context.ReportDiagnostic(Diagnostic.Create(Descriptors.XamlParserError, LocationHelpers.LocationCreate(context.FilePath!, (IXmlLineInfo)node, ""), "StaticResourceExtension: Key must be a string literal"));
context.ReportDiagnostic(Diagnostic.Create(Descriptors.XamlParserError, LocationHelpers.LocationCreate(context.ProjectItem.RelativePath!, (IXmlLineInfo)node, ""), "StaticResourceExtension: Key must be a string literal"));
returnType = context.Compilation.ObjectType;
value = string.Empty;
return false;
Expand Down
Loading
Loading