SignaturesMatch() 공개 정적인 메소드

Checks whether signatures of two methods match exactly so one can override the second.
public static SignaturesMatch ( this a, MethodSymbol b ) : bool
a this
b MethodSymbol
리턴 bool
        void EmitToString(Emit.PEModuleBuilder module)
        {
            if (this.IsInterface || this.IsTrait)
            {
                return;
            }

            var __tostring = this.GetMembersByPhpName(SpecialMethodNames.Tostring.Value).OfType <MethodSymbol>().FirstOrDefault();

            if (__tostring != null)    // implement ToString if: there is __toString() function
            {
                // lookup base string ToString()
                var overriden = this.LookupMember <MethodSymbol>(
                    WellKnownMemberNames.ObjectToString,
                    m => OverrideHelper.SignaturesMatch(m, (MethodSymbol)DeclaringCompilation.GetSpecialTypeMember(SpecialMember.System_Object__ToString)));

                Debug.Assert(overriden != null);

                if (overriden == null || overriden.IsSealed || overriden.ContainingType == this)
                {
                    // cannot be overriden
                    return;
                }

                // public sealed override string ToString()
                var tostring = new SynthesizedMethodSymbol(this, WellKnownMemberNames.ObjectToString, false, true, DeclaringCompilation.CoreTypes.String, Accessibility.Public, isfinal: false, phphidden: true)
                {
                    ExplicitOverride = overriden,
                    ForwardedCall    = __tostring,
                };

                module.SetMethodBody(tostring, MethodGenerator.GenerateMethodBody(module, tostring, il =>
                {
                    var thisPlace = new ArgPlace(this, 0);
                    var cg        = new CodeGenerator(il, module, DiagnosticBag.GetInstance(), module.Compilation.Options.OptimizationLevel, false, this, new FieldPlace(thisPlace, this.ContextStore, module), thisPlace);

                    if (__tostring != null)
                    {
                        // __tostring().ToString()
                        cg.EmitConvert(cg.EmitForwardCall(__tostring, tostring, callvirt: true), 0, tostring.ReturnType);
                    }
                    else
                    {
                        // PhpException.ObjectToStringNotSupported(this)
                        cg.EmitThis();
                        cg.EmitPop(cg.EmitCall(ILOpCode.Call, cg.CoreTypes.PhpException.Method("ObjectToStringNotSupported", cg.CoreTypes.Object)));

                        // return ""
                        cg.Builder.EmitStringConstant(string.Empty);
                    }
                    cg.EmitRet(tostring.ReturnType);
                }, null, DiagnosticBag.GetInstance(), false));
                module.SynthesizedManager.AddMethod(this, tostring);
            }
        }
예제 #2
0
        /// <summary>
        /// Matches all methods that can be overriden (non-static, public or protected, abstract or virtual)
        /// within this type sub-tree (this type, its base and interfaces)
        /// with its override.
        /// Methods without an override are either abstract or a ghost stup has to be synthesized.
        /// </summary>
        /// <param name="diagnostics"></param>
        internal OverrideInfo[] ResolveOverrides(DiagnosticBag diagnostics)
        {
            if (_lazyOverrides != null)
            {
                // already resolved
                return(_lazyOverrides);
            }

            // inherit abstracts from base type
            // ignoring System.Object (we don't override its methods from PHP)
            var overrides = new List <OverrideInfo>();

            if (BaseType != null && BaseType.SpecialType != SpecialType.System_Object)
            {
                overrides.AddRange(BaseType.ResolveOverrides(diagnostics));
            }

            // collect this type declared methods including synthesized methods
            var members = this.GetMembers();

            // resolve overrides of inherited members
            for (int i = 0; i < overrides.Count; i++)
            {
                var m = overrides[i];
                if (m.HasOverride == false)
                {
                    // update override info of the inherited member
                    overrides[i] = new OverrideInfo(m.Method, OverrideHelper.ResolveMethodImplementation(m.Method, members));
                }
                else
                {
                    // clear the interface flag of inherited override info
                    m.ImplementsInterface = false;
                    overrides[i]          = m;
                }
            }

            // resolve overrides of interface methods
            foreach (var iface in Interfaces)
            {
                // skip interfaces implemented by base type or other interfaces,
                // we don't want to add redundant override entries:
                if ((BaseType != null && BaseType.ImplementsInterface(iface)) ||
                    Interfaces.Any(x => x != iface && x.ImplementsInterface(iface)))
                {
                    // iface is already handled within overrides => skip
                    // note: iface can be ignored in metadata at all actually
                    continue;
                }

                var iface_abstracts = iface.ResolveOverrides(diagnostics);
                foreach (var m in iface_abstracts)
                {
                    if (BaseType != null && m.Method.ContainingType != iface && BaseType.ImplementsInterface(m.Method.ContainingType))
                    {
                        // iface {m.Method.ContainingType} already handled within overrides => skip
                        continue;
                    }

                    // ignore interface method that is already implemented:
                    if (overrides.Any(o => OverrideHelper.SignaturesMatch(o.Method, m.Method)))
                    {
                        continue;
                    }

                    // add interface member,
                    // resolve its override
                    overrides.Add(new OverrideInfo(m.Method, this.IsInterface ? null : OverrideHelper.ResolveMethodImplementation(m.Method, this))
                    {
                        ImplementsInterface = true
                    });
                }
            }

            // add overrideable routines from this type
            foreach (var s in members)
            {
                if (s is MethodSymbol m && m.IsOverrideable())
                {
                    overrides.Add(new OverrideInfo(m));
                }
            }

            // handle unresolved abstracts
            for (int i = 0; i < overrides.Count; i++)
            {
                var m = overrides[i];

                if (m.IsUnresolvedAbstract && this is SourceTypeSymbol srct && !this.IsInterface)
                {
                    if (!this.IsAbstract)
                    {
                        // Class '{0}' doesn't implement abstract method {1}::{2}()
                        diagnostics.Add(DiagnosticBagExtensions.ParserDiagnostic(srct.ContainingFile.SyntaxTree, srct.Syntax.HeadingSpan,
                                                                                 Devsense.PHP.Errors.Errors.AbstractMethodNotImplemented,
                                                                                 srct.FullName.ToString(), ((IPhpTypeSymbol)m.Method.ContainingType).FullName.ToString(), m.RoutineName));
                    }
                    else if (m.ImplementsInterface /*&& this.IsAbstract*/)
                    {
                        m.ImplementsInterface = false;

                        var method = m.Method;

                        Debug.Assert(!method.IsStatic);
                        Debug.Assert(method.DeclaredAccessibility != Accessibility.Private);
                        Debug.Assert(method.ContainingType.IsInterface);

                        // Template: abstract function {name}({parameters})
                        var ghost = new SynthesizedMethodSymbol(this, method.RoutineName,
                                                                isstatic: false, isvirtual: true, isabstract: true, isfinal: false,
                                                                returnType: method.ReturnType,
                                                                accessibility: method.DeclaredAccessibility);

                        ghost.SetParameters(SynthesizedParameterSymbol.Create(ghost, method.Parameters));
                        //module.SynthesizedManager.AddMethod(this, ghost); // will be added to synthesized manager by FinalizeMethodTable

                        m.Method = ghost;   // replace the interface method with synthesized abstract method

                        // update overrides
                        overrides[i] = m;
                    }
                }
            }

            // cache & return
            return(_lazyOverrides = overrides.ToArray());
        }
