Beispiel #1
0
        /// <summary>
        /// Gets (PHP) type symbols that has to be declared in order to declare given <paramref name="type"/>.
        /// </summary>
        /// <param name="type">The type declaration which dependant symbols will be returned.</param>
        public static IList <NamedTypeSymbol> GetDependentSourceTypeSymbols(this SourceTypeSymbol type)
        {
            // TODO: what type can be declared on Context ? SourceTypeSymbol and PENamedTypeSymbol compiled from PHP sources
            // TODO: traits

            var btype  = type.BaseType as SourceTypeSymbol;
            var ifaces = type.Interfaces;

            if (ifaces.Length == 0 && btype == null)
            {
                return(Array.Empty <NamedTypeSymbol>());
            }

            var list = new List <NamedTypeSymbol>(1 + ifaces.Length);

            if (btype != null)
            {
                list.Add(btype);
            }
            if (ifaces.Length != 0)
            {
                list.AddRange(ifaces.Where(x => x is SourceTypeSymbol));
            }

            return(list);
        }
Beispiel #2
0
        private SynthesizedPhpCtorSymbol(SourceTypeSymbol containingType, Accessibility accessibility,
                                         bool isInitFieldsOnly,
                                         MethodSymbol basector, MethodSymbol __construct, int paramsLimit = int.MaxValue)
            : base(containingType, WellKnownMemberNames.InstanceConstructorName, false, false, containingType.DeclaringCompilation.CoreTypes.Void, accessibility)
        {
            if (basector == null)
            {
                throw new ArgumentNullException(nameof(basector));
            }

            _basector     = basector;
            _phpconstruct = __construct;

            this.IsInitFieldsOnly = isInitFieldsOnly;

            // clone parameters from __construct ?? basector
            var template = (__construct ?? basector).Parameters;
            var ps       = new List <ParameterSymbol>(template.Length)
            {
                new SpecialParameterSymbol(this, DeclaringCompilation.CoreTypes.Context, SpecialParameterSymbol.ContextName, 0) // Context <ctx>
            };

            // same parameters as PHP constructor
            for (int i = 0; i < template.Length && i < paramsLimit; i++)
            {
                var p = template[i];
                if (!SpecialParameterSymbol.IsContextParameter(p))
                {
                    ps.Add(new SynthesizedParameterSymbol(this, p.Type, ps.Count, p.RefKind, p.Name, p.IsParams,
                                                          explicitDefaultConstantValue: p.ExplicitDefaultConstantValue));
                }
            }

            _parameters = ps.ToImmutableArray();
        }
Beispiel #3
0
        public SourceFieldSymbol(
            SourceTypeSymbol type, string name, Location location, Accessibility accessibility,
            PHPDocBlock phpdoc, PhpPropertyKind kind,
            BoundExpression initializer = null,
            ImmutableArray <AttributeData> attributes = default)
        {
            Contract.ThrowIfNull(type);
            Contract.ThrowIfNull(name);

            _containingType = type;
            _fieldName      = name;
            _fieldKind      = kind;
            _accessibility  = accessibility;
            _initializer    = initializer;
            _location       = location;
            _attributes     = attributes.IsDefault ? ImmutableArray <AttributeData> .Empty : attributes;
            PHPDocBlock     = phpdoc;

            // implicit attributes from PHPDoc
            var deprecated = phpdoc?.GetElement <PHPDocBlock.DeprecatedTag>();

            if (deprecated != null)
            {
                // [ObsoleteAttribute(message, false)]
                _attributes = _attributes.Add(DeclaringCompilation.CreateObsoleteAttribute(deprecated));
            }
        }
