Exemplo n.º 1
0
    public override IEnumerable <StatementSyntax> GenerateCode(CsCallable csElement, PlatformDetectionType platform)
    {
        var interopSig = csElement.InteropSignatures[platform];

        if (!interopSig.ForcedReturnBufferSig && csElement.HasReturnTypeValue)
        {
            foreach (var statement in GenerateProlog(csElement.ReturnValue, null, null))
            {
                yield return(statement);
            }
        }

        foreach (var signatureParameter in interopSig.ParameterTypes)
        {
            var publicParameter   = signatureParameter.Item;
            var nativeParameter   = IdentifierName(signatureParameter.Name);
            var interopTypeSyntax = signatureParameter.InteropTypeSyntax;
            var builder           = GetPrologBuilder(publicParameter);

            foreach (var statement in builder(publicParameter, nativeParameter, interopTypeSyntax))
            {
                yield return(statement);
            }
        }
    }
Exemplo n.º 2
0
    public override IEnumerable <MemberDeclarationSyntax> GenerateCode(CsCallable csElement,
                                                                       PlatformDetectionType platform)
    {
        var sig = csElement.InteropSignatures[platform];

        var delegateDecl = GenerateDelegateDeclaration(csElement, platform, sig);

        if (csElement is CsMethod {
            IsFunctionPointerInVtbl : true
        })
Exemplo n.º 3
0
    public ExpressionSyntax VTableOffsetExpression(PlatformDetectionType platform)
    {
        int windowsOffset = WindowsOffset, offset = Offset;

        return(GeneratorHelpers.PlatformSpecificExpression(
                   Ioc.GlobalNamespace, platform, () => offset != windowsOffset,
                   () => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(windowsOffset)),
                   () => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(offset))
                   ));
    }
Exemplo n.º 4
0
 private ExpressionSyntax GetMarshalFunctionPointerForDelegate(CsMethod method,
                                                               PlatformDetectionType platform) =>
 InvocationExpression(
     MemberAccessExpression(
         SyntaxKind.SimpleMemberAccessExpression,
         GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal),
         IdentifierName("GetFunctionPointerForDelegate")
         ),
     ArgumentList(SingletonSeparatedList(Argument(IdentifierName(GetMethodCacheName(method, platform)))))
     );
Exemplo n.º 5
0
    private static void CoercePlatform(CsMethod csMethod, ref PlatformDetectionType platform)
    {
        var interopSignatures = csMethod.InteropSignatures;

        if (interopSignatures.ContainsKey(platform))
        {
            return;
        }

        platform = PlatformDetectionType.Any;
        Debug.Assert(interopSignatures.ContainsKey(platform));
    }
Exemplo n.º 6
0
    private void InitSignatureWithReturnType(CsCallable callable,
                                             InteropMethodSignature cSharpInteropCalliSignature,
                                             PlatformDetectionType platform)
    {
        var returnType = CoerceToBlittable(GetInteropTypeForReturnValue(callable.ReturnValue, platform));

        if (returnType is null)
        {
            Logger.Error(LoggingCodes.InvalidMethodReturnType, "Invalid return type {0} for method {1}",
                         callable.ReturnValue.PublicType.QualifiedName, callable.CppElement);
            returnType = callable.ReturnValue.PublicType.QualifiedName;
        }

        cSharpInteropCalliSignature.ReturnType = returnType;
    }
        private InteropMethodSignature GetNativeInteropSignature(CsCallable callable, bool isFunction,
                                                                 PlatformDetectionType platform)
        {
            // Tag if the method is a function
            var cSharpInteropCalliSignature = new InteropMethodSignature
            {
                IsFunction        = isFunction,
                CallingConvention = callable.CppCallingConvention
            };

            InitSignatureWithReturnType(callable, cSharpInteropCalliSignature, platform);

            // Handle Parameters
            InitCalliSignatureParameters(callable, cSharpInteropCalliSignature);

            return(cSharpInteropCalliSignature);
        }
        private InteropType GetInteropTypeForReturnValue(CsReturnValue returnValue,
                                                         PlatformDetectionType platform,
                                                         ref InteropMethodSignatureFlags flags)
        {
            var platformSpecificReturnTypeOverrides = (platform & PlatformDetectionType.Windows) != 0
                                                          ? windowsOnlyReturnTypeOverrides
                                                          : systemvOnlyReturnTypeOverrides;

            // Handle Return Type parameter
            // MarshalType.Type == null, then check that it is a structure
            if (returnValue.PublicType is CsStruct or CsEnum)
            {
                var returnQualifiedName = returnValue.PublicType.QualifiedName;

                if (returnTypeOverrides.TryGetValue(returnQualifiedName, out var interopType))
                {
                    flags |= interopType.SetFlags;
                    return(interopType.NewType);
                }

                if (platformSpecificReturnTypeOverrides.TryGetValue(returnQualifiedName, out interopType))
                {
                    flags |= interopType.SetFlags;
                    return(interopType.NewType);
                }

                return(returnValue.HasNativeValueType
                           ? $"{returnValue.MarshalType.QualifiedName}.__Native"
                           : returnValue.MarshalType.QualifiedName);
            }

            if (returnValue.MarshalType is CsFundamentalType fundamentalReturn)
            {
                return(fundamentalReturn);
            }

            if (returnValue.HasPointer)
            {
                return(returnValue.IsInterface ? TypeRegistry.IntPtr : TypeRegistry.VoidPtr);
            }

            return(null);
        }
