Represents a simple compiler generated parameter of a given type.
Inheritance: ParameterSymbol
Example #1
0
            internal InvokeMethod(SynthesizedDelegateSymbol containingType, BitVector byRefParameters, TypeSymbol voidReturnTypeOpt)
            {
                var typeParams = containingType.TypeParameters;

                _containingType = containingType;

                // if we are given Void type the method returns Void, otherwise its return type is the last type parameter of the delegate:
                _returnType = voidReturnTypeOpt ?? typeParams.Last();

                var parameters = new ParameterSymbol[typeParams.Length - ((object)voidReturnTypeOpt != null ? 0 : 1)];

                for (int i = 0; i < parameters.Length; i++)
                {
                    // we don't need to distinguish between out and ref since this is an internal synthesized symbol:
                    var refKind = !byRefParameters.IsNull && byRefParameters[i] ? RefKind.Ref : RefKind.None;

                    parameters[i] = new SynthesizedParameterSymbol(this, typeParams[i], i, refKind);
                }

                _parameters = parameters.AsImmutableOrNull();
            }
Example #2
0
        /// <summary>
        /// Gets array of parameter symbols.
        /// Lazily ensures there is the variadic parameter at the end if needed.
        /// </summary>
        ImmutableArray <ParameterSymbol> GetParameters()
        {
            if ((Flags & RoutineFlags.RequiresParams) != 0 && (this is SourceFunctionSymbol || this is SourceMethodSymbol))
            {
                if (_params.Length == 0 || !_params.Last().IsParams)
                {
                    // lazily add [params] PhpValue[] <params>
                    var p = new SynthesizedParameterSymbol( // IsImplicitlyDeclared, IsParams
                        this,
                        ArrayTypeSymbol.CreateSZArray(this.ContainingAssembly, this.DeclaringCompilation.CoreTypes.PhpValue),
                        _params.Length,
                        RefKind.None,
                        SpecialParameterSymbol.ParamsName, true);

                    //
                    _params = _params.Add(p);
                }
            }

            //
            return(_params);
        }
        protected virtual IEnumerable<ParameterSymbol> CreateParameters(IEnumerable<ParameterSymbol> baseparams)
        {
            int index = 0;

            // Context <ctx>
            yield return new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.Context, SpecialParameterSymbol.ContextName, index++);

            if (IsInitFieldsOnly)
            {
                // DummyFieldsOnlyCtor _
                yield return new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.DummyFieldsOnlyCtor, "_", index++);
            }

            // same parameters as PHP constructor
            foreach (var p in baseparams)
            {
                if (SpecialParameterSymbol.IsContextParameter(p)) continue;
                if (SpecialParameterSymbol.IsDummyFieldsOnlyCtorParameter(p)) continue;

                yield return SynthesizedParameterSymbol.Create(this, p, index++);
            }
        }
        /// <summary>
        /// Collects methods that has to be overriden and matches with this declaration.
        /// Missing overrides are reported, needed ghost stubs are synthesized.
        /// </summary>
        public void FinalizeMethodTable(Emit.PEModuleBuilder module, DiagnosticBag diagnostics)
        {
            // creates ghost stubs for overrides that do not match the signature

            foreach (var info in this.ResolveOverrides(diagnostics))
            {
                // note: unresolved abstracts already reported by ResolveOverrides

                // is ghost stub needed?

                if (ReferenceEquals(info.OverrideCandidate?.ContainingType, this) ||    // candidate not matching exactly the signature in this type
                    info.ImplementsInterface)                                           // explicitly implement the interface
                {
                    if (info.HasOverride)
                    {
                        if (info.ImplementsInterface && info.Override != null && info.Override.IsVirtual)
                        {
                            // create explicit override only if the interface method is implemented with a class method that does not implement the interface

                            /*
                             * interface I { foo }  // METHOD
                             * class X { foo }      // OVERRIDE
                             * class Y : X, I { explicit I.foo override }   // GHOST
                             */
                            if (info.Override.ContainingType.ImplementsInterface(info.Method.ContainingType))
                            {
                                /* => X implements I */
                                // explicit method override is not needed
                                continue;
                            }
                        }

                        /*
                         * class A {
                         *    TReturn1 foo(A, B);
                         * }
                         * class B : A {
                         *    TReturn2 foo(A2, B2);
                         *
                         *    // SYNTHESIZED GHOST:
                         *    override TReturn foo(A, B){ return (TReturn)foo((A2)A, (B2)B);
                         * }
                         */

                        // override method with a ghost that calls the override
                        (info.Override ?? info.OverrideCandidate).CreateGhostOverload(
                            this, module, diagnostics,
                            info.Method.ReturnType, info.Method.Parameters,
                            phphidden: true, explicitOverride: info.Method);
                    }
                    else
                    {
                        // synthesize abstract method implementing unresolved interface member
                        if (info.IsUnresolvedAbstract && info.ImplementsInterface && this.IsAbstract && !this.IsInterface)
                        {
                            var method = info.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(method.Parameters.Select(p => SynthesizedParameterSymbol.Create(ghost, p)).ToArray());
                            module.SynthesizedManager.AddMethod(this, ghost);
                        }
                    }
                }

                // setup synthesized methods explicit override as resolved
                if (info.Override is SynthesizedMethodSymbol sm && sm.ExplicitOverride == null && sm.ContainingType == this)
                {
                    sm.ExplicitOverride = info.Method;
                }
            }

            // synthesized field accessors:
            foreach (var srcf in GetMembers().OfType <SourceFieldSymbol>())
            {
                var paccessor = srcf.FieldAccessorProperty;
                if (paccessor != null)
                {
                    GenerateFieldAccessorProperty(module, diagnostics, srcf, paccessor);
                }
            }
        }
Example #5
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());
        }
            internal InvokeMethod(SynthesizedDelegateSymbol containingType, BitVector byRefParameters, TypeSymbol voidReturnTypeOpt)
            {
                var typeParams = containingType.TypeParameters;

                _containingType = containingType;

                // if we are given Void type the method returns Void, otherwise its return type is the last type parameter of the delegate:
                _returnType = voidReturnTypeOpt ?? typeParams.Last();

                var parameters = new ParameterSymbol[typeParams.Length - ((object)voidReturnTypeOpt != null ? 0 : 1)];
                for (int i = 0; i < parameters.Length; i++)
                {
                    // we don't need to distinguish between out and ref since this is an internal synthesized symbol:
                    var refKind = !byRefParameters.IsNull && byRefParameters[i] ? RefKind.Ref : RefKind.None;

                    parameters[i] = new SynthesizedParameterSymbol(this, typeParams[i], i, refKind);
                }

                _parameters = parameters.AsImmutableOrNull();
            }