private static void AddDependentType(PhpTypeDesc /*!*/ selfType, List <KeyValuePair <string, DTypeDesc> > /*!*/ dependentTypes, DTypeDesc dependentType) { if (dependentType != null && dependentType is PhpTypeDesc && !IsSameCompilationUnit(selfType, dependentType)) { dependentTypes.Add(new KeyValuePair <string, DTypeDesc>(dependentType.MakeFullName(), dependentType)); } }
public static string GetCalledClass(DTypeDesc caller) { if (caller == null || caller.IsUnknown) { return(null); } return(caller.MakeFullName()); }
/// <summary> /// Generates Expression that throws a 'Protected method called' or 'Private method called' <see cref="PhpException"/>. /// </summary> /// <param name="method">The <see cref="DRoutineDesc"/>.</param> /// <param name="callerContext">The caller that was passed to method lookup or <B>null</B> /// if it should be determined by this method (by tracing the stack).</param> /// <remarks> /// This method is intended to be called after <see cref="DTypeDesc.GetMethod"/> has returned /// <see cref="GetMemberResult.BadVisibility"/> while performing a method lookup. /// </remarks> public static Expression /*!*/ ThrowVisibilityError(DRoutineDesc /*!*/ method, DTypeDesc /*!*/ callerContext) { if (method.IsProtected) { return(ThrowError("protected_method_called", method.DeclaringType.MakeFullName(), method.MakeFullName(), callerContext == null ? String.Empty : callerContext.MakeFullName())); } else if (method.IsPrivate) { return(ThrowError("private_method_called", method.DeclaringType.MakeFullName(), method.MakeFullName(), callerContext == null ? String.Empty : callerContext.MakeFullName())); } throw new NotImplementedException(); }
public static string GetParentClass(DTypeDesc caller, object classNameOrObject) { ScriptContext context = ScriptContext.CurrentContext; DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, true); if (type == null || type.IsInterface) { return(null); } DTypeDesc parent_type = type.Base; return(parent_type == null ? null : parent_type.MakeFullName()); }
/// <summary> /// Generates Expression that throws a 'Protected method called' or 'Private method called' <see cref="PhpException"/>. /// </summary> /// <param name="method">The <see cref="DRoutineDesc"/>.</param> /// <param name="callerContext">The caller that was passed to method lookup or <B>null</B> /// if it should be determined by this method (by tracing the stack).</param> /// <remarks> /// This method is intended to be called after <see cref="DTypeDesc.GetMethod"/> has returned /// <see cref="GetMemberResult.BadVisibility"/> while performing a method lookup. /// </remarks> public static Expression/*!*/ ThrowVisibilityError(DRoutineDesc/*!*/ method, DTypeDesc/*!*/ callerContext) { if (method.IsProtected) { return ThrowError("protected_method_called", method.DeclaringType.MakeFullName(), method.MakeFullName(), callerContext == null ? String.Empty : callerContext.MakeFullName()); } else if (method.IsPrivate) { return ThrowError("private_method_called", method.DeclaringType.MakeFullName(), method.MakeFullName(), callerContext == null ? String.Empty : callerContext.MakeFullName()); } throw new NotImplementedException(); }
public static PhpArray GetClassParents(DTypeDesc caller, object classNameOrObject, bool useAutoload) { ScriptContext context = ScriptContext.CurrentContext; DTypeDesc type = ClassNameOrObjectToType(context, null, caller, classNameOrObject, useAutoload); if (type == null || type.IsInterface) { return(null); } PhpArray result = new PhpArray(); while ((type = type.Base) != null) { string class_name = type.MakeFullName(); result.Add(class_name, class_name); } return(result); }
public static void UnsetStaticProperty(DTypeDesc type, object propertyName, DTypeDesc caller, ScriptContext context) { // convert propertyName to string string name = (propertyName == null ? String.Empty : Convert.ObjectToString(propertyName)); // throw the error PhpException.StaticPropertyUnset(type.MakeFullName(), name); }
/// <summary> /// Gets the <see cref="DPropertyDesc"/> of a static property of a class. /// </summary> /// <param name="type">The class to get the property of.</param> /// <param name="propertyName">The property name.</param> /// <param name="caller"><see cref="DTypeDesc"/> of the object that request the retrieval.</param> /// <param name="context">Current <see cref="ScriptContext"/>.</param> /// <param name="quiet">If <B>true</B>, the "property not found" exception should not be thrown.</param> /// <returns>The <see cref="DPropertyDesc"/> representing the static property or <B>null</B> if an error occurs.</returns> /// <exception cref="PhpException">The property denoted by <paramref name="propertyName"/> was not found. (Error)</exception> /// <exception cref="PhpException">The property is inaccessible due to its protected or private visibility level (Error). /// </exception> internal static DPropertyDesc GetStaticPropertyDesc(DTypeDesc type, object propertyName, DTypeDesc caller, ScriptContext context, bool quiet) { if (type == null) return null; // convert propertyName to string string name = (propertyName == null ? String.Empty : Convert.ObjectToString(propertyName)); // find the property DPropertyDesc property; switch (type.GetProperty(new VariableName(name), caller, out property)) { case GetMemberResult.NotFound: { if (!quiet) PhpException.UndeclaredStaticProperty(type.MakeFullName(), name); return null; } case GetMemberResult.BadVisibility: { if (!quiet) { PhpException.PropertyNotAccessible( property.DeclaringType.MakeFullName(), name, (caller == null ? String.Empty : caller.MakeFullName()), property.IsProtected); } return null; } case GetMemberResult.OK: { if (!property.IsStatic) goto case GetMemberResult.NotFound; break; } } // make sure that the property has been initialized for this request property.EnsureInitialized(context); return property; }
public static object GetClassConstant(DTypeDesc type, string constantName, DTypeDesc caller, ScriptContext context) { if (type == null) return null; // lookup the constant desc DConstantDesc constant; switch (type.GetConstant(new VariableName(constantName), caller, out constant)) { case GetMemberResult.NotFound: { PhpException.Throw(PhpError.Error, CoreResources.GetString("undefined_class_constant", type.MakeFullName(), constantName)); return null; } case GetMemberResult.BadVisibility: { PhpException.ConstantNotAccessible( constant.DeclaringType.MakeFullName(), constantName, (caller == null ? String.Empty : caller.MakeFullName()), constant.IsProtected); return null; } } // make sure that the constant has been initialized for this request return PhpVariable.Dereference(constant.GetValue(context)); }
public static string GetCalledClass(DTypeDesc caller) { if (caller == null || caller.IsUnknown) return null; return caller.MakeFullName(); }
/// <summary> /// Specifies dynamic behavior for set operation for a constant /// </summary> public override bool TrySetMember( SetMemberBinder binder, Object value ) { if (type != null) { PhpException.Throw(PhpError.Error, String.Format(PHP.Core.Localizations.Strings.constant_redefined, type.MakeFullName() + Name.ClassMemberSeparator + binder.Name)); return(true); } Context.DefineConstant(GetFullName(binder.Name), value); return(true); }
private static void ReportErrorMakingInstantiation(DTypeDesc.MakeGenericArgumentsResult/*!*/ error, DTypeDesc/*!*/ genericType, DTypeDesc argument, GenericParameterDesc/*!*/ parameter) { switch (error) { case DTypeDesc.MakeGenericArgumentsResult.IncompatibleConstraint: PhpException.Throw(PhpError.Error, CoreResources.GetString("incompatible_type_parameter_constraints_type", argument.MakeFullName(), parameter.RealType.GenericParameterPosition, parameter.RealType.Name)); break; case DTypeDesc.MakeGenericArgumentsResult.MissingArgument: PhpException.Throw(PhpError.Error, CoreResources.GetString("missing_type_argument_in_type_use", genericType.MakeFullName(), parameter.RealType.GenericParameterPosition, parameter.RealType.Name)); break; case DTypeDesc.MakeGenericArgumentsResult.TooManyArguments: PhpException.Throw(PhpError.Warning, CoreResources.GetString("too_many_type_arguments_in_type_use", genericType.MakeFullName(), genericType.GenericParameters.Length)); break; } }
public static string GetGenericArg(int index) { DTypeDesc type_desc = ScriptContext.CurrentContext.Stack.GetTypeArgument(index); return((type_desc != null) ? type_desc.MakeFullName() : null); }
private DynamicMetaObject /*!*/ FallbackInvokeMember(DynamicMetaObject target /*!*/, DynamicMetaObject /*!*/[] /*!*/ args) { // determine run time values and additional restrictions: DTypeDesc classContext = this._classContext; string fieldName = this._fieldName; BindingRestrictions restrictions = BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType); //target.Restrictions; int currentArg = 0; if (!ClassContextIsKnown) { Debug.Assert(args.Length > currentArg, "Not enough arguments!"); Debug.Assert(args[currentArg].Value == null || Types.DTypeDesc[0].IsAssignableFrom(args[currentArg].LimitType), "Wrong class context type!"); classContext = (DTypeDesc)args[currentArg].Value; Debug.Assert(classContext == null || !classContext.IsUnknown, "Class context should be known at run time!"); restrictions = restrictions.Merge(BindingRestrictions.GetInstanceRestriction(args[currentArg].Expression, classContext)); currentArg++; } if (IsIndirect) { Debug.Assert(args.Length > currentArg, "Not enough arguments!"); Debug.Assert(Types.String[0].IsAssignableFrom(args[currentArg].LimitType), "Wrong field name type!"); fieldName = (string)args[currentArg].Value; restrictions = restrictions.Merge( BindingRestrictions.GetExpressionRestriction( Expression.Equal( args[currentArg].Expression, Expression.Constant(fieldName, Types.String[0])))); currentArg++; } // ////Debug.Assert(!(var is PhpReference) && name != null); Debug.Assert(target.HasValue && target.LimitType != Types.PhpReference[0], "Target should not be PhpReference!"); ////if (ReferenceEquals(obj, ScriptContext.SetterChainSingletonObject)) ////{ //// ScriptContext.CurrentContext.AbortSetterChain(false); //// return new PhpReference(); ////} if (WantReference && ReferenceEquals(target.Value, ScriptContext.SetterChainSingletonObject)) { // GetObjectPropertyRef: Func <PhpReference> abortSetterChain = () => { ScriptContext.CurrentContext.AbortSetterChain(false); return(new PhpReference()); }; return(new DynamicMetaObject( Expression.Call(abortSetterChain.Method), BindingRestrictions.GetInstanceRestriction(target.Expression, ScriptContext.SetterChainSingletonObject) )); } DObject obj; ////// a property of a DObject: if ((obj = target.Value as DObject) != null) { if (obj is ClrObject /*|| obj is IClrValue // IClrValue -> ClrValue<T> -> already in restriction */) { // ((DObject)target).RealType == <obj>.RealType restrictions = restrictions.Merge( BindingRestrictions.GetInstanceRestriction( Expression.Property(Expression.Convert(target.Expression, Types.DObject[0]), Properties.DObject_RealType), obj.RealType)); } //// return GetObjectProperty(obj, name, caller, quiet); DPropertyDesc property; GetMemberResult result = obj.TypeDesc.GetInstanceProperty(new VariableName(fieldName), classContext, out property); switch (result) { case GetMemberResult.OK: ////object value = property.Get(this); ////PhpReference reference = value as PhpReference; if (property.Member is PhpField || property.Member is PhpVisibleProperty) { var realType = property.DeclaringType.RealType; FieldInfo realField = (property.Member is PhpField) ? property.PhpField.RealField : null; PropertyInfo realProperty = (property.Member is PhpVisibleProperty) ? ((PhpVisibleProperty)property.Member).RealProperty : null; Debug.Assert(realField != null ^ realProperty != null); MemberExpression getter = null; if (realField != null) { getter = Expression.Field(Expression.Convert(target.Expression, realType), realField); } else if (realProperty != null) { getter = Expression.Property(Expression.Convert(target.Expression, realType), realProperty); } if (Types.PhpReference[0].IsAssignableFrom(getter.Type)) { var reference = Expression.Variable(Types.PhpReference[0]); var assignment = Expression.Assign(reference, getter); if (WantReference) { ////value = property.Get(this); ////reference = value as PhpReference; var returnLabel = Expression.Label(this._returnType); ////if (reference != null && reference.IsSet) ////{ //// reference.IsAliased = true; //// return reference; ////} var isset = Expression.IfThen( Expression.Property(assignment, Properties.PhpReference_IsSet), Expression.Block( Expression.Assign(Expression.Property(reference, Properties.PhpReference_IsAliased), Expression.Constant(true)), Expression.Return(returnLabel, reference))); ////// the CT property has been unset -> try to invoke __get ////PhpReference get_ref = InvokeGetterRef(name, caller, out getter_exists); ////if (getter_exists) return (get_ref == null ? new PhpReference() : get_ref); ////if (reference == null) ////{ //// reference = new PhpReference(value); //// property.Set(this, reference); ////} ////else ////{ //// reference.IsAliased = true; //// reference.IsSet = true; ////} Func <DObject, string, DTypeDesc, PhpReference, PhpReference> notsetOperation = (self, name, caller, refrnc) => { bool getter_exists; // the CT property has been unset -> try to invoke __get PhpReference get_ref = self.InvokeGetterRef(name, caller, out getter_exists); if (getter_exists) { return(get_ref ?? new PhpReference()); } Debug.Assert(refrnc != null); refrnc.IsAliased = true; refrnc.IsSet = true; return(refrnc); }; ////return reference; return(new DynamicMetaObject( Expression.Block(this._returnType, new[] { reference }, new Expression[] { isset, Expression.Label(returnLabel, Expression.Call(null, notsetOperation.Method, Expression.Convert(target.Expression, Types.DObject[0]), Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0]), reference)) }), restrictions)); } else { ////if (reference != null && !reference.IsSet) ////{ //// // the property is CT but has been unset //// if (issetSemantics) //// { //// bool handled; //// return PropertyIssetHandler(name, caller, out handled); //// } //// else return GetRuntimeField(name, caller); ////} ////else return value; Func <DObject, string, DTypeDesc, object> notsetOperation; if (_issetSemantics) { notsetOperation = (self, name, caller) => { return(PhpVariable.Dereference(self.GetRuntimeField(name, caller))); } } ; else { notsetOperation = (self, name, caller) => { bool handled; return(PhpVariable.Dereference(self.PropertyIssetHandler(name, caller, out handled))); } }; var value = Expression.Block(this._returnType, new[] { reference }, Expression.Condition( Expression.Property(assignment, Properties.PhpReference_IsSet), Expression.Field(reference, Fields.PhpReference_Value), Expression.Call(null, notsetOperation.Method, Expression.Convert(target.Expression, Types.DObject[0]), Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0])) )); return(new DynamicMetaObject(value, restrictions)); } } else { if (WantReference) { return(new DynamicMetaObject( Expression.New(Constructors.PhpReference_Object, Expression.Convert(getter, Types.Object[0])), restrictions)); } else { return(new DynamicMetaObject( Expression.Call(Methods.PhpVariable.Dereference, Expression.Convert(getter, Types.Object[0])), restrictions)); } } } else if (property.Member is ClrProperty) { var realType = property.DeclaringType.RealType; var realProperty = property.ClrProperty.RealProperty; // (target.{RealObject|realValue}).<realProperty> Expression value = Expression.Convert( BinderHelper.ClrObjectWrapDynamic( Expression.Property( BinderHelper.ClrRealObject(target, realType), realProperty)), Types.Object[0]); if (WantReference) { value = BinderHelper.MakePhpReference(value); } return(new DynamicMetaObject(value, restrictions)); } else if (property.Member is ClrField) { var realType = property.DeclaringType.RealType; var realField = property.ClrField.FieldInfo; // (target.{RealObject|realValue}).<realField> Expression value = Expression.Convert( BinderHelper.ClrObjectWrapDynamic( Expression.Field( BinderHelper.ClrRealObject(target, realType), realField)), Types.Object[0]); if (WantReference) { value = BinderHelper.MakePhpReference(value); } return(new DynamicMetaObject(value, restrictions)); } else if (property.Member is ClrEvent) { var clrEvent = (ClrEvent)property.Member; var realType = property.DeclaringType.RealType; // emit stub that Wraps event as [ ClrEventObject<handlerType>.Wrap(<SC>, <event name>, <addMethod>, <removeMethod>) ] var stub = new System.Reflection.Emit.DynamicMethod( string.Format("event<{0}>", fieldName), Types.DObject[0], new[] { realType }, realType); var il = new ILEmitter(stub); clrEvent.EmitGetEventObject( il, new Place(null, Properties.ScriptContext_CurrentContext), new IndexedPlace(PlaceHolder.Argument, 0), false); il.Emit(System.Reflection.Emit.OpCodes.Ret); Expression value = Expression.Call(stub, BinderHelper.ClrRealObject(target, realType)); if (WantReference) { value = BinderHelper.MakePhpReference(value); } return(new DynamicMetaObject(value, restrictions)); } else { throw new NotImplementedException(); } case GetMemberResult.NotFound: if (WantReference) { Func <DObject, string, DTypeDesc, PhpReference> op = (self, name, caller) => { PhpReference reference; bool getter_exists; // search in RT fields if (self.RuntimeFields != null && self.RuntimeFields.ContainsKey(name)) { var namekey = new IntStringKey(name); return(self.RuntimeFields.table._ensure_item_ref(ref namekey, self.RuntimeFields)); } // property is not present -> try to invoke __get reference = self.InvokeGetterRef(name, caller, out getter_exists); if (getter_exists) { return((reference == null) ? new PhpReference() : reference); } // (no notice/warning/error thrown by PHP) // add the field reference = new PhpReference(); if (self.RuntimeFields == null) { self.RuntimeFields = new PhpArray(); } self.RuntimeFields[name] = reference; return(reference); }; return(new DynamicMetaObject( Expression.Call(null, op.Method, Expression.Convert(target.Expression, Types.DObject[0]), Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0])), restrictions)); } else { ////if (issetSemantics) ////{ //// OrderedHashtable<string>.Element element; //// if (RuntimeFields != null && (element = RuntimeFields.GetElement(name)) != null) //// { //// return element.Value; //// } //// else //// { //// bool handled; //// return PropertyIssetHandler(name, caller, out handled); //// } ////} ////else return GetRuntimeField(name, caller); if (_issetSemantics) { Func <DObject, string, DTypeDesc, object> notsetOperation = (self, name, caller) => { if (self.RuntimeFields != null) { object value; if (self.RuntimeFields.TryGetValue(name, out value)) { return(value); } } bool handled; return(self.PropertyIssetHandler(name, caller, out handled)); }; return(new DynamicMetaObject( Expression.Call(Methods.PhpVariable.Dereference, Expression.Call(null, notsetOperation.Method, Expression.Convert(target.Expression, Types.DObject[0]), Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0]))), restrictions)); } else { return(new DynamicMetaObject( Expression.Call( Methods.PhpVariable.Dereference, Expression.Call( Expression.Convert(target.Expression, Types.DObject[0]), Methods.DObject_GetRuntimeField, Expression.Constant(fieldName), Expression.Constant(classContext, Types.DTypeDesc[0]))), restrictions)); }; } case GetMemberResult.BadVisibility: { ////PhpException.PropertyNotAccessible( //// property.DeclaringType.MakeFullName(), //// name.ToString(), //// (caller == null ? String.Empty : caller.MakeFullName()), //// property.IsProtected); string stringResourceKey = property.IsProtected ? "protected_property_accessed" : "private_property_accessed"; return(new DynamicMetaObject( Expression.Block(this._returnType, Expression.Call(null, Methods.PhpException.Throw, Expression.Constant(PhpError.Error, Types.PhpError_String[0]), Expression.Constant(CoreResources.GetString(stringResourceKey, property.DeclaringType.MakeFullName(), fieldName, (classContext == null ? String.Empty : classContext.MakeFullName())))), WantReference ? (Expression)Expression.New(Constructors.PhpReference_Void) : Expression.Constant(null) ), restrictions)); } } } ////// warnings: ////if (!quiet) // not in isset() operator only ////{ if (!_issetSemantics) { //// if (PhpVariable.IsEmpty(var)) //// // empty: //// PhpException.Throw(PhpError.Notice, CoreResources.GetString("empty_used_as_object")); //// else //// // PhpArray, string, scalar type: //// PhpException.VariableMisusedAsObject(var, false); Action <object> error = (var) => { if (PhpVariable.IsEmpty(var)) { // empty: PhpException.Throw(PhpError.Notice, CoreResources.GetString("empty_used_as_object")); } else { // PhpArray, string, scalar type: PhpException.VariableMisusedAsObject(var, false); } }; return(new DynamicMetaObject( Expression.Block(this._returnType, Expression.Call(error.Method, target.Expression), WantReference ? (Expression)Expression.New(Constructors.PhpReference_Void) : Expression.Constant(null)), (target.HasValue && target.Value == null) ? BindingRestrictions.GetInstanceRestriction(target.Expression, null) : BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); } ////} ////// property does not exist ////return null; return(new DynamicMetaObject( Expression.Constant(null), (target.HasValue && target.Value == null) ? BindingRestrictions.GetInstanceRestriction(target.Expression, null) : BindingRestrictions.GetTypeRestriction(target.Expression, target.LimitType))); }
public virtual object __construct(ScriptContext context, object @class, object methodname) { string methodnameStr = PhpVariable.AsString(methodname); this.dtype = null; this.method = null; DObject dobj; if ((dobj = (@class as DObject)) != null) { this.dtype = dobj.TypeDesc; } else { var str = PhpVariable.AsString(@class); if (str != null) { this.dtype = context.ResolveType(str, null, null, null, ResolveTypeFlags.UseAutoload); } if (this.dtype == null) { PhpException.Throw(PhpError.Error, string.Format("Class {0} does not exist", str)); return(false); } } if (this.dtype.GetMethod(new Name(methodnameStr), dtype, out this.method) == GetMemberResult.NotFound) { PhpException.Throw(PhpError.Error, string.Format("Method {0}::{1}() does not exist", dtype.MakeFullName(), methodnameStr)); return(false); } return(null); }
/// <summary> /// Attemps to find a method desc according to a given class name and method name. Used when /// a non-virtual dispatch is about to be performed and when a <c>array(class, method)</c> /// callback is being bound. /// </summary> /// <param name="requestedType">The type whose method should be returned.</param> /// <param name="methodName">The method name.</param> /// <param name="self">Current <c>$this</c>. Will be set to an instance, on which the resulting /// CLR method should be invoked (<B>null</B> if the CLR method is static).</param> /// <param name="caller"><see cref="Type"/> of the object that request the lookup.</param> /// <param name="context">Current <see cref="ScriptContext"/>.</param> /// <param name="quiet">If <B>true</B>, no exceptions will be thrown if an error occurs.</param> /// <param name="removeFrame">If <B>true</B>, <see cref="PhpStack.RemoveFrame"/> will be called /// before throwing an exception.</param> /// <param name="isCallerMethod">Will be set to true, if required method was not found but __callStatic was.</param> /// <returns>The <see cref="DRoutineDesc"/> or <B>null</B> on error.</returns> internal static DRoutineDesc GetStaticMethodDesc(DTypeDesc requestedType, string methodName, ref DObject self, DTypeDesc caller, ScriptContext context, bool quiet, bool removeFrame, out bool isCallerMethod) { Debug.Assert(requestedType != null); isCallerMethod = false; DRoutineDesc method; GetMemberResult result = requestedType.GetMethod(new Name(methodName), caller, out method); if (result == GetMemberResult.NotFound) { // if not found, perform __callStatic or __call 'magic' method lookup Name callMethod = (self != null && requestedType.IsAssignableFrom(self.TypeDesc)) ? Name.SpecialMethodNames.Call : Name.SpecialMethodNames.CallStatic; if ((result = requestedType.GetMethod(callMethod, caller, out method)) != GetMemberResult.NotFound) { isCallerMethod = true; } else { // there is no such method in the class if (removeFrame) context.Stack.RemoveFrame(); if (!quiet) PhpException.UndefinedMethodCalled(requestedType.MakeFullName(), methodName); return null; } } if (result == GetMemberResult.BadVisibility) { if (removeFrame) context.Stack.RemoveFrame(); if (!quiet) { PhpException.MethodNotAccessible( method.DeclaringType.MakeFullName(), method.MakeFullName(), (caller == null ? String.Empty : caller.MakeFullName()), method.IsProtected); } return null; } // check whether the method is abstract if (method.IsAbstract) { if (removeFrame) context.Stack.RemoveFrame(); if (!quiet) PhpException.AbstractMethodCalled(method.DeclaringType.MakeFullName(), method.MakeFullName()); return null; } if (method.IsStatic) { self = null; } else { // check whether self is of acceptable type if (self != null && !method.DeclaringType.RealType.IsInstanceOfType(self.RealObject)) self = null; /* // PHP allows for static invocations of instance method if (self == null && (requestedType.IsAbstract || !(requestedType is PhpTypeDesc)) && (method.DeclaringType.IsAbstract || !(method.DeclaringType is PhpTypeDesc))) { // calling instance methods declared in abstract classes statically through abstract classes // is unsupported - passing null as 'this' to such instance method could result in // NullReferenceException even if the method does not touch $this if (removeFrame) context.Stack.RemoveFrame(); if (!quiet) { PhpException.Throw(PhpError.Error, CoreResources.GetString("nonstatic_method_called_statically", method.DeclaringType.MakeFullName(), method.MakeFullName())); } return null; } if (self == null) { if (!quiet && !context.Config.Variables.ZendEngineV1Compatible) { PhpException.Throw(PhpError.Strict, CoreResources.GetString("nonstatic_method_called_statically", method.DeclaringType.MakeFullName(), method.MakeFullName())); } // create a dummy instance to be passed as 'this' to the instance method DTypeDesc dummy_type = (!requestedType.IsAbstract && requestedType is PhpTypeDesc) ? requestedType : method.DeclaringType; self = PhpFunctionUtils.InvokeConstructor( dummy_type, //Emit.Types.ScriptContext_Bool, context, false); }*/ // // The code above was commented and replaced with following. // // We can call instance method, and pass null as 'this', and expect // it can fail with NullReferenceException (even if the method does not touch $this). // // Note this solution has no side effect as above - invoking constructor of dummy instance. // // !! self can be null !! if (self == null) { if (!quiet /*&& !context.Config.Variables.ZendEngineV1Compatible*/) { PhpException.Throw(PhpError.Strict, CoreResources.GetString("nonstatic_method_called_statically", method.DeclaringType.MakeFullName(), method.MakeFullName())); } } } return method; }
public static object New(DTypeDesc type, DTypeDesc caller, ScriptContext context, NamingContext nameContext) { // error has been thrown by Convert.ObjectToTypeDesc or MakeGenericTypeInstantiation if (type == null) { context.Stack.RemoveFrame(); return null; } // interfaces and abstract classes cannot be instantiated if (type.IsAbstract) { context.Stack.RemoveFrame(); PhpException.CannotInstantiateType(type.MakeFullName(), type.IsInterface); return null; } return type.New(context.Stack, caller, nameContext); }
private static void AddDependentType(PhpTypeDesc/*!*/selfType, List<KeyValuePair<string, DTypeDesc>>/*!*/dependentTypes, DTypeDesc dependentType) { if (dependentType != null && dependentType is PhpTypeDesc && dependentType.RealType.Module != selfType.RealType.Module)// base type if from different module (external dependency) dependentTypes.Add(new KeyValuePair<string, DTypeDesc>(dependentType.MakeFullName(), dependentType)); }
public static string GetFullyQualifiedName(DTypeDesc type) { if (type == null) return string.Empty; return type.MakeFullName(); }
private static void AddDependentType(PhpTypeDesc/*!*/selfType, List<KeyValuePair<string, DTypeDesc>>/*!*/dependentTypes, DTypeDesc dependentType) { if (dependentType != null && dependentType is PhpTypeDesc && !IsSameCompilationUnit(selfType, dependentType)) dependentTypes.Add(new KeyValuePair<string, DTypeDesc>(dependentType.MakeFullName(), dependentType)); }