Exemplo n.º 9
0
        public static string GetPlatformSpecificSuffix(PlatformDetectionType platform)
        {
            if (platform == PlatformDetectionType.Any)
            {
                return("_");
            }

            StringBuilder str = new StringBuilder("_");

            foreach (PlatformDetectionType flag in platforms)
            {
                if ((platform & flag) == flag && flag != PlatformDetectionType.Any)
                {
                    str.Append(flag);
                    str.Append('_');
                }
            }
            return(str.ToString());
        }
    public override IEnumerable <MemberDeclarationSyntax> GenerateCode(
        CsFunction csElement, PlatformDetectionType platform)
    {
        var sig = csElement.InteropSignatures[platform];

        yield return(MethodDeclaration(
                         sig.ReturnTypeSyntax,
                         $"{csElement.CppElementName}{GeneratorHelpers.GetPlatformSpecificSuffix(platform)}"
                         )
                     .WithModifiers(ModifierList)
                     .WithAttributeLists(
                         SingletonList(
                             AttributeList(
                                 SingletonSeparatedList(
                                     Attribute(
                                         DllImportName)
                                     .WithArgumentList(
                                         AttributeArgumentList(
                                             SeparatedList(
                                                 new[]
        {
            AttributeArgument(IdentifierName(csElement.DllName)),
            AttributeArgument(
                LiteralExpression(
                    SyntaxKind.StringLiteralExpression,
                    Literal(csElement.CppElementName)))
            .WithNameEquals(
                NameEquals(IdentifierName("EntryPoint"))),
            AttributeArgument(
                ModelUtilities
                .GetManagedCallingConventionExpression(
                    csElement.CppCallingConvention))
            .WithNameEquals(
                NameEquals(IdentifierName("CallingConvention")))
        })))))))
                     .WithParameterList(
                         ParameterList(
                             SeparatedList(
                                 sig.ParameterTypes.Select(
                                     param => Parameter(Identifier(param.Name))
                                     .WithType(param.InteropTypeSyntax)))))
                     .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
    }
        private void InitSignatureWithReturnType(CsCallable callable,
                                                 InteropMethodSignature cSharpInteropCalliSignature,
                                                 PlatformDetectionType platform)
        {
            InteropMethodSignatureFlags flags = default;

            var returnType = GetInteropTypeForReturnValue(callable.ReturnValue, platform, ref flags);

            if (returnType == null)
            {
                logger.Error(LoggingCodes.InvalidMethodReturnType, "Invalid return type {0} for method {1}",
                             callable.ReturnValue.PublicType.QualifiedName, callable.CppElement);
                returnType = callable.ReturnValue.PublicType.QualifiedName;
            }

            if (flags != default)
            {
                cSharpInteropCalliSignature.Flags |= flags;
            }

            cSharpInteropCalliSignature.ReturnType = returnType;
        }
Exemplo n.º 12
0
        public static string GetPlatformSpecificSuffix(PlatformDetectionType platform)
        {
            if (platform == PlatformDetectionType.Any)
            {
                return("_");
            }

            StringBuilder str = new("_", PlatformsNoAnyStringLength);

            foreach (var flag in PlatformsNoAny)
            {
                if ((platform & flag) != flag)
                {
                    continue;
                }

                str.Append(flag);
                str.Append('_');
            }

            return(str.ToString());
        }
Exemplo n.º 13
0
 private DelegateDeclarationSyntax GenerateDelegateDeclaration(CsCallable csElement, PlatformDetectionType platform, InteropMethodSignature sig)
 {
     return(DelegateDeclaration(ParseTypeName(sig.ReturnType.TypeName), VtblGenerator.GetMethodDelegateName(csElement, platform))
            .AddAttributeLists(
                AttributeList(
                    SingletonSeparatedList(
                        Attribute(
                            ParseName("System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"))
                        .AddArgumentListArguments(
                            AttributeArgument(
                                MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    MemberAccessExpression(
                                        SyntaxKind.SimpleMemberAccessExpression,
                                        MemberAccessExpression(
                                            SyntaxKind.SimpleMemberAccessExpression,
                                            MemberAccessExpression(
                                                SyntaxKind.SimpleMemberAccessExpression,
                                                IdentifierName("System"),
                                                IdentifierName("Runtime")),
                                            IdentifierName("InteropServices")),
                                        IdentifierName("CallingConvention")),
                                    IdentifierName(sig.CallingConvention.ToManagedCallingConventionName())))))))
            .WithParameterList(
                ParameterList(
                    (csElement is CsMethod ?
                     SingletonSeparatedList(
                         Parameter(Identifier("thisObject"))
                         .WithType(ParseTypeName("System.IntPtr")))
                 : default)
 public abstract StatementSyntax GenerateCode(T csElement, PlatformDetectionType platform);
Exemplo n.º 15
0
        public override bool Execute()
        {
            var documentationFiles = new Dictionary <string, XmlDocument>();

            foreach (var file in ExternalDocumentation ?? Enumerable.Empty <ITaskItem>())
            {
                using (var stream = File.OpenRead(file.ItemSpec))
                {
                    var xml = new XmlDocument();
                    xml.Load(stream);
                    documentationFiles.Add(file.ItemSpec, xml);
                }
            }

            var globalNamespace = new GlobalNamespaceProvider();

            foreach (var nameOverride in GlobalNamespaceOverrides ?? Enumerable.Empty <ITaskItem>())
            {
                var wellKnownName = nameOverride.ItemSpec;
                var overridenName = nameOverride.GetMetadata("Override");
                if (overridenName != null && Enum.TryParse(wellKnownName, out WellKnownName name))
                {
                    globalNamespace.OverrideName(name, overridenName);
                }
            }

            PlatformDetectionType platformMask = 0;

            foreach (var platform in Platforms ?? Enumerable.Empty <ITaskItem>())
            {
                if (!Enum.TryParse <PlatformDetectionType>("Is" + platform.ItemSpec, out var parsedPlatform))
                {
                    Log.LogWarning(null, LoggingCodes.InvalidPlatformDetectionType, null, null, 0, 0, 0, 0, $"The platform type {platform} is an unknown platform to SharpGenTools. Falling back to Any platform detection.");
                    platformMask = PlatformDetectionType.Any;
                }
                else
                {
                    platformMask |= parsedPlatform;
                }
            }

            if (platformMask == 0)
            {
                platformMask = PlatformDetectionType.Any;
            }

            var config = new GeneratorConfig
            {
                Platforms = platformMask
            };

            var generator = new RoslynGenerator(
                new Logger(new MSBuildSharpGenLogger(Log), null),
                globalNamespace,
                new CachedDocumentationLinker(DocLinkCache.ItemSpec),
                new ExternalDocCommentsReader(documentationFiles),
                config);

            generator.Run(CsAssembly.Read(Model.ItemSpec), GeneratedCodeFolder);

            return(true);
        }
Exemplo n.º 16
0
 public abstract MemberDeclarationSyntax GenerateCode(T csElement, PlatformDetectionType platform);
Exemplo n.º 17
0
 public abstract IEnumerable <StatementSyntax> GenerateCode(T csElement, PlatformDetectionType platform);
Exemplo n.º 18
0
    protected override ExpressionSyntax Generate(CsCallable callable, PlatformDetectionType platform)
    {
        var interopSig        = callable.InteropSignatures[platform];
        var interopReturnType = interopSig.ReturnTypeSyntax;
        var arguments         = IterateNativeArguments(callable is CsMethod, interopSig).ToArray();

        var vtblAccess = callable switch
        {
            CsMethod method => ElementAccessExpression(
                ThisExpression(),
                BracketedArgumentList(
                    SingletonSeparatedList(
                        Argument(
                            method.CustomVtbl
                                ? MemberAccessExpression(
                                SyntaxKind.SimpleMemberAccessExpression,
                                ThisExpression(),
                                IdentifierName($"{callable.Name}__vtbl_index")
                                )
                                : method.VTableOffsetExpression(platform)
                            )
                        )
                    )
                ),
            _ => null
        };

        ExpressionSyntax FnPtrCall()
        {
            var fnptrParameters = arguments
                                  .Select(x => x.Type)
                                  .Append(interopReturnType)
                                  .Select(FunctionPointerParameter);

            return(GeneratorHelpers.CastExpression(
                       FunctionPointerType(
                           FunctionPointerCallingConvention(
                               Token(SyntaxKind.UnmanagedKeyword),
                               FunctionPointerUnmanagedCallingConventionList(
                                   SingletonSeparatedList(
                                       FunctionPointerUnmanagedCallingConvention(
                                           Identifier(callable.CppCallingConvention.ToCallConvShortName())
                                           )
                                       )
                                   )
                               ),
                           FunctionPointerParameterList(SeparatedList(fnptrParameters))
                           ),
                       vtblAccess
                       ));
        }

        var what = callable switch
        {
            CsFunction => IdentifierName(
                callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform)
                ),
            CsMethod => GeneratorHelpers.WrapInParentheses(FnPtrCall()),
            _ => throw new ArgumentOutOfRangeException()
        };

        ExpressionSyntax call = InvocationExpression(
            what,
            ArgumentList(SeparatedList(arguments.Select(x => x.Argument)))
            );

        if (interopSig.ForcedReturnBufferSig || !callable.HasReturnType)
        {
            return(call);
        }

        var generatesMarshalVariable = GetMarshaller(callable.ReturnValue).GeneratesMarshalVariable(callable.ReturnValue);
        var publicTypeSyntax         = ReverseCallablePrologCodeGenerator.GetPublicType(callable.ReturnValue);

        if (callable.HasReturnTypeValue && !generatesMarshalVariable && !publicTypeSyntax.IsEquivalentTo(interopSig.ReturnTypeSyntax))
        {
            call = CastExpression(publicTypeSyntax, call);
        }

        return(AssignmentExpression(
                   SyntaxKind.SimpleAssignmentExpression,
                   generatesMarshalVariable
                ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue)
                : IdentifierName(callable.ReturnValue.Name),
                   call
                   ));
    }
Exemplo n.º 19
0
        private static StatementSyntax PlatformSpecificStatement(GlobalNamespaceProvider globalNamespace, PlatformDetectionType allPlatformBitmap, PlatformDetectionType platform, StatementSyntax statement)
        {
            if ((platform & allPlatformBitmap) == allPlatformBitmap)
            {
                return(statement);
            }

            ExpressionSyntax condition = null;

            foreach (PlatformDetectionType flag in platforms)
            {
                if ((platform & flag) == flag && flag != PlatformDetectionType.Any)
                {
                    var newCondition = MemberAccessExpression(
                        Microsoft.CodeAnalysis.CSharp.SyntaxKind.SimpleMemberAccessExpression,
                        globalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection),
                        IdentifierName(flag.ToString()));
                    condition = condition is null ?
                                (ExpressionSyntax)newCondition
                        : BinaryExpression(Microsoft.CodeAnalysis.CSharp.SyntaxKind.LogicalAndExpression,
                                           condition,
                                           newCondition);
                }
            }

            return(condition is null ?
                   statement
                : IfStatement(
                       condition,
                       statement));
        }
Exemplo n.º 20
0
        public ExpressionSyntax GenerateCall(CsCallable callable, PlatformDetectionType platform,
                                             InteropMethodSignature interopSig)
        {
            var arguments = IterateNativeArguments(callable, interopSig).ToArray();

            ElementAccessExpressionSyntax vtblAccess = null;

            if (callable is CsMethod method)
            {
                var windowsOffsetExpression =
                    LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.WindowsOffset));
                var nonWindowsOffsetExpression =
                    LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.Offset));

                ExpressionSyntax vtableOffsetExpression;
                if ((platform & PlatformDetectionType.Any) == PlatformDetectionType.Any &&
                    method.Offset != method.WindowsOffset)
                {
                    vtableOffsetExpression = ConditionalExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            GlobalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection),
                            IdentifierName("Is" + nameof(PlatformDetectionType.Windows))),
                        windowsOffsetExpression,
                        nonWindowsOffsetExpression);
                }
                else if ((platform & PlatformDetectionType.Windows) != 0)
                {
                    vtableOffsetExpression = windowsOffsetExpression;
                }
                else
                {
                    vtableOffsetExpression = nonWindowsOffsetExpression;
                }

                vtblAccess = ElementAccessExpression(
                    ThisExpression(),
                    BracketedArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                method.CustomVtbl
                                    ? MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    ThisExpression(),
                                    IdentifierName($"{callable.Name}__vtbl_index")
                                    )
                                    : vtableOffsetExpression
                                )
                            )
                        )
                    );
            }

            ExpressionSyntax FnPtrCall()
            {
                var fnptrParameters = arguments
                                      .Select(x => x.Type)
                                      .Append(ParseTypeName(interopSig.ReturnType.TypeName))
                                      .Select(FunctionPointerParameter);

                return(GeneratorHelpers.CastExpression(
                           FunctionPointerType(
                               FunctionPointerCallingConvention(
                                   Token(SyntaxKind.UnmanagedKeyword),
                                   FunctionPointerUnmanagedCallingConventionList(
                                       SingletonSeparatedList(
                                           FunctionPointerUnmanagedCallingConvention(
                                               Identifier(callable.CppCallingConvention.ToCallConvShortName())
                                               )
                                           )
                                       )
                                   ),
                               FunctionPointerParameterList(SeparatedList(fnptrParameters))
                               ),
                           vtblAccess
                           ));
            }

            var what = callable switch
            {
                CsFunction => IdentifierName(
                    callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform)
                    ),
                CsMethod => GeneratorHelpers.WrapInParentheses(FnPtrCall()),
                _ => throw new ArgumentOutOfRangeException()
            };

            ExpressionSyntax call = InvocationExpression(
                what,
                ArgumentList(SeparatedList(arguments.Select(x => x.Argument)))
                );

            if (interopSig.CastToNativeLong)
            {
                call = CastExpression(GlobalNamespace.GetTypeNameSyntax(WellKnownName.NativeLong), call);
            }

            if (interopSig.CastToNativeULong)
            {
                call = CastExpression(GlobalNamespace.GetTypeNameSyntax(WellKnownName.NativeULong), call);
            }

            if (interopSig.ForcedReturnBufferSig || !callable.HasReturnType)
            {
                return(call);
            }

            return(AssignmentExpression(
                       SyntaxKind.SimpleAssignmentExpression,
                       GetMarshaller(callable.ReturnValue).GeneratesMarshalVariable(callable.ReturnValue)
                    ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue)
                    : IdentifierName(callable.ReturnValue.Name),
                       call
                       ));
        }
        private void InitSignatureWithReturnType(CsCallable callable, InteropMethodSignature cSharpInteropCalliSignature, PlatformDetectionType platform)
        {
            Debug.Assert((platform & (PlatformDetectionType.IsWindows | PlatformDetectionType.IsItaniumSystemV)) != (PlatformDetectionType.IsWindows | PlatformDetectionType.IsItaniumSystemV) || !callable.IsReturnStructLarge);
            var platformSpecificReturnTypeOverrides = (platform & PlatformDetectionType.IsWindows) != 0
                ? windowsOnlyReturnTypeOverrides
                : systemvOnlyReturnTypeOverrides;

            // Handle Return Type parameter
            // MarshalType.Type == null, then check that it is a structure
            if (callable.ReturnValue.PublicType is CsStruct || callable.ReturnValue.PublicType is CsEnum)
            {
                var returnQualifiedName = callable.ReturnValue.PublicType.QualifiedName;
                if (returnTypeOverrides.TryGetValue(returnQualifiedName, out var interopType))
                {
                    cSharpInteropCalliSignature.ReturnType = interopType;
                }
                else if (platformSpecificReturnTypeOverrides.TryGetValue(returnQualifiedName, out interopType))
                {
                    cSharpInteropCalliSignature.ReturnType = interopType;
                }
                else if (callable.ReturnValue.HasNativeValueType)
                {
                    cSharpInteropCalliSignature.ReturnType = $"{callable.ReturnValue.MarshalType.QualifiedName}.__Native";
                }
                else
                {
                    cSharpInteropCalliSignature.ReturnType = callable.ReturnValue.MarshalType.QualifiedName;
                }
            }
            else if (callable.ReturnValue.MarshalType is CsFundamentalType fundamentalReturn)
            {
                cSharpInteropCalliSignature.ReturnType = fundamentalReturn.Type;
            }
            else if (callable.ReturnValue.HasPointer)
            {
                if (callable.ReturnValue.IsInterface)
                {
                    cSharpInteropCalliSignature.ReturnType = typeof(IntPtr);
                }
                else
                {
                    cSharpInteropCalliSignature.ReturnType = typeof(void *);
                }
            }
            else
            {
                cSharpInteropCalliSignature.ReturnType = callable.ReturnValue.PublicType.QualifiedName;
                logger.Error(LoggingCodes.InvalidMethodReturnType, "Invalid return type {0} for method {1}", callable.ReturnValue.PublicType.QualifiedName, callable.CppElement);
            }
        }
 public abstract IEnumerable <MemberDeclarationSyntax> GenerateCode(T csElement, PlatformDetectionType platform);
