static void _Patch(CodeDelegateInvokeExpression di, CodeDomVisitContext ctx, CodeDomResolver resolver)
        {
            if (null != di)
            {
                // these can be method invokes depending.
                if (null != di.TargetObject)
                {
                    // probably already fixed in an earlier visit
                    var mr = di.TargetObject as CodeMethodReferenceExpression;
                    if (null != mr)
                    {
                        var mi = new CodeMethodInvokeExpression(mr);
                        mi.Parameters.AddRange(di.Parameters);
                        CodeDomVisitor.ReplaceTarget(ctx, mi);

                        //args.Cancel = true;
                    }
                    else
                    {
                        var cco = di.TargetObject as CodeObject;
                        if (null == cco)
                        {
                            System.Diagnostics.Debugger.Break();
                        }
                    }
                }
                else
                {
                    // we really are at a loss here as the only way this would be valid is
                    // through a self call on a delegate object itself, like this();
                    throw new InvalidProgramException("Untargeted delegate invoke produced by slang parser!");
                }
                //return;
            }
        }
 static void _Patch(CodeMemberMethod meth, CodeDomVisitContext ctx, CodeDomResolver resolver)
 {
     if (null != meth)
     {
         // TODO: Populate public implementation types
         meth.UserData.Remove("slang:unresolved");
         if ("Main" == meth.Name && (meth.Attributes & MemberAttributes.ScopeMask) == MemberAttributes.Static)
         {
             if (0 == meth.Parameters.Count && null == meth.ReturnType || "System.Void" == meth.ReturnType.BaseType)
             {
                 var epm = new CodeEntryPointMethod();
                 epm.Attributes = meth.Attributes;
                 epm.LinePragma = meth.LinePragma;
                 epm.StartDirectives.AddRange(meth.StartDirectives);
                 epm.EndDirectives.AddRange(meth.EndDirectives);
                 epm.Comments.AddRange(meth.Comments);
                 epm.CustomAttributes.AddRange(meth.CustomAttributes);
                 epm.ReturnTypeCustomAttributes.AddRange(meth.ReturnTypeCustomAttributes);
                 epm.TypeParameters.AddRange(meth.TypeParameters);
                 epm.PrivateImplementationType = meth.PrivateImplementationType;
                 epm.ImplementationTypes.AddRange(meth.ImplementationTypes);
                 epm.Name = meth.Name;
                 epm.Statements.AddRange(meth.Statements);
                 CodeDomVisitor.ReplaceTarget(ctx, epm);
             }
         }
         //return;
     }
 }
 static void _Patch(CodeMemberProperty prop, CodeDomVisitContext ctx, CodeDomResolver resolver)
 {
     if (null != prop)
     {
         // TODO: add public implementation types
         prop.UserData.Remove("slang:unresolved");
     }
 }
        static bool _IsDelegate(CodeExpression target, CodeDomResolver res)
        {
            var v = target as CodeVariableReferenceExpression;

            if (null != v && v.UserData.Contains("slang:unresolved"))
            {
                var scope = res.GetScope(target);
                if (scope.MemberNames.Contains(v.VariableName))
                {
                    return(true);
                }
            }
            return(false);
        }
 static void _Patch(CodeTypeReference tr, CodeDomVisitContext ctx, CodeDomResolver res)
 {
     if (null != tr)
     {
         if (res.IsValidType(tr, res.GetScope(tr)))
         {
             tr.UserData.Remove("slang:unresolved");
             return;
         }
         // this is probably a nested type but with . instead of +
         // so now we need to crack it apart and hunt it down
         throw new NotImplementedException();
     }
 }
 static void _Patch(CodeObjectCreateExpression oc, CodeDomVisitContext ctx, CodeDomResolver res)
 {
     if (null != oc)             // we have to check to see if this is a delegate creation expression
     {
         oc.UserData.Remove("slang:unresolved");
         if (1 == oc.Parameters.Count)
         {
             if (_IsDelegate(oc.Parameters[0], res))
             {
                 var del = _GetDelegateFromFields(oc, oc.Parameters[0], res);
                 CodeDomVisitor.ReplaceTarget(ctx, del);
             }
         }
     }
 }
        static void _Patch(CodeIndexerExpression indexer, CodeDomVisitContext ctx, CodeDomResolver resolver)
        {
            if (null != indexer)
            {
                if (indexer.TargetObject.UserData.Contains("slang:unresolved"))
                {
                    return;
                }

                var ctr = resolver.GetTypeOfExpression(indexer.TargetObject);
                if (null != ctr.ArrayElementType && 0 < ctr.ArrayRank)
                {
                    var ai = new CodeArrayIndexerExpression(indexer.TargetObject);
                    ai.Indices.AddRange(indexer.Indices);
                    CodeDomVisitor.ReplaceTarget(ctx, ai);

                    //return;
                }
                indexer.UserData.Remove("slang:unresolved");
            }
        }
        /// <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();
            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 CodeVariableReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeDelegateInvokeExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeObjectCreateExpression, 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 CodeTypeReference, ctx, resolver);
                        }
                    });
                }
                resolver.Refresh();
            }
        }
        static void _Patch(CodeVariableDeclarationStatement vd, CodeDomVisitContext ctx, CodeDomResolver resolver)
        {
            if (null != vd)
            {
                if (CodeDomResolver.IsNullOrVoidType(vd.Type))
                {
                    if (null == vd.InitExpression)
                    {
                        throw new ArgumentException("The code contains an incomplete variable declaration.", "resolver");
                    }
                    if (!_HasUnresolved(vd.InitExpression))
                    {
                        var t = resolver.GetTypeOfExpression(vd.InitExpression, resolver.GetScope(vd.InitExpression));

                        vd.Type = t;
                        if (!CodeDomResolver.IsNullOrVoidType(t))
                        {
                            vd.UserData.Remove("slang:unresolved");
                        }
                    }
                }
            }
        }
