/// <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); }
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(); }
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)); } }
/// <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); }
/// <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; }
/// <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); }
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(); }
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(); }
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(); }
/// <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); }
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; } } }
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; }
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); }
/// <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 // ... }
public SynthesizedPhpCtorSymbol(SourceTypeSymbol /*!*/ container) : base(container) { _parameters = default(ImmutableArray <ParameterSymbol>); // lazy initialized }
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 }
/// <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 }
internal TypeRefContext(SourceUnit sourceUnit, SourceTypeSymbol containingType) { _sourceUnit = sourceUnit; _typeRefs = new List<ITypeRef>(); _containingType = containingType; }
/// <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)); } }); }
public SynthesizedTraitFieldSymbol(SourceTypeSymbol containing, FieldSymbol traitInstanceField, IPhpPropertySymbol sourceField) : base(containing, null, sourceField.Name, sourceField.DeclaredAccessibility, isStatic: false, isReadOnly: false) { _traitInstanceField = traitInstanceField; _traitmember = sourceField; }
/// <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)); }
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()); }