Exemplo n.º 23
0
 StatementSyntax IPlatformSingleCodeGenerator <T, StatementSyntax> .GenerateCode(
     T csElement, PlatformDetectionType platform
     ) => Generate(csElement, platform) is
 {
Exemplo n.º 24
0
 protected abstract IEnumerable <ExpressionSyntax> Generate(T csElement, PlatformDetectionType platform);
Exemplo n.º 25
0
 IEnumerable <StatementSyntax> IPlatformMultiCodeGenerator <T, StatementSyntax> .GenerateCode(
     T csElement, PlatformDetectionType platform
     ) => Generate(csElement, platform)
 .Where(static x => x != null)
Exemplo n.º 26
0
        private bool Execute(ConfigFile config)
        {
            config.GetFilesWithIncludesAndExtensionHeaders(
                out var configsWithHeaders,
                out var configsWithExtensionHeaders
                );

            var cppHeaderGenerator = new CppHeaderGenerator(SharpGenLogger, OutputPath);

            var cppHeaderGenerationResult = cppHeaderGenerator.GenerateCppHeaders(config, configsWithHeaders, configsWithExtensionHeaders);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var resolver = new IncludeDirectoryResolver(SharpGenLogger);

            resolver.Configure(config);

            var castXml = new CastXmlRunner(SharpGenLogger, resolver, CastXmlExecutable.ItemSpec, CastXmlArguments)
            {
                OutputPath = OutputPath
            };

            var macroManager = new MacroManager(castXml);

            var cppExtensionGenerator = new CppExtensionHeaderGenerator();

            var module = config.CreateSkeletonModule();

            macroManager.Parse(Path.Combine(OutputPath, config.HeaderFileName), module);

            cppExtensionGenerator.GenerateExtensionHeaders(
                config, OutputPath, module, configsWithExtensionHeaders, cppHeaderGenerationResult.UpdatedConfigs
                );

            GenerateInputsCache(
                macroManager.IncludedFiles
                .Concat(config.ConfigFilesLoaded.Select(x => x.AbsoluteFilePath))
                .Concat(configsWithExtensionHeaders.Select(x => Path.Combine(OutputPath, x.ExtensionFileName)))
                .Select(s => Utilities.FixFilePath(s, Utilities.EmptyFilePathBehavior.Ignore))
                .Where(x => x != null)
                .Distinct()
                );

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            // Run the parser
            var parser = new CppParser(SharpGenLogger, config)
            {
                OutputPath = OutputPath
            };

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            CppModule group;

            using (var xmlReader = castXml.Process(parser.RootConfigHeaderFileName))
            {
                // Run the C++ parser
                group = parser.Run(module, xmlReader);
            }

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            config.ExpandDynamicVariables(SharpGenLogger, group);

            var docLinker    = new DocumentationLinker();
            var typeRegistry = new TypeRegistry(SharpGenLogger, docLinker);
            var namingRules  = new NamingRulesManager();

            var globalNamespace = new GlobalNamespaceProvider();

            foreach (var nameOverride in GlobalNamespaceOverrides)
            {
                var wellKnownName = nameOverride.ItemSpec;
                var overridenName = nameOverride.GetMetadata("Override");

                if (string.IsNullOrEmpty(overridenName))
                {
                    continue;
                }

                if (Enum.TryParse(wellKnownName, out WellKnownName name))
                {
                    globalNamespace.OverrideName(name, overridenName);
                }
                else
                {
                    SharpGenLogger.Warning(
                        LoggingCodes.InvalidGlobalNamespaceOverride,
                        "Invalid override of \"{0}\": unknown class name, ignoring the override.",
                        wellKnownName
                        );
                }
            }

            // Run the main mapping process
            var transformer = new TransformManager(
                globalNamespace,
                namingRules,
                SharpGenLogger,
                typeRegistry,
                docLinker,
                new ConstantManager(namingRules, docLinker)
                );

            var(solution, defines) = transformer.Transform(group, config);

            var consumerConfig = new ConfigFile
            {
                Id            = ConsumerBindMappingConfigId,
                IncludeProlog = { cppHeaderGenerationResult.Prologue },
                Extension     = new List <ExtensionBaseRule>(defines)
            };

            var(bindings, generatedDefines) = transformer.GenerateTypeBindingsForConsumers();

            consumerConfig.Bindings.AddRange(bindings);
            consumerConfig.Extension.AddRange(generatedDefines);

            consumerConfig.Mappings.AddRange(
                docLinker.GetAllDocLinks().Select(
                    link => new MappingRule
            {
                DocItem          = link.cppName,
                MappingNameFinal = link.cSharpName
            }
                    )
                );

            GenerateConfigForConsumers(consumerConfig);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var documentationCacheItemSpec = DocumentationCache.ItemSpec;

            Utilities.RequireAbsolutePath(documentationCacheItemSpec, nameof(DocumentationCache));

            var cache = File.Exists(documentationCacheItemSpec)
                            ? DocItemCache.Read(documentationCacheItemSpec)
                            : new DocItemCache();

            DocumentationLogger docLogger = new(SharpGenLogger) { MaxLevel = LogLevel.Warning };
            var docContext = new Lazy <DocumentationContext>(() => new DocumentationContext(docLogger));

            ExtensibilityDriver.Instance.DocumentModule(SharpGenLogger, cache, solution, docContext).Wait();

            if (docContext.IsValueCreated)
            {
                Regex[] silencePatterns    = null;
                var     docLogLevelDefault = DocumentationFailuresAsErrors ? LogLevel.Error : LogLevel.Warning;

                foreach (var queryFailure in docContext.Value.Failures)
                {
                    if (silencePatterns == null)
                    {
                        silencePatterns = new Regex[SilenceMissingDocumentationErrorIdentifierPatterns.Length];
                        for (var i = 0; i < silencePatterns.Length; i++)
                        {
                            silencePatterns[i] = new Regex(
                                SilenceMissingDocumentationErrorIdentifierPatterns[i].ItemSpec,
                                RegexOptions.CultureInvariant
                                );
                        }
                    }

                    if (silencePatterns.Length != 0)
                    {
                        bool SilencePredicate(Regex x) => x.Match(queryFailure.Query).Success;

                        if (silencePatterns.Any(SilencePredicate))
                        {
                            continue;
                        }
                    }

                    var providerName = queryFailure.FailedProviderName ?? "<null>";

                    var docLogLevel = queryFailure.TreatProviderFailuresAsErrors
                                          ? docLogLevelDefault
                                          : docLogLevelDefault > LogLevel.Warning
                                              ? LogLevel.Warning
                                              : docLogLevelDefault;

                    if (queryFailure.Exceptions == null || queryFailure.Exceptions.Count <= 1)
                    {
                        SharpGenLogger.LogRawMessage(
                            docLogLevel,
                            LoggingCodes.DocumentationProviderInternalError,
                            "Documentation provider [{0}] query for \"{1}\" failed.",
                            queryFailure.Exceptions?.FirstOrDefault(),
                            providerName,
                            queryFailure.Query
                            );
                    }
                    else
                    {
                        var exceptionsCount = queryFailure.Exceptions.Count;
                        for (var index = 0; index < exceptionsCount; index++)
                        {
                            var exception = queryFailure.Exceptions[index];

                            SharpGenLogger.LogRawMessage(
                                docLogLevel,
                                LoggingCodes.DocumentationProviderInternalError,
                                "Documentation provider [{0}] query for \"{1}\" failed ({2}/{3}).",
                                exception,
                                providerName,
                                queryFailure.Query,
                                index + 1,
                                exceptionsCount
                                );
                        }
                    }
                }
            }

            cache.WriteIfDirty(documentationCacheItemSpec);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var documentationFiles = new Dictionary <string, XmlDocument>();

            foreach (var file in ExternalDocumentation)
            {
                using var stream = File.OpenRead(file.ItemSpec);

                var xml = new XmlDocument();
                xml.Load(stream);
                documentationFiles.Add(file.ItemSpec, xml);
            }

            PlatformDetectionType platformMask = 0;

            foreach (var platform in Platforms)
            {
                if (!Enum.TryParse <PlatformDetectionType>(platform.ItemSpec, out var parsedPlatform))
                {
                    SharpGenLogger.Warning(
                        LoggingCodes.InvalidPlatformDetectionType,
                        "The platform type {0} is an unknown platform to SharpGenTools. Falling back to Any platform detection.",
                        platform
                        );
                    platformMask = PlatformDetectionType.Any;
                }
                else
                {
                    platformMask |= parsedPlatform;
                }
            }

            if (platformMask == 0)
            {
                platformMask = PlatformDetectionType.Any;
            }

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var generator = new RoslynGenerator(
                SharpGenLogger,
                globalNamespace,
                docLinker,
                new ExternalDocCommentsReader(documentationFiles),
                new GeneratorConfig
            {
                Platforms = platformMask
            }
                );

            generator.Run(solution, GeneratedCodeFolder);

            return(!SharpGenLogger.HasErrors);
        }
Exemplo n.º 27
0
 IEnumerable <ExpressionSyntax> IPlatformMultiCodeGenerator <T, ExpressionSyntax> .GenerateCode(
     T csElement, PlatformDetectionType platform
     ) => Generate(csElement, platform);
Exemplo n.º 28
0
 private FieldDeclarationSyntax DelegateCacheDecl(CsMethod method, PlatformDetectionType platform) =>
 FieldDeclaration(
     default, TokenList(
Exemplo n.º 29
0
 internal static string GetMethodDelegateName(CsCallable csElement, PlatformDetectionType platform) =>
 csElement.Name + "Delegate" + GeneratorHelpers.GetPlatformSpecificSuffix(platform);
Exemplo n.º 30
0
 ExpressionSyntax IPlatformSingleCodeGenerator <T, ExpressionSyntax> .GenerateCode(
     T csElement, PlatformDetectionType platform
     ) => Generate(csElement, platform);