diff --git a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj
index 5a77c43cfbf..50e69ddd6a5 100644
--- a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj
+++ b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Microsoft.Macios.Bindings.Analyzer.csproj
@@ -63,8 +63,8 @@
Generator/Extensions/CompilationExtensions.cs
-
- Generator/Extensions/TypeSymbolExtensions.cs
+
+ Generator/Extensions/TypeSymbolExtensions.Core.cs
Generator/Extensions/TypedConstantExtensions.cs
diff --git a/src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.cs b/src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.Core.cs
similarity index 59%
rename from src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.cs
rename to src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.Core.cs
index 7a2766ff02e..57eaf428816 100644
--- a/src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.cs
+++ b/src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.Core.cs
@@ -1,19 +1,16 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis;
-using Microsoft.Macios.Generator.Attributes;
-using Microsoft.Macios.Generator.Availability;
namespace Microsoft.Macios.Generator.Extensions;
-static class TypeSymbolExtensions {
+static partial class TypeSymbolExtensions {
///
/// Retrieve a dictionary with the attribute data of all the attributes attached to a symbol. Because
/// an attribute can appear more than once, the valus are a collection of attribute data.
@@ -71,74 +68,6 @@ public static ImmutableArray GetParents (this ISymbol symbol)
return [.. result];
}
- ///
- /// Return the symbol availability WITHOUT taking into account the parent symbols availability.
- ///
- /// The symbols whose availability attributes we want to retrieve.
- /// The symbol availability WITHOUT taking into account the parent symbols.
- /// This is a helper method, you probably don't want to use it.
- static SymbolAvailability GetAvailabilityForSymbol (this ISymbol symbol)
- {
- //get the attribute of the symbol and look for the Supported and Unsupported attributes and
- // add the different platforms to the result hashsets
- var builder = SymbolAvailability.CreateBuilder ();
- var boundAttributes = symbol.GetAttributes ();
- if (boundAttributes.Length == 0) {
- // no attrs in the symbol, therefore the symbol is supported in all platforms
- return builder.ToImmutable ();
- }
-
- foreach (var attributeData in boundAttributes) {
- var attrName = attributeData.AttributeClass?.ToDisplayString ();
- if (string.IsNullOrEmpty (attrName))
- continue;
- // we only care in this case about the support and unsupported attrs, ignore any other
- switch (attrName) {
- case AttributesNames.SupportedOSPlatformAttribute:
- if (SupportedOSPlatformData.TryParse (attributeData, out var supportedPlatform)) {
- builder.Add (supportedPlatform.Value);
- }
-
- break;
- case AttributesNames.UnsupportedOSPlatformAttribute:
- if (UnsupportedOSPlatformData.TryParse (attributeData, out var unsupportedPlatform)) {
- builder.Add (unsupportedPlatform.Value);
- }
-
- break;
- case AttributesNames.ObsoletedOSPlatformAttribute:
- if (ObsoletedOSPlatformData.TryParse (attributeData, out var obsoletedOsPlatform)) {
- builder.Add (obsoletedOsPlatform.Value);
- }
-
- break;
- default:
- continue;
- }
- }
-
- return builder.ToImmutable ();
- }
-
- ///
- /// Returns the symbol availability taking into account the parent symbols availability.
- ///
- /// That means that the attributes used on the current symbol are merged with the attributes used
- /// in all the symbol parents following the correct child-parent order.
- ///
- /// The symbol whose availability we want to retrieve.
- /// A symbol availability structure for the symbol.
- public static SymbolAvailability GetSupportedPlatforms (this ISymbol symbol)
- {
- var availability = GetAvailabilityForSymbol (symbol);
- // get the parents and return the merge
- foreach (var parent in GetParents (symbol)) {
- availability = availability.MergeWithParent (GetAvailabilityForSymbol (parent));
- }
-
- return availability;
- }
-
public static bool HasAttribute (this ISymbol symbol, string attribute)
{
var boundAttributes = symbol.GetAttributes ();
@@ -156,56 +85,6 @@ public static bool HasAttribute (this ISymbol symbol, string attribute)
return false;
}
- public static bool IsSmartEnum (this ITypeSymbol symbol)
- {
- // a type is a smart enum if its type is a enum one AND it was decorated with the
- // binding type attribute
- return symbol.TypeKind == TypeKind.Enum
- && symbol.HasAttribute (AttributesNames.BindingAttribute);
- }
-
- public static BindingTypeData GetBindingData (this ISymbol symbol)
- {
- var boundAttributes = symbol.GetAttributes ();
- if (boundAttributes.Length == 0) {
- // no attrs in the symbol, therefore the symbol is supported in all platforms
- return default;
- }
-
- // we are looking for the basic BindingAttribute attr
- foreach (var attributeData in boundAttributes) {
- var attrName = attributeData.AttributeClass?.ToDisplayString ();
- if (string.IsNullOrEmpty (attrName) || attrName != AttributesNames.BindingAttribute)
- continue;
- if (BindingTypeData.TryParse (attributeData, out var bindingData)) {
- return bindingData.Value;
- }
- }
-
- return default;
- }
-
- public static BindingTypeData GetBindingData (this ISymbol symbol) where T : Enum
- {
- var boundAttributes = symbol.GetAttributes ();
- if (boundAttributes.Length == 0) {
- // no attrs in the symbol, therefore the symbol is supported in all platforms
- return default;
- }
-
- var targetAttrName = AttributesNames.GetBindingTypeAttributeName ();
- foreach (var attributeData in boundAttributes) {
- var attrName = attributeData.AttributeClass?.ToDisplayString ();
- if (string.IsNullOrEmpty (attrName) || attrName != targetAttrName)
- continue;
- if (BindingTypeData.TryParse (attributeData, out var bindingData)) {
- return bindingData.Value;
- }
- }
-
- return default;
- }
-
delegate string? GetAttributeNames ();
delegate bool TryParse (AttributeData data, [NotNullWhen (true)] out T? value) where T : struct;
@@ -235,28 +114,6 @@ public static BindingTypeData GetBindingData (this ISymbol symbol) where T
return null;
}
- ///
- /// Retrieve the data of an export attribute on a symbol.
- ///
- /// The tagged symbol.
- /// Enum type used in the attribute.
- /// The data of the export attribute if present or null if it was not found.
- /// If the passed enum is unknown or not supported as an enum for the export attribute, null will be
- /// returned.
- public static ExportData? GetExportData (this ISymbol symbol) where T : Enum
- => GetAttribute> (symbol, AttributesNames.GetExportAttributeName, ExportData.TryParse);
-
- ///
- /// Retrieve the data of a field attribute on a symbol.
- ///
- /// The tagged symbol.
- /// Enum type used in the attribute.
- /// The data of the export attribute if present or null if it was not found.
- /// If the passed enum is unknown or not supported as an enum for the field attribute, null will be
- /// returned.
- public static FieldData? GetFieldData (this ISymbol symbol) where T : Enum
- => GetAttribute> (symbol, AttributesNames.GetFieldAttributeName, FieldData.TryParse);
-
///
/// Returns if a type is blittable or not.
///
diff --git a/src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.Generator.cs b/src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.Generator.cs
new file mode 100644
index 00000000000..70d64b65039
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Generator/Extensions/TypeSymbolExtensions.Generator.cs
@@ -0,0 +1,152 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using Microsoft.CodeAnalysis;
+using Microsoft.Macios.Generator.Attributes;
+using Microsoft.Macios.Generator.Availability;
+
+namespace Microsoft.Macios.Generator.Extensions;
+
+static partial class TypeSymbolExtensions {
+
+ ///
+ /// Return the symbol availability WITHOUT taking into account the parent symbols availability.
+ ///
+ /// The symbols whose availability attributes we want to retrieve.
+ /// The symbol availability WITHOUT taking into account the parent symbols.
+ /// This is a helper method, you probably don't want to use it.
+ static SymbolAvailability GetAvailabilityForSymbol (this ISymbol symbol)
+ {
+ //get the attribute of the symbol and look for the Supported and Unsupported attributes and
+ // add the different platforms to the result hashsets
+ var builder = SymbolAvailability.CreateBuilder ();
+ var boundAttributes = symbol.GetAttributes ();
+ if (boundAttributes.Length == 0) {
+ // no attrs in the symbol, therefore the symbol is supported in all platforms
+ return builder.ToImmutable ();
+ }
+
+ foreach (var attributeData in boundAttributes) {
+ var attrName = attributeData.AttributeClass?.ToDisplayString ();
+ if (string.IsNullOrEmpty (attrName))
+ continue;
+ // we only care in this case about the support and unsupported attrs, ignore any other
+ switch (attrName) {
+ case AttributesNames.SupportedOSPlatformAttribute:
+ if (SupportedOSPlatformData.TryParse (attributeData, out var supportedPlatform)) {
+ builder.Add (supportedPlatform.Value);
+ }
+
+ break;
+ case AttributesNames.UnsupportedOSPlatformAttribute:
+ if (UnsupportedOSPlatformData.TryParse (attributeData, out var unsupportedPlatform)) {
+ builder.Add (unsupportedPlatform.Value);
+ }
+
+ break;
+ case AttributesNames.ObsoletedOSPlatformAttribute:
+ if (ObsoletedOSPlatformData.TryParse (attributeData, out var obsoletedOsPlatform)) {
+ builder.Add (obsoletedOsPlatform.Value);
+ }
+
+ break;
+ default:
+ continue;
+ }
+ }
+
+ return builder.ToImmutable ();
+ }
+
+ ///
+ /// Returns the symbol availability taking into account the parent symbols availability.
+ ///
+ /// That means that the attributes used on the current symbol are merged with the attributes used
+ /// in all the symbol parents following the correct child-parent order.
+ ///
+ /// The symbol whose availability we want to retrieve.
+ /// A symbol availability structure for the symbol.
+ public static SymbolAvailability GetSupportedPlatforms (this ISymbol symbol)
+ {
+ var availability = GetAvailabilityForSymbol (symbol);
+ // get the parents and return the merge
+ foreach (var parent in GetParents (symbol)) {
+ availability = availability.MergeWithParent (GetAvailabilityForSymbol (parent));
+ }
+
+ return availability;
+ }
+
+ public static bool IsSmartEnum (this ITypeSymbol symbol)
+ {
+ // a type is a smart enum if its type is a enum one AND it was decorated with the
+ // binding type attribute
+ return symbol.TypeKind == TypeKind.Enum
+ && symbol.HasAttribute (AttributesNames.BindingAttribute);
+ }
+
+ public static BindingTypeData GetBindingData (this ISymbol symbol)
+ {
+ var boundAttributes = symbol.GetAttributes ();
+ if (boundAttributes.Length == 0) {
+ // no attrs in the symbol, therefore the symbol is supported in all platforms
+ return default;
+ }
+
+ // we are looking for the basic BindingAttribute attr
+ foreach (var attributeData in boundAttributes) {
+ var attrName = attributeData.AttributeClass?.ToDisplayString ();
+ if (string.IsNullOrEmpty (attrName) || attrName != AttributesNames.BindingAttribute)
+ continue;
+ if (BindingTypeData.TryParse (attributeData, out var bindingData)) {
+ return bindingData.Value;
+ }
+ }
+
+ return default;
+ }
+
+ public static BindingTypeData GetBindingData (this ISymbol symbol) where T : Enum
+ {
+ var boundAttributes = symbol.GetAttributes ();
+ if (boundAttributes.Length == 0) {
+ // no attrs in the symbol, therefore the symbol is supported in all platforms
+ return default;
+ }
+
+ var targetAttrName = AttributesNames.GetBindingTypeAttributeName ();
+ foreach (var attributeData in boundAttributes) {
+ var attrName = attributeData.AttributeClass?.ToDisplayString ();
+ if (string.IsNullOrEmpty (attrName) || attrName != targetAttrName)
+ continue;
+ if (BindingTypeData.TryParse (attributeData, out var bindingData)) {
+ return bindingData.Value;
+ }
+ }
+
+ return default;
+ }
+
+ ///
+ /// Retrieve the data of an export attribute on a symbol.
+ ///
+ /// The tagged symbol.
+ /// Enum type used in the attribute.
+ /// The data of the export attribute if present or null if it was not found.
+ /// If the passed enum is unknown or not supported as an enum for the export attribute, null will be
+ /// returned.
+ public static ExportData? GetExportData (this ISymbol symbol) where T : Enum
+ => GetAttribute> (symbol, AttributesNames.GetExportAttributeName, ExportData.TryParse);
+
+ ///
+ /// Retrieve the data of a field attribute on a symbol.
+ ///
+ /// The tagged symbol.
+ /// Enum type used in the attribute.
+ /// The data of the export attribute if present or null if it was not found.
+ /// If the passed enum is unknown or not supported as an enum for the field attribute, null will be
+ /// returned.
+ public static FieldData? GetFieldData (this ISymbol symbol) where T : Enum
+ => GetAttribute> (symbol, AttributesNames.GetFieldAttributeName, FieldData.TryParse);
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/AttributesNames.cs b/src/rgen/Microsoft.Macios.Transformer/AttributesNames.cs
new file mode 100644
index 00000000000..fc767cd8abd
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/AttributesNames.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+namespace Microsoft.Macios.Transformer;
+
+static class AttributesNames {
+ public const string AbstractAttribute = "AbstractAttribute";
+ public const string AdvancedAttribute = "AdvancedAttribute";
+ public const string BackingFieldTypeAttribute = "BackingFieldTypeAttribute";
+ public const string BaseTypeAttribute = "BaseTypeAttribute";
+ public const string BindAttribute = "BindAttribute";
+ public const string CategoryAttribute = "CategoryAttribute";
+ public const string CoreImageFilterAttribute = "CoreImageFilterAttribute";
+ public const string DefaultCtorVisibilityAttribute = "DefaultCtorVisibilityAttribute";
+ public const string DeprecatedAttribute = "DeprecatedAttribute";
+ public const string DesignatedDefaultCtorAttribute = "DesignatedDefaultCtorAttribute";
+ public const string DisableDefaultCtorAttribute = "DisableDefaultCtorAttribute";
+ public const string DisposeAttribute = "DisposeAttribute";
+ public const string ErrorDomainAttribute = "ErrorDomainAttribute";
+ public const string FieldAttribute = "Foundation.FieldAttribute";
+ public const string AdviceAttribute = "Foundation.AdviceAttribute";
+ public const string ModelAttribute = "Foundation.ModelAttribute";
+ public const string ProtocolAttribute = "Foundation.ProtocolAttribute";
+ public const string InternalAttribute = "InternalAttribute";
+ public const string IntroducedAttribute = "IntroducedAttribute";
+ public const string MacCatalystAttribute = "MacCatalystAttribute";
+ public const string NoiOSAttribute = "NoiOSAttribute";
+ public const string NoMacAttribute = "NoMacAttribute";
+ public const string NoMacCatalystAttribute = "NoMacCatalystAttribute";
+ public const string NoTVAttribute = "NoTVAttribute";
+ public const string iOSAttribute = "ObjCRuntime.iOSAttribute";
+ public const string MacAttribute = "ObjCRuntime.MacAttribute";
+ public const string NativeAttribute = "ObjCRuntime.NativeAttribute";
+ public const string NativeNameAttribute = "ObjCRuntime.NativeNameAttribute";
+ public const string ObsoletedAttribute = "ObsoletedAttribute";
+ public const string PartialAttribute = "PartialAttribute";
+ public const string SealedAttribute = "SealedAttribute";
+ public const string StaticAttribute = "StaticAttribute";
+ public const string StrongDictionaryAttribute = "StrongDictionaryAttribute";
+ public const string SyntheticAttribute = "SyntheticAttribute";
+ public const string EditorBrowsableAttribute = "System.ComponentModel.EditorBrowsableAttribute";
+ public const string ExperimentalAttribute = "System.Diagnostics.CodeAnalysis.ExperimentalAttribute";
+ public const string FlagsAttribute = "System.FlagsAttribute";
+ public const string ObsoleteAttribute = "System.ObsoleteAttribute";
+ public const string ThreadSafeAttribute = "ThreadSafeAttribute";
+ public const string TVAttribute = "TVAttribute";
+ public const string UnavailableAttribute = "UnavailableAttribute";
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj b/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
index 34893e627f2..3d0ac820d62 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
+++ b/src/rgen/Microsoft.Macios.Transformer/Microsoft.Macios.Transformer.csproj
@@ -15,4 +15,38 @@
+
+
+ <_Parameter1>Microsoft.Macios.Transformer.Tests
+
+
+
+
+
+ DictionaryComparer.cs
+
+
+ Attributes/ObsoletedOSPlatformData.cs
+
+
+ Attributes/SupportedOSPlatformData.cs
+
+
+ Attributes/UnsupportedOSPlatformData.cs
+
+
+ Availability/*.cs
+
+
+ Extensions/StringExtensions.cs
+
+
+ Extensions/TypeSymbolExtensions.Core.cs
+
+
+
+
+
+
+
diff --git a/src/rgen/Microsoft.Macios.Transformer/Transformer.cs b/src/rgen/Microsoft.Macios.Transformer/Transformer.cs
index c98314a37d6..fa653a299ab 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Transformer.cs
+++ b/src/rgen/Microsoft.Macios.Transformer/Transformer.cs
@@ -1,12 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
-using System.Collections.Immutable;
+using System.Diagnostics.CodeAnalysis;
using System.Text;
using Marille;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Macios.Generator.Extensions;
using Microsoft.Macios.Transformer.Extensions;
using Microsoft.Macios.Transformer.Workers;
@@ -17,19 +18,31 @@ namespace Microsoft.Macios.Transformer;
/// to be able to process the different transformations per binding type.
///
class Transformer {
- string destinationDirectory;
+ readonly string destinationDirectory;
readonly Compilation compilation;
- readonly ImmutableArray sources;
- HashSet? namespaceFilter;
+ readonly HashSet? namespaceFilter;
+ readonly Dictionary> transformers = new ();
- internal Transformer (string destination, Compilation compilationResult, ImmutableArray syntaxTrees,
- IEnumerable? namespaces = null)
+ internal Transformer (string destination, Compilation compilationResult, IEnumerable? namespaces = null)
{
destinationDirectory = destination;
compilation = compilationResult;
- sources = syntaxTrees;
if (namespaces is not null)
namespaceFilter = new HashSet (namespaces);
+
+ ITransformer<(string Path, string SymbolName)> [] defaultTransformers = [
+ new CategoryTransformer (destinationDirectory),
+ new ClassTransformer (destinationDirectory),
+ new ProtocolTransformer (destinationDirectory),
+ new SmartEnumTransformer (destinationDirectory),
+ new StrongDictionaryTransformer (destinationDirectory),
+ new CopyTransformer (destinationDirectory),
+ new ErrorDomainTransformer (destinationDirectory),
+ ];
+ // init the dict of transformers to access them via the name of the class
+ foreach (var transformer in defaultTransformers) {
+ transformers.Add (transformer.GetType ().Name, transformer);
+ }
}
internal async Task CreateHub ()
@@ -38,25 +51,71 @@ internal async Task CreateHub ()
var hub = new Hub ();
// use as many threads as the system allows
- var topicConfiguration = new TopicConfiguration { Mode = ChannelDeliveryMode.AtLeastOnceSync };
+ var configuration = new TopicConfiguration { Mode = ChannelDeliveryMode.AtLeastOnceSync };
+ foreach (var (topicName, transformer) in transformers) {
+ await hub.CreateAsync (topicName, configuration, transformer, transformer);
+ }
- // create the channels, because the app is alreay asyc there is nothing to deal with threads.
- var categories = new CategoryTransformer (destinationDirectory);
- await hub.CreateAsync (nameof (CategoryTransformer), topicConfiguration, categories, categories);
+ return hub;
+ }
- var classes = new ClassTransformer (destinationDirectory);
- await hub.CreateAsync (nameof (ClassTransformer), topicConfiguration, classes, classes);
+ internal static string? SelectTopic (INamedTypeSymbol symbol)
+ {
+ // get the attrs, based on those return the correct topic to use
+ var attrs = symbol.GetAttributeData ();
+ if (symbol.TypeKind == TypeKind.Enum) {
+ // simplest case, an error domain
+ if (attrs.ContainsKey (AttributesNames.ErrorDomainAttribute))
+ return nameof (ErrorDomainTransformer);
+
+ // in this case, we need to check if the enum is a smart enum.
+ // Smart enum: One of the enum members contains a FieldAttribute. Does NOT have to be ALL
+ var enumMembers = symbol.GetMembers ().OfType ().ToArray ();
+ foreach (var enumField in enumMembers) {
+ var fieldAttrs = enumField.GetAttributeData ();
+ if (fieldAttrs.ContainsKey (AttributesNames.FieldAttribute)) {
+ return nameof (SmartEnumTransformer);
+ }
+ }
- var protocols = new ProtocolTransformer (destinationDirectory);
- await hub.CreateAsync (nameof (ProtocolTransformer), topicConfiguration, protocols, protocols);
+ // we have either a native enum of a regular enum, we will use the copy worker
+ return nameof (CopyTransformer);
+ }
- var smartEnums = new SmartEnumTransformer (destinationDirectory);
- await hub.CreateAsync (nameof (SmartEnumTransformer), topicConfiguration, smartEnums, smartEnums);
+ if (attrs.ContainsKey (AttributesNames.BaseTypeAttribute)) {
+ // if can be a class or a protocol, check if the protocol attribute is present
+ if (attrs.ContainsKey (AttributesNames.ProtocolAttribute) ||
+ attrs.ContainsKey (AttributesNames.ModelAttribute))
+ return nameof (ProtocolTransformer);
+ if (attrs.ContainsKey (AttributesNames.CategoryAttribute))
+ return nameof (CategoryTransformer);
+ return nameof (ClassTransformer);
+ }
- var strongDictionaries = new StrongDictionaryTransformer (destinationDirectory);
- await hub.CreateAsync (nameof (StrongDictionaryTransformer), topicConfiguration, strongDictionaries, strongDictionaries);
+ if (attrs.ContainsKey (AttributesNames.StrongDictionaryAttribute))
+ return nameof (StrongDictionaryTransformer);
- return hub;
+ return null;
+ }
+
+ internal bool Skip (SyntaxTree syntaxTree, ISymbol symbol, [NotNullWhen (false)] out string? outputDirectory)
+ {
+ outputDirectory = null;
+ var symbolNamespace = symbol.ContainingNamespace.ToString ();
+ if (symbolNamespace is null)
+ // skip we could not retrieve the namespace
+ return true;
+
+ if (namespaceFilter is not null && !namespaceFilter.Contains (symbolNamespace)) {
+ // TODO we could do this better by looking at the tree
+ Console.WriteLine (
+ $"Skipping {symbol.Name} because namespace {symbolNamespace} was not included in the transformation");
+ // filtered out
+ return true;
+ }
+ outputDirectory = Path.Combine (destinationDirectory, symbolNamespace);
+ // If the syntax tree comes from the output directory, we skip it because this is a manual binding
+ return syntaxTree.FilePath.StartsWith (outputDirectory);
}
internal async Task Execute ()
@@ -74,10 +133,10 @@ internal async Task Execute ()
var hub = await CreateHub ();
// with the hub created, loop over the syntax trees and create the messages to be sent to the hub
- foreach (var tree in sources) {
+ foreach (var tree in compilation.SyntaxTrees) {
var model = compilation.GetSemanticModel (tree);
// the bindings have A LOT of interfaces, we cannot get a symbol for the entire tree
- var declarations = tree.GetRoot ()
+ var declarations = (await tree.GetRootAsync ())
.DescendantNodes ()
.OfType ().ToArray ();
@@ -91,31 +150,17 @@ internal async Task Execute ()
continue;
}
- var namespaceName = symbol.ContainingNamespace.ToString ();
- if (namespaceName is null)
- // skip we could not retrieve the namespace
- continue;
-
- if (namespaceFilter is not null && !namespaceFilter.Contains (namespaceName)) {
- // TODO we could do this better by looking at the tree
- Console.WriteLine ($"Skipping {symbol.Name} because namespace {namespaceName} was not included in the transformation");
- // filtered out
+ if (Skip (tree, symbol, out var outputDirectory))
+ // matched the filter
continue;
- }
// create the destination directory if needed, this is the only location we should be creating directories
- var currentDirectory = Path.Combine (destinationDirectory, namespaceName);
- Directory.CreateDirectory (currentDirectory);
-
- var message = (tree.FilePath, symbol.Name);
- // push the message to the hub, we are doing this to all channels, this will need to be filered in the
- // future
- Console.WriteLine ($"Publishing message to all channels: {message}");
- await hub.PublishAsync (nameof (CategoryTransformer), message);
- await hub.PublishAsync (nameof (ClassTransformer), message);
- await hub.PublishAsync (nameof (ProtocolTransformer), message);
- await hub.PublishAsync (nameof (SmartEnumTransformer), message);
- await hub.PublishAsync (nameof (StrongDictionaryTransformer), message);
+ Directory.CreateDirectory (outputDirectory);
+
+ var topicName = SelectTopic (symbol);
+ if (topicName is not null && transformers.TryGetValue (topicName, out var transformer)) {
+ await hub.PublishAsync (topicName, transformer.CreateMessage (tree, symbol));
+ }
}
}
@@ -124,8 +169,8 @@ internal async Task Execute ()
await hub.CloseAllAsync ();
}
-
- public static Task Execute (string destinationDirectory, string rspFile, string workingDirectory, string sdkDirectory)
+ public static Task Execute (string destinationDirectory, string rspFile, string workingDirectory,
+ string sdkDirectory)
{
Console.WriteLine ("Executing transformation");
// the transformation works as follows. We first need to parse the rsp file to create a compilation
@@ -135,13 +180,13 @@ public static Task Execute (string destinationDirectory, string rspFile, string
rspFile, workingDirectory, sdkDirectory);
// add NET to the preprocessor directives
- var preprocesorDirectives = parseResult.ParseOptions.PreprocessorSymbolNames.ToList ();
- preprocesorDirectives.Add ("NET");
+ var preprocessorDirectives = parseResult.ParseOptions.PreprocessorSymbolNames.ToList ();
+ preprocessorDirectives.Add ("NET");
// fixing the parsing options, we must have an issue in the rsp
var updatedParseOptions = parseResult.ParseOptions
.WithLanguageVersion (LanguageVersion.Latest)
- .WithPreprocessorSymbols (preprocesorDirectives)
+ .WithPreprocessorSymbols (preprocessorDirectives)
.WithDocumentationMode (DocumentationMode.None);
var references = parseResult.GetReferences (workingDirectory, sdkDirectory);
@@ -154,7 +199,7 @@ public static Task Execute (string destinationDirectory, string rspFile, string
options: parseResult.CompilationOptions);
var diagnostics = compilation.GetDiagnostics ();
- Console.WriteLine ($"Diganostics legth {diagnostics.Length}");
+ Console.WriteLine ($"Diagnostics length {diagnostics.Length}");
// collect all the compilation errors, ignoring the warnings, if any error is found, we throw an exception
var errors = diagnostics.Where (d => d.Severity == DiagnosticSeverity.Error).ToArray ();
if (errors.Length > 0) {
@@ -162,12 +207,11 @@ public static Task Execute (string destinationDirectory, string rspFile, string
foreach (var resultError in errors) {
sb.AppendLine ($"{resultError}");
}
- Console.WriteLine (sb);
throw new Exception ($"Error during workspace compilation: {sb}");
}
// create a new transformer with the compilation result and the syntax trees
- var transformer = new Transformer (destinationDirectory, compilation, parsedSource);
+ var transformer = new Transformer (destinationDirectory, compilation);
return transformer.Execute ();
}
}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Workers/CategoryTransformer.cs b/src/rgen/Microsoft.Macios.Transformer/Workers/CategoryTransformer.cs
index 1c1e7ab391e..86f1adb02c0 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Workers/CategoryTransformer.cs
+++ b/src/rgen/Microsoft.Macios.Transformer/Workers/CategoryTransformer.cs
@@ -2,10 +2,13 @@
// Licensed under the MIT License.
using Marille;
+using Microsoft.CodeAnalysis;
namespace Microsoft.Macios.Transformer.Workers;
-public class CategoryTransformer (string destinationDirectory) : IWorker<(string Path, string SymbolName)>, IErrorWorker<(string Path, string Example)> {
+public class CategoryTransformer (string destinationDirectory) : ITransformer<(string Path, string SymbolName)> {
+
+ public bool UseBackgroundThread { get => true; }
public Task ConsumeAsync ((string Path, string SymbolName) message, CancellationToken token = new ())
{
@@ -13,15 +16,20 @@ public class CategoryTransformer (string destinationDirectory) : IWorker<(string
return Task.Delay (10);
}
- public void Dispose () { }
-
- public ValueTask DisposeAsync () => ValueTask.CompletedTask;
-
- public Task ConsumeAsync ((string Path, string Example) message, Exception exception,
+ public Task ConsumeAsync ((string Path, string SymbolName) message, Exception exception,
CancellationToken token = new CancellationToken ())
{
return Task.CompletedTask;
}
- public bool UseBackgroundThread { get => true; }
+ public (string Path, string SymbolName) CreateMessage (SyntaxTree treeNode, ISymbol symbol)
+ {
+ return (treeNode.FilePath, symbol.Name);
+ }
+
+ public void Dispose () { }
+
+ public ValueTask DisposeAsync () => ValueTask.CompletedTask;
+
+
}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Workers/ClassTransformer.cs b/src/rgen/Microsoft.Macios.Transformer/Workers/ClassTransformer.cs
index e3785556735..1cf6367e9da 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Workers/ClassTransformer.cs
+++ b/src/rgen/Microsoft.Macios.Transformer/Workers/ClassTransformer.cs
@@ -2,26 +2,32 @@
// Licensed under the MIT License.
using Marille;
+using Microsoft.CodeAnalysis;
namespace Microsoft.Macios.Transformer.Workers;
-public class ClassTransformer (string destinationDirectory) : IWorker<(string Path, string SymbolName)>, IErrorWorker<(string Path, string Example)> {
+public class ClassTransformer (string destinationDirectory) : ITransformer<(string Path, string SymbolName)> {
+ public ValueTask DisposeAsync () => ValueTask.CompletedTask;
public Task ConsumeAsync ((string Path, string SymbolName) message, CancellationToken token = new ())
{
Console.WriteLine ($"ClassTransformer: Transforming class {message.SymbolName} for path {message.Path} to {destinationDirectory}");
return Task.Delay (10);
}
- public Task ConsumeAsync ((string Path, string Example) message, Exception exception,
+ public Task ConsumeAsync ((string Path, string SymbolName) message, Exception exception,
CancellationToken token = new CancellationToken ())
{
return Task.CompletedTask;
}
+ public (string Path, string SymbolName) CreateMessage (SyntaxTree treeNode, ISymbol symbol)
+ {
+ return (treeNode.FilePath, symbol.Name);
+ }
+
public void Dispose () { }
- public ValueTask DisposeAsync () => ValueTask.CompletedTask;
public bool UseBackgroundThread { get => true; }
}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Workers/CopyTransformer.cs b/src/rgen/Microsoft.Macios.Transformer/Workers/CopyTransformer.cs
new file mode 100644
index 00000000000..fcff0f2a384
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/Workers/CopyTransformer.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Marille;
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Macios.Transformer.Workers;
+
+public class CopyTransformer (string destinationDirectory) : ITransformer<(string Path, string SymbolName)> {
+
+ public bool UseBackgroundThread { get => true; }
+
+ public Task ConsumeAsync ((string Path, string SymbolName) message, CancellationToken token = new ())
+ {
+ Console.WriteLine ($"CopyTransformer: Transforming class {message.SymbolName} for path {message.Path} to {destinationDirectory}");
+ return Task.Delay (10);
+ }
+
+ public Task ConsumeAsync ((string Path, string SymbolName) message, Exception exception,
+ CancellationToken token = new CancellationToken ())
+ {
+ return Task.CompletedTask;
+ }
+
+ public (string Path, string SymbolName) CreateMessage (SyntaxTree treeNode, ISymbol symbol)
+ {
+ return (treeNode.FilePath, symbol.Name);
+ }
+
+ public void Dispose () { }
+
+ public ValueTask DisposeAsync () => ValueTask.CompletedTask;
+
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Workers/ErrorDomainTransformer.cs b/src/rgen/Microsoft.Macios.Transformer/Workers/ErrorDomainTransformer.cs
new file mode 100644
index 00000000000..73c2c579cb9
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/Workers/ErrorDomainTransformer.cs
@@ -0,0 +1,35 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Marille;
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Macios.Transformer.Workers;
+
+
+public class ErrorDomainTransformer (string destinationDirectory) : ITransformer<(string Path, string SymbolName)> {
+
+ public bool UseBackgroundThread { get => true; }
+
+ public Task ConsumeAsync ((string Path, string SymbolName) message, CancellationToken token = new ())
+ {
+ Console.WriteLine ($"CopyTransformer: Transforming class {message.SymbolName} for path {message.Path} to {destinationDirectory}");
+ return Task.Delay (10);
+ }
+
+ public Task ConsumeAsync ((string Path, string SymbolName) message, Exception exception,
+ CancellationToken token = new CancellationToken ())
+ {
+ return Task.CompletedTask;
+ }
+
+ public (string Path, string SymbolName) CreateMessage (SyntaxTree treeNode, ISymbol symbol)
+ {
+ return (treeNode.FilePath, symbol.Name);
+ }
+
+ public void Dispose () { }
+
+ public ValueTask DisposeAsync () => ValueTask.CompletedTask;
+
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Workers/ITransformer.cs b/src/rgen/Microsoft.Macios.Transformer/Workers/ITransformer.cs
new file mode 100644
index 00000000000..9f586727759
--- /dev/null
+++ b/src/rgen/Microsoft.Macios.Transformer/Workers/ITransformer.cs
@@ -0,0 +1,12 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Marille;
+using Microsoft.CodeAnalysis;
+
+namespace Microsoft.Macios.Transformer.Workers;
+
+interface ITransformer : IWorker, IErrorWorker where T : struct {
+
+ T CreateMessage (SyntaxTree treeNode, ISymbol symbol);
+}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Workers/ProtocolTransformer.cs b/src/rgen/Microsoft.Macios.Transformer/Workers/ProtocolTransformer.cs
index 07f71cf4e1f..7032f8e853b 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Workers/ProtocolTransformer.cs
+++ b/src/rgen/Microsoft.Macios.Transformer/Workers/ProtocolTransformer.cs
@@ -2,26 +2,32 @@
// Licensed under the MIT License.
using Marille;
+using Microsoft.CodeAnalysis;
namespace Microsoft.Macios.Transformer.Workers;
-public class ProtocolTransformer (string destinationDirectory) : IWorker<(string Path, string SymbolName)>, IErrorWorker<(string Path, string Example)> {
+public class ProtocolTransformer (string destinationDirectory) : ITransformer<(string Path, string SymbolName)> {
+ public bool UseBackgroundThread { get => true; }
public Task ConsumeAsync ((string Path, string SymbolName) message, CancellationToken token = new ())
{
Console.WriteLine ($"ProtocolTransformer: Transforming class {message.SymbolName} for path {message.Path} to {destinationDirectory}");
return Task.Delay (10);
}
- public Task ConsumeAsync ((string Path, string Example) message, Exception exception,
+ public Task ConsumeAsync ((string Path, string SymbolName) message, Exception exception,
CancellationToken token = new CancellationToken ())
{
return Task.CompletedTask;
}
+ public (string Path, string SymbolName) CreateMessage (SyntaxTree treeNode, ISymbol symbol)
+ {
+ return (treeNode.FilePath, symbol.Name);
+ }
+
public void Dispose () { }
public ValueTask DisposeAsync () => ValueTask.CompletedTask;
- public bool UseBackgroundThread { get => true; }
}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Workers/SmartEnumTransformer.cs b/src/rgen/Microsoft.Macios.Transformer/Workers/SmartEnumTransformer.cs
index b5f13dc964f..f04d83c4131 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Workers/SmartEnumTransformer.cs
+++ b/src/rgen/Microsoft.Macios.Transformer/Workers/SmartEnumTransformer.cs
@@ -2,10 +2,13 @@
// Licensed under the MIT License.
using Marille;
+using Microsoft.CodeAnalysis;
namespace Microsoft.Macios.Transformer.Workers;
-public class SmartEnumTransformer (string destinationDirectory) : IWorker<(string Path, string SymbolName)>, IErrorWorker<(string Path, string Example)> {
+public class SmartEnumTransformer (string destinationDirectory) : ITransformer<(string Path, string SymbolName)> {
+
+ public bool UseBackgroundThread { get => true; }
public Task ConsumeAsync ((string Path, string SymbolName) message, CancellationToken token = new ())
{
@@ -13,15 +16,19 @@ public class SmartEnumTransformer (string destinationDirectory) : IWorker<(strin
return Task.Delay (10);
}
- public Task ConsumeAsync ((string Path, string Example) message, Exception exception,
+ public Task ConsumeAsync ((string Path, string SymbolName) message, Exception exception,
CancellationToken token = new CancellationToken ())
{
return Task.CompletedTask;
}
+ public (string Path, string SymbolName) CreateMessage (SyntaxTree treeNode, ISymbol symbol)
+ {
+ return (treeNode.FilePath, symbol.Name);
+ }
+
public void Dispose () { }
public ValueTask DisposeAsync () => ValueTask.CompletedTask;
- public bool UseBackgroundThread { get => true; }
}
diff --git a/src/rgen/Microsoft.Macios.Transformer/Workers/StrongDictionaryTransformer.cs b/src/rgen/Microsoft.Macios.Transformer/Workers/StrongDictionaryTransformer.cs
index fbfcc1c7dc5..287ba445a5b 100644
--- a/src/rgen/Microsoft.Macios.Transformer/Workers/StrongDictionaryTransformer.cs
+++ b/src/rgen/Microsoft.Macios.Transformer/Workers/StrongDictionaryTransformer.cs
@@ -2,26 +2,32 @@
// Licensed under the MIT License.
using Marille;
+using Microsoft.CodeAnalysis;
namespace Microsoft.Macios.Transformer.Workers;
-public class StrongDictionaryTransformer (string destinationDirectory) : IWorker<(string Path, string SymbolName)>, IErrorWorker<(string Path, string Example)> {
+public class StrongDictionaryTransformer (string destinationDirectory) : ITransformer<(string Path, string SymbolName)> {
+ public bool UseBackgroundThread { get => true; }
public Task ConsumeAsync ((string Path, string SymbolName) message, CancellationToken token = new ())
{
Console.WriteLine ($"StrongDictionaryTransformer: Transforming class {message.SymbolName} for path {message.Path} to {destinationDirectory}");
return Task.Delay (10);
}
- public Task ConsumeAsync ((string Path, string Example) message, Exception exception,
+ public Task ConsumeAsync ((string Path, string SymbolName) message, Exception exception,
CancellationToken token = new CancellationToken ())
{
return Task.CompletedTask;
}
+ public (string Path, string SymbolName) CreateMessage (SyntaxTree treeNode, ISymbol symbol)
+ {
+ return (treeNode.FilePath, symbol.Name);
+ }
+
public void Dispose () { }
public ValueTask DisposeAsync () => ValueTask.CompletedTask;
- public bool UseBackgroundThread { get => true; }
}
diff --git a/src/rgen/rgen.sln b/src/rgen/rgen.sln
index 12549b0432a..cf035050472 100644
--- a/src/rgen/rgen.sln
+++ b/src/rgen/rgen.sln
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-#
+#
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Macios.Generator", "Microsoft.Macios.Generator\Microsoft.Macios.Generator.csproj", "{8E9CF45D-E836-447E-9290-03A9CACE2704}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Macios.Generator.Sample", "Microsoft.Macios.Generator.Sample\Microsoft.Macios.Generator.Sample.csproj", "{AD0A1FDC-350F-47E2-AA9D-A6F32793C130}"
@@ -18,6 +18,7 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Macios.Transformer", "Microsoft.Macios.Transformer\Microsoft.Macios.Transformer.csproj", "{D05D2AAA-71C9-49C9-B344-2F8C251E60DB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Macios.Transformer.Tests", "..\..\tests\rgen\Microsoft.Macios.Transformer.Tests\Microsoft.Macios.Transformer.Tests.csproj", "{BE23E467-7971-4439-BEE8-220B77F40027}"
+EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Macios.Bindings.CodeFixers", "Microsoft.Macios.Bindings.CodeFixers\Microsoft.Macios.Bindings.CodeFixers.csproj", "{4986D2E4-89B0-43A3-9879-93ED236C265D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Macios.Bindings.CodeFixers.Tests", "..\..\tests\rgen\Microsoft.Macios.Bindings.CodeFixers.Tests\Microsoft.Macios.Bindings.CodeFixers.Tests.csproj", "{E7928D64-8E45-40BF-B393-732FF20D35E7}"
diff --git a/tests/rgen/Microsoft.Macios.Transformer.Tests/BaseTransformerTestClass.cs b/tests/rgen/Microsoft.Macios.Transformer.Tests/BaseTransformerTestClass.cs
new file mode 100644
index 00000000000..2ec6c8e0a22
--- /dev/null
+++ b/tests/rgen/Microsoft.Macios.Transformer.Tests/BaseTransformerTestClass.cs
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections.Immutable;
+using System.Runtime.CompilerServices;
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Xamarin.Tests;
+using Xamarin.Utils;
+
+namespace Microsoft.Macios.Transformer.Tests;
+
+///
+/// Base class that allows to test the transformer.
+///
+public class BaseTransformerTestClass {
+
+ // list of the defines for each platform, this is passed to the parser to ensure that
+ // we are testing the platforms as if they were being compiled.
+ readonly Dictionary platformDefines = new () {
+ { ApplePlatform.iOS, new [] { "__IOS__" } },
+ { ApplePlatform.TVOS, new [] { "__TVOS__" } },
+ { ApplePlatform.MacOSX, new [] { "__MACOS__" } },
+ { ApplePlatform.MacCatalyst, new [] { "__MACCATALYST__" } },
+ };
+
+ protected Compilation CreateCompilation (ApplePlatform platform, [CallerMemberName] string name = "", params (string Source, string Path) [] sources)
+ {
+ // get the dotnet bcl and fully load it for the test.
+ var references = Directory.GetFiles (Configuration.DotNetBclDir, "*.dll")
+ .Select (assembly => MetadataReference.CreateFromFile (assembly)).ToList ();
+
+ // get the dll for the current platform, this is needed because that way we will get the attributes that
+ // are used in the old dlls that are needed to test the transformer.
+ var targetFramework = TargetFramework.GetTargetFramework (platform, isDotNet: true);
+ var platformDll = Configuration.GetBaseLibrary (targetFramework);
+ if (!string.IsNullOrEmpty (platformDll)) {
+ references.Add (MetadataReference.CreateFromFile (platformDll));
+ } else {
+ throw new InvalidOperationException ($"Could not find platform dll for {platform}");
+ }
+ // include the bgen attributes to the compilation, otherwise the transformer will not work.
+ var sourcesList = sources.ToList ();
+ if (Configuration.TryGetRootPath (out var rootPath)) {
+ var oldVersionAttrs = Path.Combine (rootPath, "src", "ObjCRuntime", "PlatformAvailability.cs");
+ sourcesList.Add ((File.ReadAllText (oldVersionAttrs), oldVersionAttrs));
+
+ var oldBgenAttrs = Path.Combine (rootPath, "src", "bgen", "Attributes.cs");
+ sourcesList.Add ((File.ReadAllText (oldBgenAttrs), oldBgenAttrs));
+ }
+
+ var parseOptions = new CSharpParseOptions (LanguageVersion.Latest, DocumentationMode.None, preprocessorSymbols: ["COREBUILD"]);
+ var trees = sourcesList.Select (
+ s => CSharpSyntaxTree.ParseText (s.Source, parseOptions, s.Path))
+ .ToImmutableArray ();
+
+ var options = new CSharpCompilationOptions (OutputKind.NetModule)
+ .WithAllowUnsafe (true);
+
+ return CSharpCompilation.Create (name, trees, references, options);
+ }
+
+}
diff --git a/tests/rgen/Microsoft.Macios.Transformer.Tests/Microsoft.Macios.Transformer.Tests.csproj b/tests/rgen/Microsoft.Macios.Transformer.Tests/Microsoft.Macios.Transformer.Tests.csproj
index e676a0a7b31..7ee72ccb941 100644
--- a/tests/rgen/Microsoft.Macios.Transformer.Tests/Microsoft.Macios.Transformer.Tests.csproj
+++ b/tests/rgen/Microsoft.Macios.Transformer.Tests/Microsoft.Macios.Transformer.Tests.csproj
@@ -19,40 +19,32 @@
-
+
+
-
- external\Configuration.cs
-
-
- external\ConfigurationXUnit.cs
-
-
- external\Profile.cs
-
-
- external\ExecutionHelper.cs
-
-
- external\ApplePlatform.cs
-
-
- external\TargetFramework.cs
-
-
- external\StringUtils.cs
-
-
- external\Execution.cs
-
-
- external\SdkVersions.cs
-
-
- external\Cache.cs
-
+
+ external\Configuration.cs
+
+
+ external\ConfigurationXUnit.cs
+
+
+ external\Profile.cs
+
+
+ external\ExecutionHelper.cs
+
+
+ external\StringUtils.cs
+
+
+ external\Execution.cs
+
+
+ external\Cache.cs
+
diff --git a/tests/rgen/Microsoft.Macios.Transformer.Tests/TransformerTests.cs b/tests/rgen/Microsoft.Macios.Transformer.Tests/TransformerTests.cs
new file mode 100644
index 00000000000..3d573705138
--- /dev/null
+++ b/tests/rgen/Microsoft.Macios.Transformer.Tests/TransformerTests.cs
@@ -0,0 +1,266 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System.Collections;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Microsoft.Macios.Transformer.Workers;
+using Xamarin.Tests;
+using Xamarin.Utils;
+
+namespace Microsoft.Macios.Transformer.Tests;
+
+public class TransformerTests : BaseTransformerTestClass, IDisposable {
+ string targetDirectory;
+
+ public TransformerTests ()
+ {
+ targetDirectory = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ());
+ Directory.CreateDirectory (targetDirectory);
+ }
+
+
+ class TestDataSkipTests : IEnumerable