Beispiel #4
0
        /// <summary>
        /// Gets (PHP) type symbols that has to be declared in order to declare given <paramref name="type"/>.
        /// </summary>
        /// <param name="type">The type declaration which dependant symbols will be returned.</param>
        public static IEnumerable <NamedTypeSymbol> GetDependentSourceTypeSymbols(this SourceTypeSymbol type)
        {
            // base type
            var btype = type.BaseType;

            if (btype != null && btype.IsPhpUserType())
            {
                yield return(btype);
            }

            // interfaces
            var ifaces = type.GetDeclaredInterfaces(null);

            foreach (var t in ifaces)
            {
                if (t.IsPhpUserType())
                {
                    yield return(t);
                }
            }

            // traits
            var traituses = type.TraitUses;

            foreach (var t in traituses)
            {
                if (t.Symbol.IsPhpUserType())
                {
                    yield return(t.Symbol);
                }
            }
        }
 public SynthesizedParameterlessPhpCtorSymbol(
     SourceTypeSymbol containingType, Accessibility accessibility,
     MethodSymbol defaultctor)
     : base(containingType, accessibility, defaultctor, null)
 {
     IsPhpHidden = true; // from the PHP context, do not use this Context-less .ctor, we have the Context instance and we want to pass it properly
 }
        /// <summary>
        /// Gets (PHP) type symbols that has to be declared in order to declare given <paramref name="type"/>.
        /// </summary>
        /// <param name="type">The type declaration which dependant symbols will be returned.</param>
        public static IList <NamedTypeSymbol> GetDependentSourceTypeSymbols(this SourceTypeSymbol type)
        {
            // TODO: traits

            var btype  = (type.BaseType != null && type.BaseType.IsPhpUserType()) ? type.BaseType : null;
            var ifaces = type.Interfaces;

            if (ifaces.Length == 0 && btype == null)
            {
                return(Array.Empty <NamedTypeSymbol>());
            }

            var list = new List <NamedTypeSymbol>(1 + ifaces.Length);

            if (btype != null)
            {
                list.Add(btype);
            }
            if (ifaces.Length != 0)
            {
                list.AddRange(ifaces.Where(x => x.IsPhpUserType()));
            }

            return(list);
        }
Beispiel #7
0
        /// <summary>
        /// Creates CLS constructors for a PHP class.
        /// </summary>
        /// <param name="type">PHP class.</param>
        /// <returns>Enumeration of instance constructors for PHP class.</returns>
        /// <remarks>
        /// Constructors are created with respect to <c>base..ctor</c> and class PHP constructor function.
        /// At least a single <c>.ctor</c> is created which initializes fields and calls <c>base..ctor</c>. This is main constructor needed to properly initialize the class.
        /// In case there is a PHP constructor function:
        /// - The first ctor is marked as protected and is used only by other ctors and by derived classes to initialize class without calling the PHP constructor function.
        /// - Another ctor is created in order to call the main constructor and call PHP constructor function.
        /// - Ghost stubs of the other ctor are created in order to pass default parameter values which cannot be stored in metadata (e.g. array()).
        /// </remarks>
        public static IEnumerable <MethodSymbol> CreateCtors(SourceTypeSymbol type)
        {
            if (type.IsStatic || type.IsInterface)
            {
                yield break;
            }

            // resolve php constructor
            var phpconstruct = type.ResolvePhpCtor(true); // this tells us what parameters are provided so we can select best overload for base..ctor() call

            // resolve base .ctor that has to be called
            var btype          = type.BaseType;
            var fieldsonlyctor = (MethodSymbol)(btype as IPhpTypeSymbol)?.InstanceConstructorFieldsOnly;   // base..ctor() to be called if provided
            var basectors      = (fieldsonlyctor != null)
                ? ImmutableArray.Create(fieldsonlyctor)
                : btype.InstanceConstructors
                                 .OrderByDescending(c => c.ParameterCount) // longest ctors first
                                 .AsImmutable();

            // what parameters are provided
            var givenparams = (phpconstruct != null)
                ? phpconstruct.Parameters.Where(p => !p.IsImplicitlyDeclared && !p.IsParams).AsImmutable()
                : ImmutableArray <ParameterSymbol> .Empty;

            // first declare .ctor that initializes fields only and calls base .ctor
            var basector = ResolveBaseCtor(givenparams, basectors);

            if (basector == null)
            {
                // type.BaseType was not resolved, reported by type.BaseType
                // TODO: Err & ErrorMethodSymbol
                yield break;
            }

            // create .ctor(s)
            if (phpconstruct == null)
            {
                yield return(new SynthesizedPhpCtorSymbol(type, Accessibility.Public, false, basector, null));
            }
            else
            {
                var fieldsinitctor = new SynthesizedPhpCtorSymbol(type, Accessibility.ProtectedOrInternal, true, basector, null);
                yield return(fieldsinitctor);

                // generate .ctor(s) calling PHP __construct with optional overloads in case there is an optional parameter
                var ps = phpconstruct.Parameters;
                for (int i = 0; i < ps.Length; i++)
                {
                    var p = ps[i] as SourceParameterSymbol;
                    if (p != null && p.Initializer != null && p.ExplicitDefaultConstantValue == null)   // => ConstantValue couldn't be resolved for optional parameter
                    {
                        yield return(new SynthesizedPhpCtorSymbol(type, phpconstruct.DeclaredAccessibility, false, fieldsinitctor, phpconstruct, i));
                    }
                }

                yield return(new SynthesizedPhpCtorSymbol(type, phpconstruct.DeclaredAccessibility, false, fieldsinitctor, phpconstruct));
            }

            yield break;
        }
