Ejemplo n.º 1
0
        public static bool CompileCSharpFromJass(
            string filePath,
            string assemblyName,
            string namespaceName,
            string className,
            MetadataReference[] metadataReferences,
            UsingDirectiveSyntax[] usingDirectives,
            out MetadataReference outReference,
            out UsingDirectiveSyntax outDirective,
            out EmitResult emitResult,
            OutputKind outputKind,
            bool applyNativeMemberAttributes = false,
            string outputSource   = null,
            string outputEmit     = null,
            string outputLuaTypes = null)
        {
            var directiveName = $"{namespaceName}.{className}";

            outDirective = SyntaxFactory.UsingDirective(SyntaxFactory.Token(SyntaxKind.StaticKeyword), null, SyntaxFactory.ParseName(directiveName));

            if (outputLuaTypes != null)
            {
                // These two are incompatible, because enums can't freely inherit from other types (example: igamestate and fgamestate enums inherit from gamestate).
                TranspileToEnumHandler.Reset();
            }

            var fileSyntax = JassParser.ParseFile(filePath);

            if (outputLuaTypes != null)
            {
                // Output lua source code for JASS type definitions.
                TranspileTypesToLua(fileSyntax, $"{namespaceName}{className}", outputLuaTypes);
            }

            var compilationUnit = Transpile(
                fileSyntax,
                namespaceName,
                className,
                applyNativeMemberAttributes,
                usingDirectives).NormalizeWhitespace();

            if (outputSource != null)
            {
                new FileInfo(outputSource).Directory.Create();

                // Output C# source code.
#pragma warning disable CA2000 // Dispose objects before losing scope
                CompilationHelper.SerializeTo(compilationUnit, File.OpenWrite(outputSource), false);
#pragma warning restore CA2000 // Dispose objects before losing scope
            }

            var compilation = CompilationHelper.PrepareCompilation(
                compilationUnit,
                outputKind,
                assemblyName ?? directiveName,
                metadataReferences);

            if (outputEmit is null)
            {
                var peStream = new MemoryStream();
                emitResult = compilation.Emit(peStream, options: new EmitOptions(metadataOnly: true)); // TODO: set metadataOnly to applyNativeMemberAttributes?
                peStream.Seek(0, SeekOrigin.Begin);

                if (emitResult.Success)
                {
                    outReference = MetadataReference.CreateFromStream(peStream);
                    return(true);
                }

                peStream.Dispose();
            }
            else
            {
                new FileInfo(outputEmit).Directory.Create();

                // Output .dll file.
                emitResult = compilation.Emit(outputEmit);

                if (emitResult.Success)
                {
                    outReference = MetadataReference.CreateFromFile(outputEmit);
                    return(true);
                }
            }

            outReference = null;
            return(false);
        }
Ejemplo n.º 2
0
        public static bool GetReferencesAndUsingDirectives(
            out MetadataReference[] metadataReferences,
            out UsingDirectiveSyntax[] usingDirectives,
            out EmitResult emitResult,
            bool referenceCommon,
            bool referenceBlizzard)
        {
            if (!referenceCommon && referenceBlizzard)
            {
                throw new ArgumentException("Referencing Blizzard.j requires that common.j is also referenced.");
            }

            metadataReferences = GetBasicReferences().ToArray();
            usingDirectives    = null;

            if (referenceCommon)
            {
                const string ApiNamespaceName  = "War3Api";
                const string CommonClassName   = "Common";
                const string BlizzardClassName = "Blizzard";

                var cSharpDirective = GetCSharpDirective();

                if (!referenceBlizzard)
                {
                    TranspileToEnumHandler.DefineEnumTypes(CommonEnumTypesProvider.GetEnumTypes());
                }

                if (!CompileCSharpFromJass(
                        @"JassApi\common.j",
                        null,
                        ApiNamespaceName,
                        CommonClassName,
                        metadataReferences,
                        new[] { cSharpDirective },
                        out var commonReference,
                        out var commonDirective,
                        out emitResult,
                        OutputKind.DynamicallyLinkedLibrary,
                        true,
                        null,
                        null,
                        null))
                {
                    return(false);
                }

                metadataReferences = metadataReferences.Append(commonReference).ToArray();

                if (referenceBlizzard)
                {
                    if (!CompileCSharpFromJass(
                            @"JassApi\Blizzard.j",
                            null,
                            ApiNamespaceName,
                            BlizzardClassName,
                            metadataReferences,
                            new[] { cSharpDirective, commonDirective },
                            out var blizzardReference,
                            out var blizzardDirective,
                            out emitResult,
                            OutputKind.DynamicallyLinkedLibrary,
                            true,
                            null,
                            null,
                            null))
                    {
                        return(false);
                    }

                    metadataReferences = metadataReferences.Append(blizzardReference).ToArray();

                    usingDirectives = new[] { commonDirective, blizzardDirective };
                    return(true);
                }

                usingDirectives = new[] { commonDirective };
                return(true);
            }

            usingDirectives = Array.Empty <UsingDirectiveSyntax>();
            emitResult      = null;
            return(true);
        }