Beispiel #1
0
        static void Demo4(CodeCompileUnit ccu)
        {
            // create one of these lil guys
            var res = new CodeDomResolver();

            // add our code to it
            res.CompileUnits.Add(ccu);
            // give it a chance to build its information over our code
            res.Refresh();
            CodeDomVisitor.Visit(ccu, (ctx) => {
                // for every expression...
                var expr = ctx.Target as CodeExpression;
                if (null != expr)
                {
                    // except method reference expressions...
                    var mri = expr as CodeMethodReferenceExpression;
                    if (null != mri)
                    {
                        return;
                    }
                    // get the expression type
                    var type = res.TryGetTypeOfExpression(expr);
                    // write it along with the expression itself
                    Console.WriteLine(
                        "Expression type {0}: {1} is {2}",
                        expr.GetType().Name,
                        CodeDomUtility.ToString(expr),
                        null != type?CodeDomUtility.ToString(type):"unresolvable");
                }
            });
            Console.WriteLine("Press any key...");
            Console.ReadKey();
            Console.Clear();
        }
        static void RunResolver()
        {
            byte[] data;
            using (var stream = File.OpenRead(@"myfile.bin"))
            {
                data = new byte[(int)stream.Length];
                stream.Read(data, 0, data.Length);
            }

            // create a resolver
            var res = new CodeDomResolver();

            // read the resolver sample into the compile unit
            CodeCompileUnit ccu;

            using (var stm = File.OpenRead(@"..\..\Resolver.cs"))
                ccu = SlangParser.ReadCompileUnitFrom(stm);

            // remember to patch it!
            SlangPatcher.Patch(ccu);

            Console.Error.WriteLine(CU.ToString(ccu));

            // add the compile unit to the resolver
            res.CompileUnits.Add(ccu);

            // prepare the resolver
            // any time you add compile units you'll need
            // to call Refresh()
            res.Refresh();

            // go through all expressions in the
            // graph and try to get their type
            CodeDomVisitor.Visit(ccu, (ctx) => {
                var expr = ctx.Target as CodeExpression;
                if (null != expr)
                {
                    // we want everything except CodeTypeReferenceExpression
                    var ctre = expr as CodeTypeReferenceExpression;
                    if (null == ctre)
                    {
                        // get the scope of the expression
                        var scope             = res.GetScope(expr);
                        CodeTypeReference ctr = res.TryGetTypeOfExpression(expr, scope);
                        if (null != ctr)
                        {
                            Console.WriteLine(CU.ToString(expr) + " is type: " + CU.ToString(ctr));
                            Console.WriteLine("Scope Dump:");
                            Console.WriteLine(scope.ToString());
                        }
                    }
                }
            });
        }
        static void Demo5(CodeCompileUnit ccu)
        {
            // once again, we need one of these
            var res = new CodeDomResolver();

            res.CompileUnits.Add(ccu);
            res.Refresh();
            // we happen to know Program is the 1st type in the 2nd namespace*
            var prg = ccu.Namespaces[1].Types[0];
            // we need the scope where we're at
            var scope = res.GetScope(prg);
            // because our binder attaches to it
            var binder = new CodeDomBinder(scope);
            // now get all the methods with the specified name and flags
            var members = binder.GetMethodGroup(prg, "TestOverload", BindingFlags.Public | BindingFlags.Static);

            Console.WriteLine("There are {0} TestOverload method overloads.", members.Length);
            // try selecting one that takes a single string parameter
            var argTypes1 = new CodeTypeReference[] { new CodeTypeReference(typeof(string)) };
            var m         = binder.SelectMethod(BindingFlags.Public | BindingFlags.Static, members, argTypes1, null);

            if (null != m)
            {
                Console.WriteLine("Select TestOverload(string) returned:");
                _DumpMethod(m);
            }
            else
            {
                Console.WriteLine("Unable to bind to method");
            }
            // try selecting one that takes a single it parameter
            var argTypes2 = new CodeTypeReference[] { new CodeTypeReference(typeof(int)) };

            m = binder.SelectMethod(BindingFlags.Public | BindingFlags.Static, members, argTypes2, null);
            if (null != m)
            {
                Console.WriteLine("Select TestOverload(int) returned:");
                _DumpMethod(m);
            }
            else
            {
                Console.WriteLine("Unable to bind to method");
            }
            Console.WriteLine("Press any key...");
            Console.ReadKey();
            Console.Clear();
        }
        static void RunBinding()
        {
            // we'll need the resolver in a bit
            var res = new CodeDomResolver();

            // read the binding sample into the compile unit
            CodeCompileUnit ccu;

            using (var stm = File.OpenRead(@"..\..\Binding.cs"))
                ccu = SlangParser.ReadCompileUnitFrom(stm);

            // add the compile unit to the resolver
            res.CompileUnits.Add(ccu);

            // prepare the resolver
            res.Refresh();

            // get the first class available
            var tdecl = ccu.Namespaces[1].Types[0];
            // capture the scope at the typedecl level
            var scope = res.GetScope(tdecl);
            // create a new binder with that scope
            var binder = new CodeDomBinder(scope);
            // get the method group for Test(...)
            var methodGroup = binder.GetMethodGroup(tdecl, "Test", BindingFlags.Public | BindingFlags.Instance);

            // select the method that can take a string value
            var m = binder.SelectMethod(BindingFlags.Public, methodGroup, new CodeTypeReference[] { new CodeTypeReference(typeof(string)) }, null);

            Console.WriteLine(CU.ToString((CodeMemberMethod)m));

            // select the method that can take a short value
            // (closest match accepts int)
            m = binder.SelectMethod(BindingFlags.Public, methodGroup, new CodeTypeReference[] { new CodeTypeReference(typeof(short)) }, null);
            Console.WriteLine(CU.ToString((CodeMemberMethod)m));
        }