Beispiel #8
0
 /// <summary>
 /// Gets file symbol containing given symbol.
 /// </summary>
 public static SourceFileSymbol GetContainingFileSymbol(this Symbol s)
 {
     return(s?.OriginalDefinition switch
     {
         SourceRoutineSymbol routine => routine.ContainingFile,
         SourceTypeSymbol type => type.ContainingFile,
         _ => s != null?GetContainingFileSymbol(s.ContainingSymbol) : null,
     });
        public SourceCustomAttribute(PhpCompilation compilation, SourceTypeSymbol containingType, IBoundTypeRef tref, ImmutableArray <BoundArgument> arguments)
        {
            _compilation = compilation;
            _tref        = tref;
            _arguments   = arguments;

            TypeCtx = new FlowAnalysis.TypeRefContext(compilation, containingType);
        }
Beispiel #10
0
        public SourceMethodSymbol(SourceTypeSymbol /*!*/ type, MethodDecl /*!*/ syntax)
        {
            Contract.ThrowIfNull(type);
            Contract.ThrowIfNull(syntax);

            _type   = type;
            _syntax = syntax;
        }
        protected SynthesizedPhpCtorSymbol(SourceTypeSymbol containingType, Accessibility accessibility,
                                           MethodSymbol basector, MethodSymbol __construct, int paramsLimit = int.MaxValue)
            : base(containingType, WellKnownMemberNames.InstanceConstructorName, false, false, containingType.DeclaringCompilation.CoreTypes.Void, accessibility)
        {
            _basector     = basector ?? throw ExceptionUtilities.ArgumentNull(nameof(basector));
            _phpconstruct = __construct;

            _sourceParamsCount = paramsLimit;
            _parameters        = default; // lazy
        }
        public SourceMethodSymbol(SourceTypeSymbol /*!*/ type, MethodDecl /*!*/ syntax)
        {
            Contract.ThrowIfNull(type);
            Contract.ThrowIfNull(syntax);

            _type   = type;
            _syntax = syntax;

            // TODO: lazily; when using late static binding in a static method, add special <static> parameter, where runtime passes late static bound type
            _params = BuildParameters(syntax.Signature, syntax.PHPDoc).AsImmutable();
        }
Beispiel #13
0
        public SourceMethodSymbol(SourceTypeSymbol/*!*/type, MethodDecl/*!*/syntax)
        {
            Contract.ThrowIfNull(type);
            Contract.ThrowIfNull(syntax);

            _type = type;
            _syntax = syntax;

            // TODO: lazily; when using late static binding in a static method, add special <static> parameter, where runtime passes late static bound type
            _params = BuildParameters(syntax.Signature, syntax.PHPDoc).AsImmutable();
        }
Beispiel #14
0
        public SourceFieldSymbol(SourceTypeSymbol type, string name, Accessibility accessibility, PHPDocBlock phpdoc, KindEnum kind, BoundExpression initializer = null)
        {
            Contract.ThrowIfNull(type);
            Contract.ThrowIfNull(name);

            _containingType = type;
            _fieldName      = name;
            _fieldKind      = kind;
            _accessibility  = accessibility;
            _phpDoc         = phpdoc;
            _initializer    = initializer;
        }
        protected SynthesizedPhpCtorSymbol(SourceTypeSymbol containingType, Accessibility accessibility,
                                           MethodSymbol basector, MethodSymbol __construct, int paramsLimit = int.MaxValue)
            : base(containingType, WellKnownMemberNames.InstanceConstructorName, false, false, containingType.DeclaringCompilation.CoreTypes.Void, accessibility)
        {
            _basector     = basector ?? throw ExceptionUtilities.ArgumentNull(nameof(basector));
            _phpconstruct = __construct;

            // clone parameters from __construct ?? basector
            var template = (__construct ?? basector).Parameters;

            _parameters = CreateParameters(template.Take(paramsLimit)).ToImmutableArray();
        }
Beispiel #16
0
        public SourceFieldSymbol(SourceTypeSymbol type, string name, Accessibility accessibility, PHPDocBlock phpdoc, KindEnum kind, BoundExpression initializer = null)
        {
            Contract.ThrowIfNull(type);
            Contract.ThrowIfNull(name);

            _containingType = type;
            _fieldName = name;
            _fieldKind = kind;
            _accessibility = accessibility;
            _phpDoc = phpdoc;
            _initializer = initializer;
        }
        /// <summary>
        /// Gets PHPDoc assoviated with given source symbol.
        /// </summary>
        internal static bool TryGetPHPDocBlock(this Symbol symbol, out PHPDocBlock phpdoc)
        {
            phpdoc = symbol?.OriginalDefinition switch
            {
                SourceRoutineSymbol routine => routine.PHPDocBlock,
                SourceFieldSymbol field => field.PHPDocBlock,
                SourceTypeSymbol type => type.Syntax.PHPDoc,
                                    _ => null
            };

            return(phpdoc != null);
        }
Beispiel #18
0
        void CheckForCircularBase(SourceTypeSymbol t, DiagnosticBag diagnostics)
        {
            var set = new HashSet <SourceTypeSymbol>();  // only care about source symbols

            for (var b = t; b != null; b = b.BaseType as SourceTypeSymbol)
            {
                if (set.Add(b) == false)
                {
                    diagnostics.Add(CreateLocation(_syntax.HeadingSpan.ToTextSpan()), Errors.ErrorCode.ERR_CircularBase, t.BaseType, t);
                    break;
                }
            }
        }
Beispiel #19
0
        public SourceFieldSymbol(SourceTypeSymbol type, string name, Location location, Accessibility accessibility, PHPDocBlock phpdoc, PhpPropertyKind kind, BoundExpression initializer = null, ImmutableArray <AttributeData> customAttributes = default)
        {
            Contract.ThrowIfNull(type);
            Contract.ThrowIfNull(name);

            _containingType   = type;
            _fieldName        = name;
            _fieldKind        = kind;
            _accessibility    = accessibility;
            _phpDoc           = phpdoc;
            _initializer      = initializer;
            _location         = location;
            _customAttributes = customAttributes;
        }
Beispiel #20
0
            public override void VisitTypeDecl(TypeDecl x)
            {
                var type = new SourceTypeSymbol(_currentFile, x);

                x.SetProperty(type);    // remember bound function symbol

                _tables._declaredtypes.Add(type);

                if (!x.IsConditional)
                {
                    _tables._types.Add(x.MakeQualifiedName(), type);
                }

                //
                base.VisitTypeDecl(x);
            }
Beispiel #21
0
            public override void VisitTypeDecl(TypeDecl x)
            {
                var type = new SourceTypeSymbol(_currentFile, x);

                x.SetProperty(type);    // remember bound function symbol

                _tables._declaredtypes.Add(type);

                if (!x.IsConditional)
                {
                    _tables._types.Add(x.MakeQualifiedName(), type);
                }

                //
                base.VisitTypeDecl(x);
            }
Beispiel #22
0
        /// <summary>
        /// Gets type signature of the type [BaseType or NULL, Interface1, ..., InterfaceN]
        /// </summary>
        private static IEnumerable <TypeRefSymbol> ResolveTypeSignature(SourceTypeSymbol type, PhpCompilation compilation)
        {
            var syntax = type.Syntax;

            // base type or NULL
            if (syntax.BaseClass != null)   // a class with base
            {
                var baseTypeName = syntax.BaseClass.ClassName;

                yield return(new TypeRefSymbol()
                {
                    TypeRef = syntax.BaseClass,
                    Symbol = (baseTypeName == type.FullName) ? type : (NamedTypeSymbol)compilation.GlobalSemantics.GetType(baseTypeName)
                });
            }
            else if ((syntax.MemberAttributes & (PhpMemberAttributes.Static | PhpMemberAttributes.Interface)) != 0) // a static class or an interface
            {
                yield return(default(TypeRefSymbol));                                                               // nothing
            }
            else // a class without base
            {
                yield return(new TypeRefSymbol()
                {
                    Symbol = compilation.CoreTypes.Object.Symbol
                });
            }

            // base interfaces
            var visited = new HashSet <QualifiedName>(); // set of visited interfaces

            foreach (var i in syntax.ImplementsList)
            {
                var qname = i.ClassName;
                if (visited.Add(qname))
                {
                    yield return(new TypeRefSymbol()
                    {
                        TypeRef = i,
                        Symbol = (qname == type.FullName) ? type : (NamedTypeSymbol)compilation.GlobalSemantics.GetType(qname)
                    });
                }
            }
        }
        /// <summary>
        /// Enumerates all versions of this declaration.
        /// </summary>
        public ImmutableArray <SourceTypeSymbol> AllVersions()
        {
            ResolveBaseTypes();

            if (_nextVersion == null)
            {
                return(ImmutableArray.Create(this));
            }
            else
            {
                Debug.Assert(_version != 0);
                var result = new SourceTypeSymbol[_version];
                for (var x = this; x != null; x = x.NextVersion)
                {
                    Debug.Assert(x._version > 0 && x._version <= result.Length);
                    result[x._version - 1] = x;
                }
                return(ImmutableArray.Create(result));
            }
        }
 public SynthesizedStaticFieldsHolder(SourceTypeSymbol @class)
 {
     Contract.ThrowIfNull(@class);
     _class = @class;
 }
        private void ResolveBaseTypes(DiagnosticBag diagnostics)
        {
            Debug.Assert(_lazyInterfacesType.IsDefault);    // not resolved yet

            // get possible type signature [ BaseType?, Interface1, ..., InterfaceN ]
            // Single slots may refer to a MissingTypeSymbol or an ambiguous type symbol
            var tsignature = ResolveTypeSignature(_syntax, this.DeclaringCompilation).ToArray();

            Debug.Assert(tsignature.Length >= 1);   // [0] is base class

            // check all types are supported
            foreach (var t in tsignature)
            {
                if (t == null)
                {
                    continue;
                }

                Debug.Assert(t.Item2 != null);

                if (t.Item2.Arity != 0)
                {
                    diagnostics.Add(CreateLocation(t.Item1.Span.ToTextSpan()), Errors.ErrorCode.ERR_NotYetImplemented, "Using generic types.");
                }
                if (t.Item2.IsErrorType() && ((ErrorTypeSymbol)t.Item2).CandidateReason != CandidateReason.Ambiguous)
                {
                    diagnostics.Add(CreateLocation(t.Item1.Span.ToTextSpan()), Errors.ErrorCode.ERR_TypeNameCannotBeResolved, t.Item1.ClassName.ToString());
                }
            }

            if (!diagnostics.HasAnyErrors())
            {
                // collect variations of possible base types
                var variations = Variations <NamedTypeSymbol>(tsignature.Select(t => t?.Item2).AsImmutable(), this.ContainingFile);

                // instantiate versions
                bool self        = true;
                int  lastVersion = 0;   // the SourceTypeSymbol version, 0 ~ a single version, >0 ~ multiple version
                foreach (var v in variations)
                {
                    if (self)
                    {
                        _lazyBaseType       = v[0];
                        _lazyInterfacesType = v.RemoveAt(0);
                        self = false;
                    }
                    else
                    {
                        // create next version of this type with already resolved type signature
                        _nextVersion = new SourceTypeSymbol(_file, _syntax, v[0], v.RemoveAt(0), ++lastVersion)
                        {
                            //_lambdas = _lambdas,
                            _nextVersion = _nextVersion
                        };

                        // clone lambdas that use $this
                        if (_lambdas != null)
                        {
                            foreach (var l in _lambdas.Where(l => l.UseThis))
                            {
                                ((ILambdaContainerSymbol)_nextVersion).AddLambda(new SourceLambdaSymbol((LambdaFunctionExpr)l.Syntax, _nextVersion, l.UseThis));
                            }
                        }
                    }
                }
                if (lastVersion != 0)
                {
                    _version = ++lastVersion;

                    diagnostics.Add(CreateLocation(_syntax.HeadingSpan.ToTextSpan()), Errors.ErrorCode.WRN_AmbiguousDeclaration, this.FullName);
                }
            }
            else
            {
                // default:
                _lazyBaseType       = tsignature[0]?.Item2;
                _lazyInterfacesType = tsignature.Skip(1).Select(t => t.Item2).AsImmutable();
            }

            // check for circular dependencies
            // ...
        }
Beispiel #26
0
 public SynthesizedPhpCtorSymbol(SourceTypeSymbol /*!*/ container)
     : base(container)
 {
     _parameters = default(ImmutableArray <ParameterSymbol>); // lazy initialized
 }
Beispiel #27
0
 public SynthesizedPhpNewMethodSymbol(SourceTypeSymbol container)
     : base(container, WellKnownPchpNames.PhpNewMethodName, false, false, container.DeclaringCompilation.CoreTypes.Void, Accessibility.Public)
 {
     Debug.Assert(!container.IsStatic);
     _parameters = default(ImmutableArray <ParameterSymbol>); // lazy initialized
 }
Beispiel #28
0
        /// <summary>
        /// Creates type context for a method within given type, determines naming, type context.
        /// </summary>
        public static TypeRefContext/*!*/CreateTypeRefContext(SourceTypeSymbol/*!*/containingType)
        {
            Contract.ThrowIfNull(containingType);

            var typeDecl = containingType.Syntax;
            return new TypeRefContext(typeDecl.ContainingSourceUnit, containingType);
        }
        /// <summary>
        /// Creates CLS constructors for a PHP class.
        /// </summary>
        /// <param name="type">PHP class.</param>
        /// <returns>Enumeration of instance constructors for PHP class.</returns>
        /// <remarks>
        /// Constructors are created with respect to <c>base..ctor</c> and class PHP constructor function.
        /// At least a single <c>.ctor</c> is created which initializes fields and calls <c>base..ctor</c>. This is main constructor needed to properly initialize the class.
        /// In case there is a PHP constructor function:
        /// - The first ctor is marked as protected and is used only by other ctors and by derived classes to initialize class without calling the PHP constructor function.
        /// - Another ctor is created in order to call the main constructor and call PHP constructor function.
        /// - Ghost stubs of the other ctor are created in order to pass default parameter values which cannot be stored in metadata (e.g. array()).
        /// </remarks>
        public static IEnumerable <MethodSymbol> CreateCtors(SourceTypeSymbol type)
        {
            if (type.IsStatic || type.IsInterface)
            {
                yield break;
            }

            // resolve php constructor
            var phpconstruct = type.ResolvePhpCtor(true); // this tells us what parameters are provided so we can select best overload for base..ctor() call

            // resolve base .ctor that has to be called
            var btype          = type.BaseType;
            var fieldsonlyctor = (MethodSymbol)(btype as IPhpTypeSymbol)?.InstanceConstructorFieldsOnly;   // base..ctor() to be called if provided
            var basectors      = (fieldsonlyctor != null)
                ? ImmutableArray.Create(fieldsonlyctor)
                : btype.InstanceConstructors
                                 .Where(c => c.DeclaredAccessibility != Accessibility.Private) // ignore inaccessible .ctors
                                 .OrderByDescending(c => c.ParameterCount)                     // longest ctors first
                                 .AsImmutable();

            // what parameters are provided
            var givenparams = (phpconstruct != null)
                ? phpconstruct.Parameters.Where(p => !p.IsImplicitlyDeclared && !p.IsParams).AsImmutable()
                : ImmutableArray <ParameterSymbol> .Empty;

            // first declare .ctor that initializes fields only and calls base .ctor
            var basector = ResolveBaseCtor(givenparams, basectors);

            if (basector == null)
            {
                // type.BaseType was not resolved, reported by type.BaseType
                // TODO: Err & ErrorMethodSymbol
                yield break;
            }

            MethodSymbol defaultctor; // .ctor to be used by default

            // create .ctor(s)
            if (phpconstruct == null)
            {
                yield return(defaultctor = new SynthesizedPhpCtorSymbol(type, Accessibility.Public, basector, null));
            }
            else
            {
                var fieldsinitctor = new SynthesizedPhpCtorSymbol(type, Accessibility.ProtectedOrInternal, basector, null)
                {
                    IsInitFieldsOnly        = true,
                    IsEditorBrowsableHidden = true,
                };
                yield return(fieldsinitctor);

                // generate .ctor(s) calling PHP __construct with optional overloads in case there is an optional parameter
                var ps = phpconstruct.Parameters;
                for (int i = 0; i < ps.Length; i++)
                {
                    var p = ps[i] as SourceParameterSymbol;
                    if (p != null && p.Initializer != null && p.ExplicitDefaultConstantValue == null)   // => ConstantValue couldn't be resolved for optional parameter
                    {
                        yield return(new SynthesizedPhpCtorSymbol(type, phpconstruct.DeclaredAccessibility, fieldsinitctor, phpconstruct, i));
                    }
                }

                yield return(defaultctor = new SynthesizedPhpCtorSymbol(type, phpconstruct.DeclaredAccessibility, fieldsinitctor, phpconstruct));
            }

            // parameterless .ctor() with shared context
            if (defaultctor.DeclaredAccessibility == Accessibility.Public && type.DeclaredAccessibility == Accessibility.Public && !type.IsAbstract)
            {
                // Template:
                // void .ctor(...) : this(ContextExtensions.CurrentContext, ...) { }

                // NOTE: overload resolution will prioritize the overload with Context parameter over this one

                yield return(new SynthesizedParameterlessPhpCtorSymbol(type, Accessibility.Public, defaultctor));
            }

            yield break;
        }
 public SynthesizedPhpCtorSymbol(SourceTypeSymbol/*!*/container)
     : base(container)
 {
     _parameters = default(ImmutableArray<ParameterSymbol>); // lazy initialized
 }
        public void AddSyntaxTree(PhpSyntaxTree tree)
        {
            Contract.ThrowIfNull(tree);

            Debug.Assert(tree.Root != null);

            // create file symbol (~ php script containing type)
            var fsymbol = SourceFileSymbol.Create(_compilation, tree);

            if (FirstScript == null)
            {
                FirstScript = fsymbol;
            }

            // collect type declarations
            foreach (var t in tree.Types)
            {
                var typesymbol = SourceTypeSymbol.Create(fsymbol, t);

                t.SetProperty(typesymbol);    // remember bound type symbol
                fsymbol.ContainedTypes.Add(typesymbol);
            }

            // annotate routines that contain yield
            if (!tree.YieldNodes.IsDefaultOrEmpty)
            {
                var yieldsInRoutines = new Dictionary <LangElement, List <IYieldLikeEx> >();
                foreach (var y in tree.YieldNodes)
                {
                    Debug.Assert(y is IYieldLikeEx);
                    var yield = y as IYieldLikeEx;

                    var containingRoutine = y.GetContainingRoutine();
                    Debug.Assert(containingRoutine != null);

                    if (!yieldsInRoutines.ContainsKey(containingRoutine))
                    {
                        yieldsInRoutines.Add(containingRoutine, new List <IYieldLikeEx>());
                    }
                    yieldsInRoutines[containingRoutine].Add(yield);
                }

                foreach (var yieldsInRoutine in yieldsInRoutines)
                {
                    var routine = yieldsInRoutine.Key;
                    var yields  = yieldsInRoutine.Value;

                    routine.Properties.SetProperty(typeof(ImmutableArray <IYieldLikeEx>), yields.ToImmutableArray());
                }
            }

            //
            foreach (var f in tree.Functions)
            {
                var routine = new SourceFunctionSymbol(fsymbol, f);

                f.SetProperty(routine); // remember bound function symbol
                fsymbol.AddFunction(routine);
            }

            //
            foreach (var l in tree.Lambdas)
            {
                var lambdasymbol = new SourceLambdaSymbol(l, fsymbol, !l.Modifiers.IsStatic());
                ((ILambdaContainerSymbol)fsymbol).AddLambda(lambdasymbol);
            }

            //
            _files.Add(fsymbol.RelativeFilePath, fsymbol);
            _ordinalMap.Add(tree, _ordinalMap.Count);
            _version++;
        }
 public SynthesizedPhpNewMethodSymbol(SourceTypeSymbol container)
     : base(container, WellKnownPchpNames.PhpNewMethodName, false, false, container.DeclaringCompilation.CoreTypes.Void, Accessibility.Public)
 {
     Debug.Assert(!container.IsStatic);
     _parameters = default(ImmutableArray<ParameterSymbol>); // lazy initialized
 }
Beispiel #33
0
 internal TypeRefContext(SourceUnit sourceUnit, SourceTypeSymbol containingType)
 {
     _sourceUnit = sourceUnit;
     _typeRefs = new List<ITypeRef>();
     _containingType = containingType;
 }
Beispiel #34
0
 /// <summary>
 /// Enqueues initializers of a class fields and constants.
 /// </summary>
 void EnqueueFieldsInitializer(SourceTypeSymbol type)
 {
     type.GetMembers().OfType<SourceFieldSymbol>().Foreach(f =>
     {
         if (f.Initializer != null)
         {
             EnqueueExpression(
                 f.Initializer,
                 TypeRefFactory.CreateTypeRefContext(type), //the context will be lost, analysis resolves constant values only and types are temporary
                 NameUtils.GetNamingContext(type.Syntax));
         }
     });
 }
Beispiel #35
0
 public SynthesizedTraitFieldSymbol(SourceTypeSymbol containing, FieldSymbol traitInstanceField, IPhpPropertySymbol sourceField)
     : base(containing, null, sourceField.Name, sourceField.DeclaredAccessibility, isStatic: false, isReadOnly: false)
 {
     _traitInstanceField = traitInstanceField;
     _traitmember        = sourceField;
 }
Beispiel #36
0
        /// <summary>
        /// Emits declaring type into the context.
        /// </summary>
        public void EmitDeclareType(SourceTypeSymbol t)
        {
            Debug.Assert(t != null);

            // <ctx>.DeclareType<T>()
            EmitLoadContext();
            EmitCall(ILOpCode.Call, CoreMethods.Context.DeclareType_T.Symbol.Construct(t));
        }
Beispiel #37
0
 public SynthesizedStaticFieldsHolder(SourceTypeSymbol @class)
 {
     Contract.ThrowIfNull(@class);
     _class = @class;
 }
 public SynthesizedParameterlessPhpCtorSymbol(
     SourceTypeSymbol containingType, Accessibility accessibility,
     MethodSymbol defaultctor)
     : base(containingType, accessibility, false, defaultctor, null)
 {
 }
        /// <summary>
        /// Creates CLS constructors for a PHP class.
        /// </summary>
        /// <param name="type">PHP class.</param>
        /// <returns>Enumeration of instance constructors for PHP class.</returns>
        /// <remarks>
        /// Constructors are created with respect to <c>base..ctor</c> and class PHP constructor function.
        /// At least a single <c>.ctor</c> is created which initializes fields and calls <c>base..ctor</c>. This is main constructor needed to properly initialize the class.
        /// In case there is a PHP constructor function:
        /// - The first ctor is marked as protected and is used only by other ctors and by derived classes to initialize class without calling the PHP constructor function.
        /// - Another ctor is created in order to call the main constructor and call PHP constructor function.
        /// - Ghost stubs of the other ctor are created in order to pass default parameter values which cannot be stored in metadata (e.g. array()).
        /// </remarks>
        public static ImmutableArray <MethodSymbol> CreateCtors(SourceTypeSymbol type)
        {
            if (type.IsStatic || type.IsInterface)
            {
                return(ImmutableArray <MethodSymbol> .Empty);
            }

            // resolve php constructor
            var phpconstruct = type.ResolvePhpCtor(true); // this tells us what parameters are provided so we can select best overload for base..ctor() call

            // resolve base .ctor that has to be called
            var btype          = type.BaseType;
            var fieldsonlyctor = (MethodSymbol)(btype as IPhpTypeSymbol)?.InstanceConstructorFieldsOnly;   // base..ctor() to be called if provided
            var basectors      = (fieldsonlyctor != null)
                ? ImmutableArray.Create(fieldsonlyctor)
                : btype.InstanceConstructors
                                 .Where(c => c.DeclaredAccessibility != Accessibility.Private) // ignore inaccessible .ctors
                                 .OrderByDescending(c => c.ParameterCount)                     // longest ctors first
                                 .AsImmutable();

            // what parameters are provided
            var givenparams = (phpconstruct != null)
                ? phpconstruct.Parameters.Where(p => !p.IsImplicitlyDeclared && !p.IsParams).AsImmutable()
                : ImmutableArray <ParameterSymbol> .Empty;

            // first declare .ctor that initializes fields only and calls base .ctor
            var basector = ResolveBaseCtor(givenparams, basectors);

            if (basector == null)
            {
                // type.BaseType was not resolved, reported by type.BaseType
                // TODO: Err & ErrorMethodSymbol
                return(ImmutableArray <MethodSymbol> .Empty);
            }

            MethodSymbol defaultctor = null; // .ctor to be used by default
            var          ctors       = ImmutableArray.CreateBuilder <MethodSymbol>();

            // create .ctor(s)
            if (phpconstruct == null)
            {
                ctors.Add(defaultctor = new SynthesizedPhpCtorSymbol(type, Accessibility.Public, basector, null));
            }
            else
            {
                var fieldsinitctor = new SynthesizedPhpCtorSymbol(type, Accessibility.ProtectedOrInternal, basector, null)
                {
                    IsInitFieldsOnlyPrivate = true,
                    IsEditorBrowsableHidden = true,
                };
                ctors.Add(fieldsinitctor);

                if (!type.IsAbstract)
                {
                    //// generate .ctor(s) calling PHP __construct with optional overloads in case there is an optional parameter
                    //var ps = phpconstruct.Parameters;
                    //for (int i = 0; i < ps.Length; i++)
                    //{
                    //    if (ps[i].HasUnmappedDefaultValue())
                    //    {
                    //        yield return new SynthesizedPhpCtorSymbol(type, phpconstruct.DeclaredAccessibility, fieldsinitctor, phpconstruct, i);
                    //    }
                    //}

                    ctors.Add(defaultctor = new SynthesizedPhpCtorSymbol(type, phpconstruct.DeclaredAccessibility, fieldsinitctor, phpconstruct));
                }
            }

            // parameterless .ctor() with shared context
            if (defaultctor != null && defaultctor.DeclaredAccessibility == Accessibility.Public && type.DeclaredAccessibility == Accessibility.Public && !type.IsAbstract)
            {
                // Template:
                // [PhpHidden][CompilerGenerated]
                // void .ctor(...) : this(ContextExtensions.CurrentContext, ...) { }

                // NOTE: overload resolution will prioritize the overload with Context parameter over this one

                // argless ctor must be first!
                // used for various dependency-injection situations
                ctors.Insert(0, new SynthesizedParameterlessPhpCtorSymbol(type, Accessibility.Public, defaultctor));
            }

            //
            return(ctors.ToImmutable());
        }