public ReactAssembly AnalyzeAndConstructAssemblyModel() { Contract.Assert(m_compilation != null, "Expected to have a compilation. Must call CompileAndCheckForErrors first"); var assembly = new ReactAssembly(); var proceseedTypes = new HashSet <ITypeSymbol>(); foreach (var type in GetAllTypes()) { if (TryExtractModule(type, out var module)) { assembly.Modules.Add(module); } if (IsViewManager(type)) { assembly.ViewManagers.Add(type); } // Proactively register serializable types. switch (type.TypeKind) { case TypeKind.Enum: assembly.SerializableTypes.Add(type, type.TypeKind); break; } // Register extension methods if (type.MightContainExtensionMethods) { foreach (var member in type.GetMembers()) { if (member is IMethodSymbol method) { if (method.IsExtensionMethod && method.Parameters.Length == 2 && !(method.Parameters[1].Type is ITypeParameterSymbol)) { if (method.Parameters[0].Type.Equals(ReactTypes.JSValueReader, SymbolEqualityComparer.Default) && method.Parameters[1].RefKind == RefKind.Out) { assembly.JSReaderFunctions.Add(method.Parameters[1].Type, method); } else if (method.Parameters[0].Type.Equals(ReactTypes.JSValueWriter, SymbolEqualityComparer.Default)) { assembly.JSWriterFunctions.Add(method.Parameters[1].Type, method); } } } } } } foreach (var module in assembly.Modules) { foreach (var method in module.Methods) { AddSerializableMethod(method.Method); } foreach (var constant in module.Constants) { if (constant.Symbol is IFieldSymbol field) { AddSerializableType(field.Type); } else if (constant.Symbol is IPropertySymbol property) { AddSerializableType(property.Type); } } foreach (var callback in module.Events.Union <ReactCallback>(module.Functions)) { foreach (var param in callback.CallbackParameters) { AddSerializableType(param.Type); } } } void AddSerializableMethod(IMethodSymbol method) { AddSerializableType(method.ReturnType); foreach (var param in method.Parameters) { AddSerializableType(param.Type); } } void AddSerializableType(ITypeSymbol type) { if (proceseedTypes.Contains(type)) { return; } proceseedTypes.Add(type); if (type is INamedTypeSymbol namedType) { if (type.TypeKind == TypeKind.Delegate) { Contract.Assert(namedType.DelegateInvokeMethod != null); AddSerializableMethod(namedType.DelegateInvokeMethod); } else if (type.ContainingAssembly.Equals(m_compilation.Assembly, SymbolEqualityComparer.Default)) { if (namedType.TypeKind == TypeKind.Class) { // Check that classes have a default constructor. if (!namedType .GetMembers() .Any(member => member is IMethodSymbol method && method.MethodKind == MethodKind.Constructor && method.Parameters.Length == 0)) { } } assembly.SerializableTypes.Add(namedType, namedType.TypeKind); } } } return(assembly); }
public CSharpSyntaxNode Generate(ReactAssembly assembly) { var registrationInvocations = new List <StatementSyntax>(); var providerMembers = new List <MemberDeclarationSyntax>(); if (assembly.ViewManagers.Any()) { registrationInvocations.Add(InvocationStatement(ReactNativeNames.CreateViewManagers, IdentifierName(ReactNativeNames.PackageBuilderId))); providerMembers.Add(CreateViewManagers(assembly.ViewManagers)); } if (assembly.Modules.Any()) { registrationInvocations.Add(InvocationStatement(ReactNativeNames.CreateModules, IdentifierName((ReactNativeNames.PackageBuilderId)))); providerMembers.Add(CreateModules(assembly.Modules)); } if (assembly.SerializableTypes.Any()) { registrationInvocations.Add(InvocationStatement(ReactNativeNames.CreateSerializers)); providerMembers.AddRange(CreateSerializers(assembly.SerializableTypes.Keys)); } if (assembly.JSReaderFunctions.Any()) { registrationInvocations.Add(InvocationStatement(ReactNativeNames.RegisterExtensionReaders)); providerMembers.Add(RegisterExtensionReaders(assembly.JSReaderFunctions)); } if (assembly.JSWriterFunctions.Any()) { registrationInvocations.Add(InvocationStatement(ReactNativeNames.RegisterExtensionWriter)); providerMembers.Add(RegisterExtensionWriter(assembly.JSWriterFunctions)); } // Generates: // public void CreatePackage(IPackageBuilder packageBuilder) // { // ... registrationInvocations // } var createPackageMethod = MethodDeclaration( PredefinedType(Token(SyntaxKind.VoidKeyword)), ReactNativeNames.CreatePackage) .AddModifiers( Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters( GetPackageBuilderArgument()) .WithBody( Block( registrationInvocations )); // Ensure the main package registration implementation is at the top of the file. providerMembers.Insert(0, createPackageMethod); // Generates: // namespace "MyNS" // { // public sealed partial ReactPackageProvider : IReactPackageProvider // { // ... providerMembers // } // } var ns = NamespaceDeclaration(ParseName(m_rootNamespace)) .AddMembers( ClassDeclaration("ReactPackageProvider") .AddModifiers( Token(SyntaxKind.PublicKeyword), Token(SyntaxKind.SealedKeyword), Token(SyntaxKind.PartialKeyword)) .AddBaseListTypes( SimpleBaseType( m_reactTypes.IReactPackageProvider.ToTypeSyntax())) .WithMembers( new SyntaxList <MemberDeclarationSyntax>(providerMembers)) ); return(ns); }