public FunctionBuilder(AdhocWorkspace workspace, ProjectId projectId, string directory, TypeMap typeMap) : base(workspace, projectId, directory, typeMap)
 {
 }
        private IEnumerable <StatementSyntax> BuildDelegateBody(CppFunction cppFunction, TypeInfo returnTypeInfo)
        {
            yield return(SyntaxBuilder.DeclareLocals(false));

            var delegates = new Dictionary <string, string>();

            foreach (var cppParameter in cppFunction.Parameters)
            {
                if (!TypeMap.TryResolveType(cppParameter.Type, out var paramTypeInfo, false))
                {
                    throw new ArgumentException();
                }

                if (!paramTypeInfo.IsFunction)
                {
                    continue;
                }

                var managedParameterName = GetManagedName(cppParameter.Name);
                var variableName         = managedParameterName + "Ptr";
                delegates.Add(cppParameter.Name, variableName);
                yield return(SyntaxBuilder.DeclareDelegatePointerVariable(managedParameterName, variableName));
            }

            var call =
                InvocationExpression(IdentifierName(GetManagedName(cppFunction.Name) + "Private"))
                .AddArgumentListArguments(cppFunction.Parameters.Select(BuildArgument).ToArray());

            if (returnTypeInfo.IsVoid)
            {
                yield return(ExpressionStatement(call));
            }
            else
            {
                yield return(LocalDeclarationStatement(
                                 VariableDeclaration(returnTypeInfo.TypeSyntax)
                                 .AddVariables(VariableDeclarator("result").WithInitializer(
                                                   EqualsValueClause(call)))));
            }

            foreach (var cppParameter in cppFunction.Parameters.Reverse())
            {
                if (delegates.ContainsKey(cppParameter.Name))
                {
                    var managedParameterName = GetManagedName(cppParameter.Name);
                    yield return(SyntaxBuilder.CallKeepAlive(IdentifierName(managedParameterName)));
                }
            }

            if (!returnTypeInfo.IsVoid)
            {
                yield return(ReturnStatement(IdentifierName("result")));
            }

            ArgumentSyntax BuildArgument(CppParameter cppParameter)
            {
                var name = delegates.TryGetValue(cppParameter.Name, out string paramName)
                    ? paramName
                    : GetManagedName(cppParameter.Name);

                return(Argument(IdentifierName(name)));
            }
        }
Beispiel #3
0
        private async Task <int> OnExecuteAsync(CommandLineApplication app,
                                                CancellationToken cancellationToken = default)
        {
            var outputDir = Path.IsPathFullyQualified(OutputProjectDir)
                ? OutputProjectDir
                : Path.GetFullPath(OutputProjectDir);

            Directory.CreateDirectory(outputDir);

            var workspace   = new AdhocWorkspace();
            var projectId   = ProjectId.CreateNewId();
            var projectInfo = ProjectInfo.Create(projectId, VersionStamp.Create(), "XP.SDK", "XP.SDK", LanguageNames.CSharp)
                              .WithDefaultNamespace("XP.SDK");
            var project = workspace.AddProject(projectInfo);

            var typeMap = new TypeMap(BuildTypeCallback);

            _enumBuilder = new EnumBuilder(workspace, projectId, outputDir, typeMap)
                           .Map("xpMainWindowStyle_MainWindow", "MainWindowType")
                           .Map("xpProperty_MainWindowType", "MainWindowProperty")
                           .Map("xpMessage_CloseButtonPushed", "MainWindowMessage")
                           .Map("xpSubWindowStyle_SubWindow", "SubWindowType")
                           .Map("xpProperty_SubWindowType", "SubWindowProperty")
                           .Map("xpPushButton", "ButtonType")
                           .Map("xpButtonBehaviorPushButton", "ButtonBehavior")
                           .Map("xpProperty_ButtonType", "ButtonProperty")
                           .Map("xpMsg_PushButtonPressed", "ButtonMessage")
                           .Map("xpTextEntryField", "TextFieldType")
                           .Map("xpProperty_EditFieldSelStart", "TextFieldProperty")
                           .Map("xpMsg_TextFieldChanged", "TextFieldMessage")
                           .Map("xpScrollBarTypeScrollBar", "ScrollBarType")
                           .Map("xpProperty_ScrollBarSliderPosition", "ScrollBarProperty")
                           .Map("xpMsg_ScrollBarSliderPositionChanged", "ScrollBarMessage")
                           .Map("xpProperty_CaptionLit", "CaptionProperty")
                           .Map("xpShip", "GeneralGraphicsType")
                           .Map("xpProperty_GeneralGraphicsType", "GeneralGraphicsProperty")
                           .Map("xpProperty_ProgressPosition", "ProgressBarProperty");
            _handleBuilder   = new HandleBuilder(workspace, projectId, outputDir, typeMap);
            _delegateBuilder = new DelegateBuilder(workspace, projectId, outputDir, typeMap);
            _structBuilder   = new StructBuilder(workspace, projectId, outputDir, typeMap);
            var functionBuilder = new FunctionBuilder(workspace, projectId, outputDir, typeMap);

            var xplmHeadersPath = Path.Combine(SdkRoot, "CHeaders", "XPLM");

            if (!Directory.Exists(xplmHeadersPath))
            {
                throw new DirectoryNotFoundException($"Directory '{xplmHeadersPath}' does not exist.");
            }
            var xmplHeaders = Directory.EnumerateFiles(xplmHeadersPath, "*.h");

            var xpWidgetsHeadersPath = Path.Combine(SdkRoot, "CHeaders", "Widgets");

            if (!Directory.Exists(xpWidgetsHeadersPath))
            {
                throw new DirectoryNotFoundException($"Directory '{xpWidgetsHeadersPath}' does not exist.");
            }
            var xpWidgetsHeaders = Directory.EnumerateFiles(xpWidgetsHeadersPath, "*.h");
            var headers          = xmplHeaders.Concat(xpWidgetsHeaders)
                                   /*.Where(x => Path.GetFileName(x) != "XPStandardWidgets.h")*/;

            var parserOptions = new CppParserOptions
            {
                Defines             = { "IBM", "XPLM303", "XPLM302", "XPLM301", "XPLM300", "XPLM210", "XPLM200" },
                ParseSystemIncludes = false,
                TargetCpu           = CppTargetCpu.X86_64,
                IncludeFolders      = { xplmHeadersPath },
            };


            var compilation = CppParser.ParseFiles(headers.ToList(), parserOptions);

            foreach (var child in compilation.Children().OfType <CppType>())
            {
                await BuildTypeAsync(child);
            }

            var functionsByHeader = compilation
                                    .Functions
                                    .ToLookup(x => x.Span.Start.File);

            foreach (var functionsInHeader in functionsByHeader)
            {
                await functionBuilder.BuildAsync(functionsInHeader);
            }

            foreach (var document in workspace.CurrentSolution.Projects.SelectMany(p => p.Documents))
            {
                var text = await document.GetTextAsync(cancellationToken);

                await using var writer = new StreamWriter(document.FilePath, false);
                text.Write(writer, cancellationToken);
            }

            return(0);

            async Task BuildTypeCallback(dynamic item)
            {
                using (Log.PushIdent())
                {
                    await BuildTypeAsync(item);
                }
            }
        }