Exemple #10
0
 /// <summary>
 /// Initializes the binder with the given scope
 /// </summary>
 /// <param name="scope">The scope in which the binder is to operate</param>
 public CodeDomBinder(CodeDomResolverScope scope)
 {
     _resolver = scope.Resolver;
     _scope    = scope;
 }
Exemple #11
0
        // Given a set of properties that match the base criteria, select one.
        /// <summary>
        /// Selects the property that matches the given signature
        /// </summary>
        /// <param name="flags">The binding flags to use</param>
        /// <param name="match">The properties to evaluate</param>
        /// <param name="returnType">The return type to evaluate or null to ignore</param>
        /// <param name="indices">The indices to compare with the signature</param>
        /// <param name="modifiers">Not used</param>
        /// <returns>The property that matches the signature, or null if none could be found</returns>
        public CodeMemberProperty SelectProperty(BindingFlags flags, CodeMemberProperty[] match, CodeTypeReference returnType,
                                                 CodeTypeReference[] indices, ParameterModifier[] modifiers)
        {
            // Allow a null indexes array. But if it is not null, every element must be non-null as well.
            if (indices != null && !Contract.ForAll(indices, delegate(CodeTypeReference t) { return(t != null && 0 != string.Compare(t.BaseType, "System.Void", StringComparison.InvariantCulture)); }))
            {
                Exception e;                  // Written this way to pass the Code Contracts style requirements.
                e = new ArgumentNullException("indexes");
                throw e;
            }
            if (match == null || match.Length == 0)
            {
                throw new ArgumentException("The array cannot be null or empty", nameof(match));
            }


            var candidates = (CodeMemberProperty[])match.Clone();

            int i, j = 0;

            // Find all the properties that can be described by type indexes parameter
            int CurIdx        = 0;
            int indexesLength = (indices != null) ? indices.Length : 0;

            for (i = 0; i < candidates.Length; i++)
            {
                if (indices != null)
                {
                    var par = candidates[i].Parameters;
                    if (par.Count != indexesLength)
                    {
                        continue;
                    }

                    for (j = 0; j < indexesLength; j++)
                    {
                        var pCls = par[j].Type;
                        if (null == pCls || 0 == string.Compare("System.Void", pCls.BaseType, StringComparison.InvariantCulture))
                        {
                            continue;
                        }
                        // If the classes  exactly match continue
                        if (pCls == indices[j])
                        {
                            continue;
                        }
                        if (0 == pCls.ArrayRank && 0 == string.Compare("System.Object", pCls.BaseType))
                        {
                            continue;
                        }

                        if (CodeDomResolver.IsPrimitiveType(pCls))
                        {
                            var type = indices[j];

                            if (!CodeDomResolver.IsPrimitiveType(type) || !_resolver.CanConvertTo(type, pCls, _scope))
                            {
                                break;
                            }
                        }
                        else
                        {
                            if (!_resolver.CanConvertTo(indices[j], pCls, _scope, false))
                            {
                                break;
                            }
                        }
                    }
                }

                if (j == indexesLength)
                {
                    if (returnType != null)
                    {
                        if (CodeDomResolver.IsPrimitiveType(candidates[i].Type))
                        {
                            if (CodeDomResolver.IsPrimitiveType(returnType) ||
                                !_resolver.CanConvertTo(returnType, candidates[i].Type, _scope))
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (!_resolver.CanConvertTo(returnType, candidates[i].Type, _scope, false))
                            {
                                continue;
                            }
                        }
                    }
                    candidates[CurIdx++] = candidates[i];
                }
            }
            if (CurIdx == 0)
            {
                return(null);
            }
            if (CurIdx == 1)
            {
                return(candidates[0]);
            }

            // Walk all of the properties looking the most specific method to invoke
            int  currentMin = 0;
            bool ambig      = false;

            int[] paramOrder = new int[indexesLength];
            for (i = 0; i < indexesLength; i++)
            {
                paramOrder[i] = i;
            }
            for (i = 1; i < CurIdx; i++)
            {
                int newMin = FindMostSpecificType(candidates[currentMin].Type, candidates[i].Type, returnType);
                if (newMin == 0 && indices != null)
                {
                    newMin = FindMostSpecific(_GetParamInfos(candidates[currentMin].Parameters, _scope),
                                              paramOrder,
                                              null,
                                              _GetParamInfos(candidates[i].Parameters, _scope),
                                              paramOrder,
                                              null,
                                              indices,
                                              null);
                }
                if (newMin == 0)
                {
                    newMin = FindMostSpecificProperty(candidates[currentMin], candidates[i]);
                    if (newMin == 0)
                    {
                        ambig = true;
                    }
                }
                if (newMin == 2)
                {
                    ambig      = false;
                    currentMin = i;
                }
            }

            if (ambig)
            {
                throw new AmbiguousMatchException("Multiple members matched the target argument types");
            }
            return(candidates[currentMin]);
        }
        static CodeDelegateCreateExpression _GetDelegateFromFields(CodeObjectCreateExpression oc, CodeExpression target, CodeDomResolver res)
        {
            var v = target as CodeVariableReferenceExpression;

            if (null != v)
            {
                var scope = res.GetScope(v);
                if (scope.MemberNames.Contains(v.VariableName))
                {
                    return(new CodeDelegateCreateExpression(oc.CreateType, new CodeThisReferenceExpression(), v.VariableName));
                }
            }
            throw new NotImplementedException();
        }
        static void _Patch(CodeFieldReferenceExpression fr, CodeDomVisitContext ctx, CodeDomResolver resolver)
        {
            if (null != fr)
            {
                var path = _GetUnresRootPathOfExpression(fr);
                if (null != path)
                {
                    // now we have something to work with.
                    var scope = resolver.GetScope(fr);
                    var sa    = path.Split('.');
                    if (1 == sa.Length)
                    {
                        System.Diagnostics.Debugger.Break();
                        throw new NotImplementedException();
                    }
                    else
                    {
                        object            t   = null;
                        string            tn  = null;
                        CodeExpression    tf  = fr;
                        CodeExpression    ptf = null;
                        CodeTypeReference ctr = null;
                        for (var i = sa.Length - 1; i >= 1; --i)
                        {
                            tn  = string.Join(".", sa, 0, i);
                            ptf = tf;
                            tf  = _GetTargetOfExpression(tf);
                            ctr = new CodeTypeReference(tn);
                            t   = resolver.TryResolveType(ctr, scope);
                            if (null != t)
                            {
                                break;
                            }
                        }
                        if (null != t)
                        {
                            var tt = t as Type;
                            if (null != tt)
                            {
                                ctr = new CodeTypeReference(tt);
                            }
                            else
                            {
                                ctr = resolver.GetQualifiedType(ctr, scope);
                            }
                            // we found a type reference
                            _SetTargetOfExpression(ptf, new CodeTypeReferenceExpression(ctr));
                            return;
                            //args.Cancel = true;
                        }
                    }
                }

                // this probably means part of our field has been resolved, or at the very least
                // it does not come from a rooted var ref.
                if (!fr.TargetObject.UserData.Contains("slang:unresolved"))
                {
                    var scope    = resolver.GetScope(fr);
                    var binder   = new CodeDomBinder(scope);
                    var t        = resolver.GetTypeOfExpression(fr.TargetObject);
                    var isStatic = false;
                    var tre      = fr.TargetObject as CodeTypeReferenceExpression;
                    if (null != tre)
                    {
                        isStatic = true;
                    }
                    var tt = resolver.TryResolveType(isStatic ? tre.Type: t, scope);
                    if (null == tt)
                    {
                        throw new InvalidOperationException(string.Format("The type {0} could not be resolved.", t.BaseType));
                    }

                    var td = tt as CodeTypeDeclaration;
                    // TODO: This code could be a lot faster if we added some functionality to the binder
                    // we're just checking to see if the method, property or field exists
                    var m = binder.GetField(tt, fr.FieldName, _BindFlags);
                    if (null != m)
                    {
                        fr.UserData.Remove("slang:unresolved");
                        return;
                    }
                    m = binder.GetEvent(tt, fr.FieldName, _BindFlags);
                    if (null != m)
                    {
                        var er = new CodeEventReferenceExpression(fr.TargetObject, fr.FieldName);
                        CodeDomVisitor.ReplaceTarget(ctx, er);
                        return;
                    }
                    var ml = binder.GetMethodGroup(tt, fr.FieldName, _BindFlags);
                    if (0 < ml.Length)
                    {
                        var mr = new CodeMethodReferenceExpression(fr.TargetObject, fr.FieldName);
                        CodeDomVisitor.ReplaceTarget(ctx, mr);
                        return;
                    }
                    ml = binder.GetPropertyGroup(tt, fr.FieldName, _BindFlags);
                    if (0 < ml.Length)
                    {
                        var pr = new CodePropertyReferenceExpression(fr.TargetObject, fr.FieldName);
                        CodeDomVisitor.ReplaceTarget(ctx, pr);
                        return;
                    }
                    throw new InvalidProgramException(string.Format("Cannot deterimine the target reference {0}", fr.FieldName));
                }
            }
        }
        static void _Patch(CodeVariableReferenceExpression vr, CodeDomVisitContext ctx, CodeDomResolver resolver)
        {
            if (null != vr)
            {
                if ("NodeFlags" == vr.VariableName)
                {
                    System.Diagnostics.Debugger.Break();
                }
                var scope = resolver.GetScope(vr);
                if (scope.VariableTypes.ContainsKey(vr.VariableName))
                {
                    vr.UserData.Remove("slang:unresolved");
                    return;
                }
                // we need to replace it.
                if (scope.ArgumentTypes.ContainsKey(vr.VariableName))
                {
                    var a = new CodeArgumentReferenceExpression(vr.VariableName);
                    CodeDomVisitor.ReplaceTarget(ctx, a);
                    return;
                    //args.Cancel = true;
                }
                else if (scope.FieldNames.Contains(vr.VariableName))
                {
                    CodeTypeReference tref;
                    // find out where it belongs.
                    if (scope.ThisTargets.Contains(vr.VariableName))
                    {
                        var f = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, f);
                        //return;
                    }
                    else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref))
                    {
                        var f = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, f);
                        //return;
                    }

                    return;
                }
                else if (scope.MethodNames.Contains(vr.VariableName))
                {
                    CodeTypeReference tref;
                    // find out where it belongs.
                    if (scope.ThisTargets.Contains(vr.VariableName))
                    {
                        var m = new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, m);
                        return;
                        //args.Cancel = true;
                    }
                    if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref))
                    {
                        var m = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, m);
                        return;
                        //args.Cancel = true;
                    }
                }
                else if (scope.PropertyNames.Contains(vr.VariableName))
                {
                    CodeTypeReference tref;
                    // find out where it belongs.
                    if (scope.ThisTargets.Contains(vr.VariableName))
                    {
                        var p = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, p);
                        return;
                        //args.Cancel = true;
                    }
                    else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref))
                    {
                        var p = new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, p);
                        return;
                        //args.Cancel = true;
                    }
                }
                else if (scope.EventNames.Contains(vr.VariableName))
                {
                    CodeTypeReference tref;
                    // find out where it belongs.
                    if (scope.ThisTargets.Contains(vr.VariableName))
                    {
                        var e = new CodeEventReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, e);
                        return;
                        //args.Cancel = true;
                    }
                    else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref))
                    {
                        var e = new CodeEventReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, e);
                        return;
                        //args.Cancel = true;
                    }
                }
                return;
            }
            return;
        }