예제 #3
0
        /// <summary>
        /// Matches all methods that can be overriden (non-static, public or protected, abstract or virtual)
        /// within this type sub-tree (this type, its base and interfaces)
        /// with its override.
        /// Methods without an override are either abstract or a ghost stup has to be synthesized.
        /// </summary>
        /// <param name="diagnostics"></param>
        internal OverrideInfo[] ResolveOverrides(DiagnosticBag diagnostics)
        {
            if (_lazyOverrides != null)
            {
                // already resolved
                return(_lazyOverrides);
            }

            // TODO: ignore System.Object ?

            // inherit abstracts from base type
            var overrides = new List <OverrideInfo>();

            if (BaseType != null)
            {
                overrides.AddRange(BaseType.ResolveOverrides(diagnostics));
            }

            // collect this type declared methods including synthesized methods
            var methods       = this.GetMembers().OfType <MethodSymbol>();
            var methodslookup = methods.Where(OverrideHelper.CanOverride).ToLookup(m => m.RoutineName, StringComparer.OrdinalIgnoreCase);

            // resolve overrides of inherited members
            for (int i = 0; i < overrides.Count; i++)
            {
                var m = overrides[i];
                if (m.HasOverride == false)
                {
                    // update override info of the inherited member
                    overrides[i] = new OverrideInfo(m.Method, OverrideHelper.ResolveMethodImplementation(m.Method, methodslookup[m.RoutineName]));
                }
                else
                {
                    // clear the interface flag of inherited override info
                    m.ImplementsInterface = false;
                    overrides[i]          = m;
                }
            }

            // resolve overrides of interface methods
            foreach (var iface in Interfaces)
            {
                // skip interfaces implemented by base type or other interfaces,
                // we don't want to add redundant override entries:
                if ((BaseType != null && BaseType.ImplementsInterface(iface)) ||
                    Interfaces.Any(x => x != iface && x.ImplementsInterface(iface)))
                {
                    // iface is already handled within overrides => skip
                    // note: iface can be ignored in metadata at all actually
                    continue;
                }

                var iface_abstracts = iface.ResolveOverrides(diagnostics);
                foreach (var m in iface_abstracts)
                {
                    if (BaseType != null && m.Method.ContainingType != iface && BaseType.ImplementsInterface(m.Method.ContainingType))
                    {
                        // iface {m.Method.ContainingType} already handled within overrides => skip
                        continue;
                    }

                    // ignore interface method that is already implemented:
                    if (overrides.Any(o => OverrideHelper.SignaturesMatch(o.Method, m.Method)))
                    {
                        continue;
                    }

                    // add interface member,
                    // resolve its override
                    overrides.Add(new OverrideInfo(m.Method, this.IsInterface ? null : OverrideHelper.ResolveMethodImplementation(m.Method, this))
                    {
                        ImplementsInterface = true
                    });
                }
            }

            // add overrideable routines from this type
            foreach (var m in methods)
            {
                if (m.IsOverrideable())
                {
                    overrides.Add(new OverrideInfo(m));
                }
            }

            // report unresolved abstracts
            if (!this.IsAbstract && !this.IsInterface && this is SourceTypeSymbol srct)
            {
                foreach (var m in overrides)
                {
                    if (m.IsUnresolvedAbstract)
                    {
                        // Class '{0}' doesn't implement abstract method {1}::{2}()
                        diagnostics.Add(DiagnosticBagExtensions.ParserDiagnostic(srct.ContainingFile.SyntaxTree, srct.Syntax.HeadingSpan,
                                                                                 Devsense.PHP.Errors.Errors.AbstractMethodNotImplemented,
                                                                                 srct.FullName.ToString(), ((IPhpTypeSymbol)m.Method.ContainingType).FullName.ToString(), m.RoutineName));
                    }
                }
            }

            // cache & return
            return(_lazyOverrides = overrides.ToArray());
        }