Beispiel #5
0
        /// <summary>
        /// Patches the CodeDOM tree received from the <see cref="SlangParser"/> into something more usable, by resolving type information and replacing various elements in the CodeDOM graph
        /// </summary>
        /// <param name="compileUnits">The <see cref="CodeCompileUnit"/> objects to patch</param>
        public static void Patch(IEnumerable <CodeCompileUnit> compileUnits)
        {
            var resolver = new CodeDomResolver();

            foreach (var ccu in compileUnits)
            {
                resolver.CompileUnits.Add(ccu);
            }
            resolver.Refresh();
restart:
            var working = -1;
            var oworking = 0;

            while (0 != working && oworking != working)
            {
                oworking = working;
                working  = 0;
                for (int ic = resolver.CompileUnits.Count, i = 0; i < ic; ++i)
                {
                    CodeDomVisitor.Visit(resolver.CompileUnits[i], (ctx) => {
                        var co = ctx.Target as CodeObject;
                        if (null != co && co.UserData.Contains("slang:unresolved"))
                        {
                            ++working;
                            _Patch(ctx.Target as CodeFieldReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeVariableDeclarationStatement, ctx, resolver);
                            _Patch(ctx.Target as CodeAssignStatement, ctx, resolver);
                            _Patch(ctx.Target as CodeVariableReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeDelegateInvokeExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeObjectCreateExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeBinaryOperatorExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeIndexerExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeMemberMethod, ctx, resolver);
                            _Patch(ctx.Target as CodeMemberProperty, ctx, resolver);
                            _Patch(ctx.Target as CodeTypeReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeTypeReference, ctx, resolver);
                        }
                    });
                }
                resolver.Refresh();
            }
            oworking = working;
            working  = 0;
            if (0 < oworking)
            {
                // one last time
                for (int ic = resolver.CompileUnits.Count, i = 0; i < ic; ++i)
                {
                    CodeDomVisitor.Visit(resolver.CompileUnits[i], (ctx) =>
                    {
                        var co = ctx.Target as CodeObject;
                        if (null != co && co.UserData.Contains("slang:unresolved"))
                        {
                            ++working;
                            _Patch(ctx.Target as CodeFieldReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeVariableDeclarationStatement, ctx, resolver);
                            _Patch(ctx.Target as CodeAssignStatement, ctx, resolver);
                            _Patch(ctx.Target as CodeVariableReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeDelegateInvokeExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeObjectCreateExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeBinaryOperatorExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeIndexerExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeMemberMethod, ctx, resolver);
                            _Patch(ctx.Target as CodeMemberProperty, ctx, resolver);
                            _Patch(ctx.Target as CodeTypeReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeTypeReference, ctx, resolver);
                        }
                    });
                }
                if (oworking != working)
                {
                    goto restart;
                }
            }
        }