diff --git a/Directory.Build.props b/Directory.Build.props index 84ba0b7c69db..f3f7b152b802 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -2,6 +2,16 @@ + + + + <_MauiXamlSourceGenBackCompat>true + $(DefineConstants);_MAUIXAML_SOURCEGEN_BACKCOMPAT + + true diff --git a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Colors.xaml b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Colors.xaml index 30307a5ddc3b..d57fcc6e3987 100644 --- a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Colors.xaml +++ b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Colors.xaml @@ -1,5 +1,4 @@  - diff --git a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml index 15a426f62f82..6590af989c48 100644 --- a/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml +++ b/src/Controls/samples/Controls.Sample.Embedding/Resources/Styles/Styles.xaml @@ -1,5 +1,4 @@  - diff --git a/src/Controls/src/Build.Tasks/XamlCTask.cs b/src/Controls/src/Build.Tasks/XamlCTask.cs index e5a346c6fa33..30da79f740a8 100644 --- a/src/Controls/src/Build.Tasks/XamlCTask.cs +++ b/src/Controls/src/Build.Tasks/XamlCTask.cs @@ -203,88 +203,50 @@ public override bool Execute(out IList thrownExceptions) using (var assemblyDefinition = AssemblyDefinition.ReadAssembly(IOPath.GetFullPath(Assembly), readerParameters)) { - CustomAttribute xamlProcessingAttr = null; - if (assemblyDefinition.HasCustomAttributes && - (xamlProcessingAttr = - assemblyDefinition.CustomAttributes.FirstOrDefault( - ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute")) != null) - { - var inflator = (XamlInflator)xamlProcessingAttr.ConstructorArguments[0].Value; - var generateInflatorSwitch = xamlProcessingAttr.ConstructorArguments.Count > 1 - && (bool)xamlProcessingAttr.ConstructorArguments[1].Value; - assemblyInflatorOptions = (generateInflatorSwitch, inflator); - if (!generateInflatorSwitch) - skipassembly = (inflator & XamlInflator.XamlC) != XamlInflator.XamlC && inflator != XamlInflator.Default; - - } - -#pragma warning disable CS0618 // Type or member is obsolete +#if _MAUIXAML_SOURCEGEN_BACKCOMPAT CustomAttribute xamlcAttr = null; if (assemblyDefinition.HasCustomAttributes && (xamlcAttr = assemblyDefinition.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlCompilationAttribute")) != null) { - if (xamlProcessingAttr == null) - { - var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; - if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) - skipassembly = true; - if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) - skipassembly = false; - } - else - LoggingHelper.LogWarning($"{new string(' ', 2)}Assembly has both XamlCompilationAttribute and XamlProcessingAttribute. XamlCompilationAttribute will be ignored."); + var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; + if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) + skipassembly = true; + if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) + skipassembly = false; } -#pragma warning restore CS0618 // Type or member is obsolete - xamlcAttr = xamlProcessingAttr = null; + xamlcAttr = null; +#endif foreach (var module in assemblyDefinition.Modules) { var skipmodule = skipassembly; (bool, XamlInflator)? moduleInflatorOptions = assemblyInflatorOptions; - if (module.HasCustomAttributes && - (xamlProcessingAttr = - module.CustomAttributes.FirstOrDefault( - ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute")) != null) - { - var inflator = (XamlInflator)xamlProcessingAttr.ConstructorArguments[0].Value; - var generateInflatorSwitch = xamlProcessingAttr.ConstructorArguments.Count > 1 - && (bool)xamlProcessingAttr.ConstructorArguments[1].Value; - moduleInflatorOptions = (generateInflatorSwitch, inflator); - if (!generateInflatorSwitch) - skipmodule = (inflator & XamlInflator.XamlC) != XamlInflator.XamlC && inflator != XamlInflator.Default; - } - -#pragma warning disable CS0618 // Type or member is obsolete +#if _MAUIXAML_SOURCEGEN_BACKCOMPAT if (module.HasCustomAttributes && (xamlcAttr = module.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlCompilationAttribute")) != null) { - if (xamlProcessingAttr == null) - { - - var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; - if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) - skipmodule = true; - if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) - skipmodule = false; - } - else - LoggingHelper.LogWarning($"{new string(' ', 2)}Module {module.Name} has both XamlCompilationAttribute and XamlProcessingAttribute. XamlCompilationAttribute will be ignored."); + var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; + if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) + skipmodule = true; + if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) + skipmodule = false; } -#pragma warning restore CS0618 // Type or member is obsolete - - xamlcAttr = xamlProcessingAttr = null; + xamlcAttr = null; +#endif LoggingHelper.LogMessage(Low, $"{new string(' ', 2)}Module: {module.Name}"); var resourcesToPrune = new List(); foreach (var resource in module.Resources.OfType()) { - var initCompName = "InitializeComponent"; + var generateInflatorSwitch = module.Assembly.Name.Name == "Microsoft.Maui.Controls.Xaml.UnitTests"; + var initCompName = generateInflatorSwitch ? "InitializeComponentXamlC" : "InitializeComponent"; + LoggingHelper.LogMessage(Low, $"{new string(' ', 4)}Resource: {resource.Name}"); string classname; if (!resource.IsXaml(cache, module, out classname)) @@ -301,53 +263,27 @@ public override bool Execute(out IList thrownExceptions) var skiptype = skipmodule; (bool, XamlInflator)? typeInflatorOptions = moduleInflatorOptions; - if (typeDef.HasCustomAttributes && - (xamlProcessingAttr = - typeDef.CustomAttributes.FirstOrDefault( - ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute")) != null) - { - var inflator = (XamlInflator)xamlProcessingAttr.ConstructorArguments[0].Value; - var generateInflatorSwitch = xamlProcessingAttr.ConstructorArguments.Count > 1 - && (bool)xamlProcessingAttr.ConstructorArguments[1].Value; - - typeInflatorOptions = (generateInflatorSwitch, inflator); - if (generateInflatorSwitch) - { - skiptype = (inflator & XamlInflator.XamlC) != XamlInflator.XamlC && inflator != XamlInflator.Default; - initCompName = "InitializeComponentXamlC"; - } - else - skiptype = inflator != XamlInflator.XamlC; - } -#pragma warning disable CS0618 // Type or member is obsolete +#if _MAUIXAML_SOURCEGEN_BACKCOMPAT if (typeDef.HasCustomAttributes && (xamlcAttr = typeDef.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Microsoft.Maui.Controls.Xaml.XamlCompilationAttribute")) != null) { - if (xamlProcessingAttr == null) - { - // XamlCompilationAttribute is obsolete, but we still need to support it - // for backwards compatibility - var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; - if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) - skiptype = true; - if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) - skiptype = false; - } - else - LoggingHelper.LogWarning($"{new string(' ', 6)}Type {typeDef.Name} has both XamlCompilationAttribute and XamlProcessingAttribute. XamlCompilationAttribute will be ignored."); + var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; + if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) + skiptype = true; + if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) + skiptype = false; } -#pragma warning restore CS0618 // Type or member is obsolete - - xamlcAttr = xamlProcessingAttr = null; + xamlcAttr = null; +#endif if (Type != null) skiptype = !(Type == classname); if (skiptype && !ForceCompile) { - LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}has XamlCompilation or XamlProceesing disabling XamlC... skipped."); + LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}has XamlCompilation disabling XamlC... skipped."); continue; } diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.Common.targets b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.Common.targets index 0c33a0cf414f..cffdc4ad2ca5 100644 --- a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.Common.targets +++ b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.Common.targets @@ -22,6 +22,14 @@ + + + + + + + + + - diff --git a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets index 7f9ead91c76f..493a87b53efd 100644 --- a/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets +++ b/src/Controls/src/Build.Tasks/nuget/buildTransitive/netstandard2.0/Microsoft.Maui.Controls.targets @@ -6,6 +6,11 @@ true True True + + <_MauiXamlInflator Condition="' $(MauiXamlInflator)' != '' ">$(MauiXamlInflator) + <_MauiXamlInflator Condition=" '$(MauiXamlInflator)' == '' And '$(Configuration)' == 'Debug' ">Runtime + <_MauiXamlInflator Condition=" '$(MauiXamlInflator)' == '' And '$(Configuration)' != 'Debug' ">XamlC + true @@ -73,11 +78,34 @@ Condition="'$(_XFTargetsImported)' == 'true'"/> + + + + + + + <_MauiXaml_SG Remove="@(_MauiXaml_SG)" /> + <_MauiXaml_RT Remove="@(_MauiXaml_RT)" /> + <_MauiXaml_XC Remove="@(_MauiXaml_XC)" /> + <_MauiXaml_SG Include="@(MauiXaml)" Condition="$([System.String]::new('%(MauiXaml.Inflator)').Contains('SourceGen', StringComparison.OrdinalIgnoreCase))" /> + <_MauiXaml_RT Include="@(MauiXaml)" Condition="$([System.String]::new('%(MauiXaml.Inflator)').Contains('Runtime', StringComparison.OrdinalIgnoreCase))" /> + <_MauiXaml_XC Include="@(MauiXaml)" Condition="$([System.String]::new('%(MauiXaml.Inflator)').Contains('XamlC', StringComparison.OrdinalIgnoreCase))" /> + <_MauiXaml_AsEmbeddedResource Include="@(_MauiXaml_RT)" /> + <_MauiXaml_AsEmbeddedResource Include="@(_MauiXaml_XC)" KeepDuplicates="false" /> + + + + <_MauiInjectXamlCssAdditionalFilesDependsOn> + _MauiXamlComputeInflator; + $(CreateManifestResourceNamesDependsOn); + + + + DependsOnTargets="$(_MauiInjectXamlCssAdditionalFilesDependsOn)"> <_MauiXamlWithResourceNames Remove="@(_MauiXamlWithResourceNames)" /> <_MauiXamlWithTargetPath Remove="@(_MauiXamlWithTargetPath)" /> @@ -113,6 +141,7 @@ TargetPath="%(_MauiXamlWithResourceNames.TargetPath)" RelativePath="$([MSBuild]::MakeRelative($(MSBuildProjectDirectory), %(_MauiXamlWithResourceNames.TargetPath)))" ItemSpec="%(_MauiXamlWithResourceNames.OriginalItemSpec)" + Inflator="%(_MauiXamlWithResourceNames.Inflator)" GenKind="Xaml"/> - + _MauiAddXamlEmbeddedResources; $(PrepareResourcesDependsOn); + <_MauiAddXamlEmbeddedResourcesDependsOn> + _MauiXamlComputeInflator + - + + diff --git a/src/Controls/src/SourceGen/CodeBehindCodeWriter.cs b/src/Controls/src/SourceGen/CodeBehindCodeWriter.cs index 51a633b4c269..fa901e5f271e 100644 --- a/src/Controls/src/SourceGen/CodeBehindCodeWriter.cs +++ b/src/Controls/src/SourceGen/CodeBehindCodeWriter.cs @@ -69,16 +69,25 @@ public static string GenerateXamlCodeBehind(XamlProjectItemForCB? xamlItem, Comp } var rootSymbol = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootType}"); + bool alreadyHasXamlCompilationAttribute = rootSymbol?.GetAttributes().Any(a => a.AttributeClass != null && a.AttributeClass.Equals(compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Xaml.XamlCompilationAttribute")!, SymbolEqualityComparer.Default)) ?? false; - (var generateInflatorSwitch, var xamlInflators, _) = rootSymbol?.GetXamlProcessing() ?? (false, XamlInflator.Default, false); + var generateInflatorSwitch = compilation.AssemblyName == "Microsoft.Maui.Controls.Xaml.UnitTests"; + var xamlInflators = projItem.Inflator; + + //if there's only the XamlC inflator, prevent non-assigned errors + if (xamlInflators == XamlInflator.XamlC) + sb.AppendLine("#pragma warning disable CS0649"); sb.AppendLine($"namespace {rootClrNamespace}"); sb.AppendLine("{"); sb.AppendLine($"\t[global::Microsoft.Maui.Controls.Xaml.XamlFilePath(\"{projItem.RelativePath?.Replace("\\", "\\\\")}\")]"); - if (addXamlCompilationAttribute) - { + +#if !_MAUIXAML_SOURCEGEN_BACKCOMPAT + if (addXamlCompilationAttribute && !alreadyHasXamlCompilationAttribute) sb.AppendLine($"\t[global::Microsoft.Maui.Controls.Xaml.XamlCompilation(global::Microsoft.Maui.Controls.Xaml.XamlCompilationOptions.Compile)]"); - } +#endif + if (!addXamlCompilationAttribute && (xamlInflators & XamlInflator.XamlC) == 0 && !alreadyHasXamlCompilationAttribute) + sb.AppendLine($"\t[global::Microsoft.Maui.Controls.Xaml.XamlCompilation(global::Microsoft.Maui.Controls.Xaml.XamlCompilationOptions.Skip)]"); if (hideFromIntellisense) { @@ -95,10 +104,7 @@ public static string GenerateXamlCodeBehind(XamlProjectItemForCB? xamlItem, Comp if (generateDefaultCtor) { sb.AppendLine($"\t\t[global::System.CodeDom.Compiler.GeneratedCode(\"Microsoft.Maui.Controls.SourceGen\", \"1.0.0.0\")]"); - sb.AppendLine($"\t\tpublic {rootType}()"); - sb.AppendLine("\t\t{"); - sb.AppendLine(generateInflatorSwitch ? "\t\t\tInitializeComponent(global::Microsoft.Maui.Controls.Xaml.XamlInflator.Default);" : "\t\t\tInitializeComponent();"); - sb.AppendLine("\t\t}"); + sb.AppendLine($"\t\tpublic {rootType}() => InitializeComponent();"); sb.AppendLine(); } @@ -137,33 +143,22 @@ public static string GenerateXamlCodeBehind(XamlProjectItemForCB? xamlItem, Comp // - InitializeComponentXamlC will be used for XamlC // - InitializeComponentSourceGen will be used for SourceGen // - no parameterless InitializeComponent will be generated - if (!generateInflatorSwitch) { - if (xamlInflators == XamlInflator.Default) - { - if (projItem.Configuration != null && projItem.Configuration.Equals("Release", StringComparison.OrdinalIgnoreCase)) - InitComp("InitializeComponent", empty: true); - else - InitComp("InitializeComponent"); - } if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime) InitComp("InitializeComponent"); else if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC) - InitComp("InitializeComponent", empty: true); + InitComp("InitializeComponent"); else if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen) InitComp("InitializeComponent", partialsignature: true); } else { - if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime - || xamlInflators == XamlInflator.Default) + if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime) InitComp("InitializeComponentRuntime"); - if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC - || xamlInflators == XamlInflator.Default) + if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC) InitComp("InitializeComponentXamlC", empty: true); - if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen - || xamlInflators == XamlInflator.Default) + if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen) InitComp("InitializeComponentSourceGen", partialsignature: true); } @@ -175,11 +170,8 @@ void InitComp(string methodName, bool empty = false, bool partialsignature = fal if (namedFields != null && namedFields.Any()) { sb.AppendLine($"#if NET5_0_OR_GREATER"); - foreach ((var fname, _, _) in namedFields) - { - + foreach ((var fname, _, _) in namedFields) sb.AppendLine($"\t\t[global::System.Diagnostics.CodeAnalysis.MemberNotNullAttribute(nameof({EscapeIdentifier(fname)}))]"); - } sb.AppendLine($"#endif"); } @@ -238,36 +230,40 @@ void InitComp(string methodName, bool empty = false, bool partialsignature = fal sb.AppendLine($"#endif"); } - sb.AppendLine($"\t\tprivate void InitializeComponent() => InitializeComponentRuntime();"); - sb.AppendLine(); + + //this isn't supposed to be used, so the default to the first available inflator + if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime) + sb.AppendLine($"\t\tprivate void InitializeComponent() => InitializeComponentRuntime();"); + else if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen) + sb.AppendLine($"\t\tprivate void InitializeComponent() => InitializeComponentSourceGen();"); + else if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC) + sb.AppendLine($"\t\tprivate void InitializeComponent() => InitializeComponentXamlC();"); + sb.AppendLine($"\t\t[global::System.CodeDom.Compiler.GeneratedCode(\"Microsoft.Maui.Controls.SourceGen\", \"1.0.0.0\")]"); - sb.AppendLine($"\t\tpublic {rootType}(global::Microsoft.Maui.Controls.Xaml.XamlInflator inflator)"); + sb.AppendLine($"\t\tinternal {rootType}(global::Microsoft.Maui.Controls.Xaml.XamlInflator inflator)"); sb.AppendLine("\t\t{"); sb.AppendLine("\t\t\tswitch (inflator)"); sb.AppendLine("\t\t\t{"); - if (xamlInflators == XamlInflator.Default || (xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime) + if ((xamlInflators & XamlInflator.Runtime) == XamlInflator.Runtime) { sb.AppendLine("\t\t\t\tcase global::Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime:"); sb.AppendLine("\t\t\t\t\tInitializeComponentRuntime();"); sb.AppendLine("\t\t\t\t\tbreak;"); } - if (xamlInflators == XamlInflator.Default || (xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC) + if ((xamlInflators & XamlInflator.XamlC) == XamlInflator.XamlC) { sb.AppendLine("\t\t\t\tcase global::Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC:"); sb.AppendLine("\t\t\t\t\tInitializeComponentXamlC();"); sb.AppendLine("\t\t\t\t\tbreak;"); } - if (xamlInflators == XamlInflator.Default || (xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen) + if ((xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen) { sb.AppendLine("\t\t\t\tcase global::Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen:"); sb.AppendLine("\t\t\t\t\tInitializeComponentSourceGen();"); sb.AppendLine("\t\t\t\t\tbreak;"); } - sb.AppendLine("\t\t\t\tcase global::Microsoft.Maui.Controls.Xaml.XamlInflator.Default:"); - sb.AppendLine("\t\t\t\t\tInitializeComponent();"); - sb.AppendLine("\t\t\t\t\tbreak;"); sb.AppendLine("\t\t\t\tdefault:"); sb.AppendLine("\t\t\t\t\tthrow new global::System.NotSupportedException($\"no code for {inflator} generated. check the [XamlProcessing] attribute.\");"); sb.AppendLine("\t\t\t}"); @@ -301,12 +297,14 @@ public static bool TryParseXaml(XamlProjectItemForCB parseResult, string uid, Co return false; } +#if _MAUIXAML_SOURCEGEN_BACKCOMPAT // if the following xml processing instruction is present // // // // we will generate a xaml.g.cs file with the default ctor calling InitializeComponent, and a XamlCompilation attribute var hasXamlCompilationProcessingInstruction = GetXamlCompilationProcessingInstruction(root.OwnerDocument); +#endif var rootClass = root.Attributes["Class", XamlParser.X2006Uri] ?? root.Attributes["Class", XamlParser.X2009Uri]; @@ -315,6 +313,7 @@ public static bool TryParseXaml(XamlProjectItemForCB parseResult, string uid, Co { XmlnsHelper.ParseXmlns(rootClass.Value, out rootType, out rootClrNamespace, out _, out _); } +#if _MAUIXAML_SOURCEGEN_BACKCOMPAT else if (hasXamlCompilationProcessingInstruction && root.NamespaceURI == XamlParser.MauiUri) { rootClrNamespace = "__XamlGeneratedCode__"; @@ -323,6 +322,7 @@ public static bool TryParseXaml(XamlProjectItemForCB parseResult, string uid, Co addXamlCompilationAttribute = true; hideFromIntellisense = true; } +#endif else if (parseResult?.ProjectItem?.ManifestResourceName != null && parseResult.ProjectItem.TargetPath != null) { // rootClass == null && !hasXamlCompilationProcessingInstruction) { xamlResourceIdOnly = true; //only generate the XamlResourceId assembly attribute @@ -345,6 +345,7 @@ public static bool TryParseXaml(XamlProjectItemForCB parseResult, string uid, Co return true; } +#if _MAUIXAML_SOURCEGEN_BACKCOMPAT //true, unless explicitely false static bool GetXamlCompilationProcessingInstruction(XmlDocument xmlDoc) { @@ -358,6 +359,7 @@ static bool GetXamlCompilationProcessingInstruction(XmlDocument xmlDoc) return true; } +#endif internal static string GetWarningDisable(XmlDocument xmlDoc) { diff --git a/src/Controls/src/SourceGen/CodeBehindGenerator.cs b/src/Controls/src/SourceGen/CodeBehindGenerator.cs index 3f67c36023b2..8bfc747f4005 100644 --- a/src/Controls/src/SourceGen/CodeBehindGenerator.cs +++ b/src/Controls/src/SourceGen/CodeBehindGenerator.cs @@ -218,26 +218,31 @@ static bool ShouldGenerateSourceGenInitializeComponent(XamlProjectItemForIC xaml var rootClass = root.Attributes["Class", XamlParser.X2006Uri] ?? root.Attributes["Class", XamlParser.X2009Uri]; + INamedTypeSymbol? rootType; - if (rootClass == null) - return false; - - XmlnsHelper.ParseXmlns(rootClass.Value, out var rootTypeName, out var rootClrNamespace, out _, out _); + if (rootClass != null) + { + XmlnsHelper.ParseXmlns(rootClass.Value, out var rootTypeName, out var rootClrNamespace, out _, out _); + rootType = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootTypeName}"); + } + else + { //no x:Class, but it can be an autogenerated type (starting with __Type, and with a XamlResourceId attribute) + ITypeSymbol xamlResIdAttr = compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Xaml.XamlResourceIdAttribute")!; + INamedTypeSymbol? GetTypeForResourcePath(string resourcePath, IAssemblySymbol assembly) + { + var attr = assembly.GetAttributes(xamlResIdAttr).FirstOrDefault(attr => (string)attr.ConstructorArguments[1].Value! == resourcePath); + return attr?.ConstructorArguments[2].Value as INamedTypeSymbol; + } - var rootType = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootTypeName}"); + rootType = GetTypeForResourcePath(xamlItem.ProjectItem.RelativePath!, compilation.Assembly); + } if (rootType == null) return false; - (_, var xamlInflators, var set) = rootType.GetXamlProcessing(); - - //this test must go as soon as 'set' goes away - if (!set) - return false; + var xamlInflators = xamlItem.ProjectItem.Inflator; - if ((xamlInflators & XamlInflator.SourceGen) != XamlInflator.SourceGen - && xamlInflators != XamlInflator.Default - && xamlItem.ProjectItem.ForceSourceGen == false) + if ((xamlInflators & XamlInflator.SourceGen) != XamlInflator.SourceGen) return false; return true; diff --git a/src/Controls/src/SourceGen/GeneratorHelpers.cs b/src/Controls/src/SourceGen/GeneratorHelpers.cs index ebf4360966a0..0be0f5e58b54 100644 --- a/src/Controls/src/SourceGen/GeneratorHelpers.cs +++ b/src/Controls/src/SourceGen/GeneratorHelpers.cs @@ -53,11 +53,33 @@ public static string EscapeIdentifier(string identifier) 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._MauiForceXamlSourcegen", out var forceSourceGen); fileOptions.TryGetValue("build_property.Configuration", out var configuration); - return new ProjectItem(additionalText, targetPath: targetPath, relativePath: relativePath, manifestResourceName: manifestResourceName, kind: kind, targetFramework: targetFramework) + + fileOptions.TryGetValue("build_metadata.additionalfiles.Inflator", out var inflator); + + + var xamlinflator = 0; + if (!string.IsNullOrEmpty(inflator)) + { + var parts = inflator!.Split(','); + for (int i = 0; i < parts.Length; i++) + { + var trimmed = parts[i].Trim(); + if (!Enum.TryParse(trimmed, true, out var xinfl)) + throw new InvalidOperationException($"Invalid inflator '{trimmed}' for {additionalText.Path}."); + xamlinflator |= (int)xinfl; + } + } + + return new ProjectItem { - ForceSourceGen = forceSourceGen == true.ToString(), + AdditionalText = additionalText, + TargetPath = targetPath, + RelativePath = relativePath, + ManifestResourceName = manifestResourceName, + Kind = kind, + Inflator = (XamlInflator)xamlinflator, + TargetFramework = targetFramework, Configuration = configuration!, }; } diff --git a/src/Controls/src/SourceGen/ITypeSymbolExtensions.cs b/src/Controls/src/SourceGen/ITypeSymbolExtensions.cs index 187f1069b96c..e1fa53e20815 100644 --- a/src/Controls/src/SourceGen/ITypeSymbolExtensions.cs +++ b/src/Controls/src/SourceGen/ITypeSymbolExtensions.cs @@ -167,38 +167,6 @@ public static bool ImplementsGeneric(this ITypeSymbol type, ITypeSymbol iface, o return false; } - //FIXME: we won't need the set value in the future, but this allows to not generate for files without the attribute and avoid too many errors - public static (bool generateInflatorSwitch, XamlInflator inflators, bool set) GetXamlProcessing(this ITypeSymbol type) - { - var attr = type.GetAttributes("Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute").FirstOrDefault(ad => ad.ConstructorArguments.Length >= 1); - if (attr != null) - { - var inflator = (XamlInflator)attr.ConstructorArguments[0].Value!; - var generateInflatorSwitch = attr.ConstructorArguments.Length == 2 && (bool)attr.ConstructorArguments[1].Value!; - return (generateInflatorSwitch, inflator, true); - } - - var module = type.ContainingModule; - attr = module.GetAttributes("Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute").FirstOrDefault(ad => ad.ConstructorArguments.Length >= 1); - if (attr != null) - { - var inflator = (XamlInflator)attr.ConstructorArguments[0].Value!; - var generateInflatorSwitch = attr.ConstructorArguments.Length == 2 && (bool)attr.ConstructorArguments[1].Value!; - return (generateInflatorSwitch, inflator, true); - } - - var assembly = type.ContainingAssembly; - attr = assembly.GetAttributes("Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute").FirstOrDefault(ad => ad.ConstructorArguments.Length >= 1); - if (attr != null) - { - var inflator = (XamlInflator)attr.ConstructorArguments[0].Value!; - var generateInflatorSwitch = attr.ConstructorArguments.Length == 2 && (bool)attr.ConstructorArguments[1].Value!; - return (generateInflatorSwitch, inflator, true); - } - - return (false, XamlInflator.Default, false); - } - public static bool IsPublic(this ISymbol symbol) => symbol.DeclaredAccessibility == Accessibility.Public; public static bool IsPublicOrVisibleInternal(this ITypeSymbol type, IEnumerable internalsVisible) diff --git a/src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs b/src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs index 2026ecffb121..ded9035cf1d6 100644 --- a/src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs +++ b/src/Controls/src/SourceGen/InitializeComponentCodeWriter.cs @@ -6,6 +6,7 @@ using System.Runtime.InteropServices; using System.Xml; using Microsoft.CodeAnalysis; +using System.Linq; using Microsoft.Maui.Controls.Xaml; namespace Microsoft.Maui.Controls.SourceGen; @@ -45,9 +46,11 @@ PrePost newblock() => } var root = xamlItem.Root!; + string accessModifier = "public"; + INamedTypeSymbol? rootType = null; + if (root.Properties.TryGetValue(XmlName.xClass, out var classNode)) { - string accessModifier = "public"; if ((classNode as ValueNode)?.Value is not string rootClass) goto exit; @@ -56,58 +59,61 @@ PrePost newblock() => var classModifier = (classModifierNode as ValueNode)?.Value as string; accessModifier = classModifier?.ToLowerInvariant().Replace("notpublic", "internal") ?? "public"; // notpublic is WPF for internal } - //TODO support x:TypeArguments XmlnsHelper.ParseXmlns(rootClass, out var rootTypeName, out var rootClrNamespace, out _, out _); - var rootType = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootTypeName}"); - //roottype null might mean we need to add the type to the Compilation, we'll figure that out later - if (rootType == null) - goto exit; + rootType = compilation.GetTypeByMetadataName($"{rootClrNamespace}.{rootTypeName}"); + } + else + { //no x:Class, but it can be an autogenerated type (starting with __Type, and with a XamlResourceId attribute) + ITypeSymbol xamlResIdAttr = compilation.GetTypeByMetadataName("Microsoft.Maui.Controls.Xaml.XamlResourceIdAttribute")!; + INamedTypeSymbol? GetTypeForResourcePath(string resourcePath, IAssemblySymbol assembly) + { + var attr = assembly.GetAttributes(xamlResIdAttr).FirstOrDefault(attr => (string)attr.ConstructorArguments[1].Value! == resourcePath); + return attr?.ConstructorArguments[2].Value as INamedTypeSymbol; + } - (var genSwitch, var xamlInflators, var set) = rootType.GetXamlProcessing(); + rootType = GetTypeForResourcePath(xamlItem.ProjectItem.RelativePath!, compilation.Assembly); + } - //FIXME later we shouln't gnerate the file at all if generate is false - var generate = (xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen - || xamlItem.ProjectItem.ForceSourceGen - || xamlInflators == XamlInflator.Default && genSwitch; + if (rootType == null) + goto exit; - if (!generate) - goto exit; + var genSwitch = compilation.AssemblyName == "Microsoft.Maui.Controls.Xaml.UnitTests"; + var xamlInflators = xamlItem.ProjectItem.Inflator; - codeWriter.WriteLine($"namespace {rootClrNamespace};"); - codeWriter.WriteLine(); + var generate = (xamlInflators & XamlInflator.SourceGen) == XamlInflator.SourceGen; + + if (!generate) + goto exit; + + codeWriter.WriteLine($"namespace {rootType.ContainingNamespace};"); + codeWriter.WriteLine(); + if (!rootType.Name.StartsWith("__Type")) codeWriter.WriteLine(GeneratedCodeAttribute); - codeWriter.WriteLine($"{accessModifier} partial class {rootTypeName}"); + codeWriter.WriteLine($"{accessModifier} partial class {rootType.Name}"); + using (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 }; using (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 }; - using (newblock()) - { - Visit(root, sgcontext); - - foreach (var localMethod in sgcontext.LocalMethods) - { - codeWriter.WriteLine(localMethod); - codeWriter.WriteLine(); - } - } + Visit(root, sgcontext); - foreach (var writer in sgcontext.AddtitionalWriters) + foreach (var localMethod in sgcontext.LocalMethods) { - codeWriter.Write(writer.ToString()); + codeWriter.WriteLine(localMethod); codeWriter.WriteLine(); } } - } - else - { //No x:Class attribute - //TODO - + foreach (var writer in sgcontext.AddtitionalWriters) + { + codeWriter.Write(writer.ToString()); + codeWriter.WriteLine(); + } } exit: codeWriter.Flush(); diff --git a/src/Controls/src/SourceGen/ProjectItem.cs b/src/Controls/src/SourceGen/ProjectItem.cs index 896ed1185cf6..7a3200c7f063 100644 --- a/src/Controls/src/SourceGen/ProjectItem.cs +++ b/src/Controls/src/SourceGen/ProjectItem.cs @@ -1,27 +1,19 @@ using Microsoft.CodeAnalysis; +using Microsoft.Maui.Controls.Xaml; namespace Microsoft.Maui.Controls.SourceGen; -class ProjectItem +record ProjectItem { - public ProjectItem(AdditionalText additionalText, string? targetPath, string? relativePath, string? manifestResourceName, string kind, string? targetFramework) - { - AdditionalText = additionalText; - TargetPath = targetPath ?? additionalText.Path; - RelativePath = relativePath; - ManifestResourceName = manifestResourceName; - Kind = kind; - TargetFramework = targetFramework; - } - - public AdditionalText AdditionalText { get; } - public string? TargetPath { get; } - public string? RelativePath { get; } - public string? ManifestResourceName { get; } - public string Kind { get; } - public string? TargetFramework { get; } + public required AdditionalText AdditionalText { get; init; } + private string? _targetPath; + public string? TargetPath { get => _targetPath ?? AdditionalText.Path; init => _targetPath = value; } + public string? RelativePath { get; init; } + public string? ManifestResourceName { get; init; } + public required string Kind { get; init; } + public string? TargetFramework { get; init; } + public required XamlInflator Inflator { get; init; } //bypass attribute check. used for testing - public bool ForceSourceGen { get; internal set; } public string Configuration { get; internal set; } = "Debug"; } diff --git a/src/Controls/src/SourceGen/compat.cs b/src/Controls/src/SourceGen/compat.cs new file mode 100644 index 000000000000..49832e9e3e1c --- /dev/null +++ b/src/Controls/src/SourceGen/compat.cs @@ -0,0 +1,47 @@ +// 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. + +//allow usage of required and record in netstandard2.0 + +using System.ComponentModel; + +namespace System.Runtime.CompilerServices +{ +#if !NET5_0_OR_GREATER + + [EditorBrowsable(EditorBrowsableState.Never)] + internal static class IsExternalInit {} + +#endif // !NET5_0_OR_GREATER + +#if !NET7_0_OR_GREATER + + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] + internal sealed class RequiredMemberAttribute : Attribute {} + + [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] + internal sealed class CompilerFeatureRequiredAttribute : Attribute + { + public CompilerFeatureRequiredAttribute(string featureName) + { + FeatureName = featureName; + } + + public string FeatureName { get; } + public bool IsOptional { get; init; } + + public const string RefStructs = nameof(RefStructs); + public const string RequiredMembers = nameof(RequiredMembers); + } + +#endif // !NET7_0_OR_GREATER +} + +namespace System.Diagnostics.CodeAnalysis +{ +#if !NET7_0_OR_GREATER + [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] + internal sealed class SetsRequiredMembersAttribute : Attribute {} +#endif +} \ No newline at end of file diff --git a/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt index c35016ca9941..e393e24d2252 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-android/PublicAPI.Unshipped.txt @@ -8,14 +8,6 @@ *REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void -Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider ~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void ~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void diff --git a/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt index c35016ca9941..e393e24d2252 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-ios/PublicAPI.Unshipped.txt @@ -8,14 +8,6 @@ *REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void -Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider ~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void ~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void diff --git a/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt index c35016ca9941..e393e24d2252 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt @@ -8,14 +8,6 @@ *REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void -Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider ~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void ~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void diff --git a/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt index c35016ca9941..e393e24d2252 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-tizen/PublicAPI.Unshipped.txt @@ -8,14 +8,6 @@ *REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void -Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider ~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void ~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void diff --git a/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt index 1393cf62e369..8c0c1145a575 100644 --- a/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net-windows/PublicAPI.Unshipped.txt @@ -68,14 +68,6 @@ Microsoft.Maui.Controls.Xaml.XamlCompilationOptions Microsoft.Maui.Controls.Xaml.XamlCompilationOptions.Compile = 2 -> Microsoft.Maui.Controls.Xaml.XamlCompilationOptions Microsoft.Maui.Controls.Xaml.XamlCompilationOptions.Skip = 1 -> Microsoft.Maui.Controls.Xaml.XamlCompilationOptions Microsoft.Maui.Controls.Xaml.XamlFilePathAttribute -Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider ~Microsoft.Maui.Controls.Xaml.AppThemeBindingExtension.Dark.get -> object ~Microsoft.Maui.Controls.Xaml.AppThemeBindingExtension.Dark.set -> void diff --git a/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt index c35016ca9941..e393e24d2252 100644 --- a/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/net/PublicAPI.Unshipped.txt @@ -8,14 +8,6 @@ *REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void -Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider ~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void ~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void diff --git a/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt index c35016ca9941..e393e24d2252 100644 --- a/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt +++ b/src/Controls/src/Xaml/PublicAPI/netstandard/PublicAPI.Unshipped.txt @@ -8,14 +8,6 @@ *REMOVED*~Microsoft.Maui.Controls.Xaml.FontImageExtension.ProvideValue(System.IServiceProvider serviceProvider) -> Microsoft.Maui.Controls.ImageSource *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.get -> double *REMOVED*Microsoft.Maui.Controls.Xaml.FontImageExtension.Size.set -> void -Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Default = 0 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.Runtime = 1 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.XamlC = 2 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlInflator.SourceGen = 4 -> Microsoft.Maui.Controls.Xaml.XamlInflator -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlProcessingAttribute(Microsoft.Maui.Controls.Xaml.XamlInflator inflator) -> void -Microsoft.Maui.Controls.Xaml.XamlProcessingAttribute.XamlInflator.get -> Microsoft.Maui.Controls.Xaml.XamlInflator Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider ~Microsoft.Maui.Controls.Xaml.Internals.XamlDataTypeProvider.XamlDataTypeProvider(string dataType) -> void ~Microsoft.Maui.Controls.Xaml.Internals.XamlServiceProvider.XamlServiceProvider(object rootObject) -> void diff --git a/src/Controls/src/Xaml/XamlCompilationAttribute.cs b/src/Controls/src/Xaml/XamlCompilationAttribute.cs index e0e923ebecc8..6bfec7586c52 100644 --- a/src/Controls/src/Xaml/XamlCompilationAttribute.cs +++ b/src/Controls/src/Xaml/XamlCompilationAttribute.cs @@ -4,8 +4,9 @@ namespace Microsoft.Maui.Controls.Xaml { - // TODO: obsolete when we are ready to switch to SourceGen - // [Obsolete("use XamlProcessingOptions instead.")] +#if !_MAUIXAML_SOURCEGEN_BACKCOMPAT + [Obsolete("Specify xaml inflator and other options using msbuild metadata on MauiXaml items in your .csproj: ", error: true)] +#endif [Flags] public enum XamlCompilationOptions { @@ -13,8 +14,9 @@ public enum XamlCompilationOptions Compile = XamlInflator.XamlC, } - // TODO: obsolete when we are ready to switch to SourceGen - // [Obsolete("use XamlProcessingAttribute instead.")] +#if !_MAUIXAML_SOURCEGEN_BACKCOMPAT + [Obsolete("Specify xaml inflator and other options using msbuild metadata on MauiXaml items in your .csproj: ", error: true)] +#endif [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class, Inherited = false)] public sealed class XamlCompilationAttribute : Attribute { @@ -26,11 +28,11 @@ public XamlCompilationAttribute(XamlCompilationOptions xamlCompilationOptions) public XamlCompilationOptions XamlCompilationOptions { get; set; } } +#if _MAUIXAML_SOURCEGEN_BACKCOMPAT static class XamlCExtensions { public static bool IsCompiled(this Type type) { -#pragma warning disable CS0618 // Type or member is obsolete var attr = type.GetCustomAttribute(); if (attr != null) return attr.XamlCompilationOptions == XamlCompilationOptions.Compile; @@ -42,7 +44,7 @@ public static bool IsCompiled(this Type type) return attr.XamlCompilationOptions == XamlCompilationOptions.Compile; return false; -#pragma warning restore CS0618 // Type or member is obsolete } } +#endif } \ No newline at end of file diff --git a/src/Controls/src/Xaml/XamlInflator.cs b/src/Controls/src/Xaml/XamlInflator.cs index b5746ba79124..dc2a4a59c436 100644 --- a/src/Controls/src/Xaml/XamlInflator.cs +++ b/src/Controls/src/Xaml/XamlInflator.cs @@ -1,16 +1,9 @@ -namespace Microsoft.Maui.Controls.Xaml +namespace Microsoft.Maui.Controls.Xaml; + +//used for unit testing switching, and internal use of the sourcegen +enum XamlInflator { - public enum XamlInflator - { - /// - /// Picks the best Inflator available, don't change it unless you know what you're doing. - /// - Default = 0, - Runtime = 1 << 0, - XamlC = 1 << 1, -#if !NETSTANDARD2_0 && !NETSTANDARD2_1 - [System.Runtime.Versioning.RequiresPreviewFeatures] -#endif - SourceGen = 1 << 2, - } + Runtime = 1 << 0, + XamlC = 1 << 1, + SourceGen = 1 << 2, } \ No newline at end of file diff --git a/src/Controls/src/Xaml/XamlProcessingAttribute.cs b/src/Controls/src/Xaml/XamlProcessingAttribute.cs deleted file mode 100644 index a694dc9f816f..000000000000 --- a/src/Controls/src/Xaml/XamlProcessingAttribute.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Runtime.Versioning; - -namespace Microsoft.Maui.Controls.Xaml; - -[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class, Inherited = false)] -//when we remove this attribute, we'll have to obsolete XamlCompilationAttribute -#if !NETSTANDARD -[System.Runtime.Versioning.RequiresPreviewFeatures] -#endif -public sealed class XamlProcessingAttribute : Attribute -{ - public XamlProcessingAttribute(XamlInflator inflator) - { - if ((inflator & (inflator - 1)) != 0) //check if only one bit is set (http://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 - throw new ArgumentException("Only one option can be set at a time"); - XamlInflator = inflator; - } - - internal XamlProcessingAttribute(XamlInflator inflators, bool generateInflatorSwitch) - { - XamlInflator = inflators; //used as a flag to indicate the infators used for unit test purposes - GenerateInflatorSwitch = generateInflatorSwitch; - } - - public XamlInflator XamlInflator { get; } - internal bool GenerateInflatorSwitch { get; } -} \ No newline at end of file diff --git a/src/Controls/tests/SourceGen.UnitTests/SourceGeneratorDriver.cs b/src/Controls/tests/SourceGen.UnitTests/SourceGeneratorDriver.cs index 0d0833fa058d..0f58065a9d3c 100644 --- a/src/Controls/tests/SourceGen.UnitTests/SourceGeneratorDriver.cs +++ b/src/Controls/tests/SourceGen.UnitTests/SourceGeneratorDriver.cs @@ -151,6 +151,7 @@ public override bool TryGetValue(string key, [NotNullWhen(true)] out string? val "build_metadata.additionalfiles.TargetPath" => _additionalFile.TargetPath, "build_metadata.additionalfiles.ManifestResourceName" => _additionalFile.ManifestResourceName, "build_metadata.additionalfiles.RelativePath" => _additionalFile.RelativePath, + "build_metadata.additionalfiles.Inflator" => "SourceGen", "build_property.targetframework" => _additionalFile.TargetFramework, _ => null }; diff --git a/src/Controls/tests/TestCases.HostApp/Elements/CollectionView/HeaderFooterGalleries/HeaderFooterView.xaml b/src/Controls/tests/TestCases.HostApp/Elements/CollectionView/HeaderFooterGalleries/HeaderFooterView.xaml index f1a9f5af30e3..0bda91b2ddd1 100644 --- a/src/Controls/tests/TestCases.HostApp/Elements/CollectionView/HeaderFooterGalleries/HeaderFooterView.xaml +++ b/src/Controls/tests/TestCases.HostApp/Elements/CollectionView/HeaderFooterGalleries/HeaderFooterView.xaml @@ -1,4 +1,4 @@ - + false 0114;0672;0108;0067;0168;0169;0219;0612;0618;1998 Controls.Xaml.UnitTests.ExternalAssembly + + @@ -21,6 +24,7 @@ + diff --git a/src/Controls/tests/Xaml.UnitTests/AcceptEmptyServiceProvider.xaml.cs b/src/Controls/tests/Xaml.UnitTests/AcceptEmptyServiceProvider.xaml.cs index eeeb46884c9a..f3cfea50a960 100644 --- a/src/Controls/tests/Xaml.UnitTests/AcceptEmptyServiceProvider.xaml.cs +++ b/src/Controls/tests/Xaml.UnitTests/AcceptEmptyServiceProvider.xaml.cs @@ -20,7 +20,6 @@ object IMarkupExtension.ProvideValue(IServiceProvider serviceProvider) } } - [XamlProcessing(XamlInflator.Default, true)] public partial class AcceptEmptyServiceProvider : ContentPage { public AcceptEmptyServiceProvider() diff --git a/src/Controls/tests/Xaml.UnitTests/AppResources/Colors.xaml b/src/Controls/tests/Xaml.UnitTests/AppResources/Colors.rtxc.xaml similarity index 100% rename from src/Controls/tests/Xaml.UnitTests/AppResources/Colors.xaml rename to src/Controls/tests/Xaml.UnitTests/AppResources/Colors.rtxc.xaml diff --git a/src/Controls/tests/Xaml.UnitTests/AppResources/CompiledColors.xaml b/src/Controls/tests/Xaml.UnitTests/AppResources/CompiledColors.rtxc.xaml similarity index 100% rename from src/Controls/tests/Xaml.UnitTests/AppResources/CompiledColors.xaml rename to src/Controls/tests/Xaml.UnitTests/AppResources/CompiledColors.rtxc.xaml diff --git a/src/Controls/tests/Xaml.UnitTests/AppResources/RD13209.xaml b/src/Controls/tests/Xaml.UnitTests/AppResources/RD13209.rtxc.xaml similarity index 100% rename from src/Controls/tests/Xaml.UnitTests/AppResources/RD13209.xaml rename to src/Controls/tests/Xaml.UnitTests/AppResources/RD13209.rtxc.xaml diff --git a/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml b/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml index e47fdb970c53..ce9d29db2111 100644 --- a/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml +++ b/src/Controls/tests/Xaml.UnitTests/AutoMergedResourceDictionaries.xaml @@ -7,7 +7,7 @@ Purple Pink - +