コード例 #1
0
ファイル: Prototype.cs プロジェクト: Bablakeluke/Nitrassic
        /// <summary>
        /// Adds a property to this object, typically generating a field of the given type.
        /// </summary>
        /// <param name="name"> The name of the property to add. </param>
        /// <param name="attributes"> The property attributes. </param>
        internal PropertyVariable AddProperty(string name, Nitrassic.Library.PropertyAttributes attributes, Type valueType)
        {
            if (Properties == null)
            {
                Properties = new Dictionary <string, PropertyVariable>();
            }

            PropertyVariable sp = new PropertyVariable(this, name, attributes, valueType);

            Properties[name] = sp;

            return(sp);
        }
コード例 #2
0
ファイル: Prototype.cs プロジェクト: Bablakeluke/Nitrassic
        /// <summary>
        /// Adds the given method to the prototype.
        /// </summary>
        private void AddMethod(MethodBase method, Type type, int staticMode)
        {
            // Get the properties attribute if it's got one:
            var attribute = (JSProperties)Attribute.GetCustomAttribute(method, typeof(JSProperties));

            if (attribute != null && attribute.Hidden)
            {
                return;
            }

            // Determine the name of the method.
            string name;

            if (attribute != null && attribute.Name != null)
            {
                name = attribute.Name;
            }
            else
            {
                name = method.Name;
            }

            // Reject properties (but not constructors):
            if (method.IsSpecialName && name != ".ctor")
            {
                return;
            }

            ParameterInfo[] mParams = null;

            if (method.IsStatic && staticMode != 0)
            {
                // If it's static and it does not have a 'thisObj' property
                // then it's a constructor level static function, IF the object has a constructor at all.
                mParams = method.GetParameters();

                if (mParams.Length > 0)
                {
                    if (mParams[0].Name == "thisObj" || (mParams.Length > 1 && mParams[1].Name == "thisObj"))
                    {
                        // Not actually static.
                        if (staticMode == 2)
                        {
                            return;
                        }
                    }
                    else if (staticMode == 1)
                    {
                        return;
                    }
                }
            }

            bool enumerable = true;

            if (name == "OnConstruct" || name == ".ctor")
            {
                name       = ".make";
                enumerable = false;
            }
            else if (name == "OnCall")
            {
                name       = ".call";
                enumerable = false;
            }

            // Special case for get_ or set_ methods - we want them to act like properties.
            // Chop off get_ or set_ here (so the actual name entering the proto is correct)
            // then when the user attempts to use it like a property, it checks then.
            int actLikeProperty = 0;

            if (name.StartsWith("get_"))
            {
                name            = name.Substring(4);
                actLikeProperty = 1;
            }
            else if (name.StartsWith("set_"))
            {
                name            = name.Substring(4);
                actLikeProperty = 2;
            }

            // For methods, auto == lowercase.
            if (attribute == null)
            {
                name = char.ToLower(name[0]) + name.Substring(1);
            }
            else
            {
                // For methods, auto == lowercase
                if (attribute.FirstCharacter == CaseMode.Upper)
                {
                    name = char.ToUpper(name[0]) + name.Substring(1);
                }
                else if (attribute.FirstCharacter == CaseMode.Lower || attribute.FirstCharacter == CaseMode.Auto)
                {
                    name = char.ToLower(name[0]) + name.Substring(1);
                }
            }

            if (actLikeProperty != 0)
            {
                if (name == "_Item")
                {
                    // Rename! Actually got an indexer here.
                    name = "___item";

                    if (mParams == null)
                    {
                        mParams = method.GetParameters();
                    }

                    // Skip thisObj and engine if they're set:
                    for (int i = 0; i < mParams.Length; i++)
                    {
                        ParameterInfo p = mParams[i];

                        if (i < 2)
                        {
                            // Skip special parameters.

                            if (p.Name == "thisObj" || (i == 0 && p.ParameterType == typeof(ScriptEngine)))
                            {
                                continue;
                            }
                        }

                        // Append the type name:
                        name += "_" + p.ParameterType.Name;
                    }
                }
                else if (name == "_Properties")
                {
                    // Rename! Got the property enumerator here.
                    name = "___properties";
                }
            }

            // Check property attributes.
            Nitrassic.Library.PropertyAttributes descriptorAttributes = Nitrassic.Library.PropertyAttributes.Sealed;
            if (attribute != null && attribute.IsEnumerable && enumerable)
            {
                descriptorAttributes |= Nitrassic.Library.PropertyAttributes.Enumerable;
            }
            if (attribute == null || attribute.IsConfigurable)
            {
                descriptorAttributes |= Nitrassic.Library.PropertyAttributes.Configurable;
            }
            if (attribute == null || attribute.IsWritable)
            {
                descriptorAttributes |= Nitrassic.Library.PropertyAttributes.Writable;
            }

            // Already defined this property?
            PropertyVariable property = GetProperty(name);

            if (property == null)
            {
                // Add as a single method, optionally as a virtual property:
                object propertyValue;

                if (actLikeProperty == 0)
                {
                    // Straight apply the method:
                    propertyValue = method;
                }
                else
                {
                    // Create a virtual property:
                    VirtualProperty vProperty = new VirtualProperty();

                    // Apply the method:
                    if (actLikeProperty == 1)
                    {
                        vProperty.GetMethod = method;
                        vProperty.LoadMeta();
                    }
                    else
                    {
                        vProperty.SetMethod = method;
                    }

                    // Apply virtual property as the value:
                    propertyValue = vProperty;
                }

                property = AddProperty(name, propertyValue, descriptorAttributes);
            }
            else if (actLikeProperty != 0)
            {
                // Got the other method in a property.
                VirtualProperty vProperty = property.ConstantValue as VirtualProperty;

                // Apply the method:
                if (actLikeProperty == 1)
                {
                    vProperty.GetMethod = method;
                    vProperty.LoadMeta();
                }
                else
                {
                    vProperty.SetMethod = method;
                }
            }
            else
            {
                // Already a method set?
                MethodGroup group = property.ConstantValue as MethodGroup;

                if (group == null)
                {
                    // Create a method group and add the current method to it:
                    group = new MethodGroup();

                    // Set the attributes:
                    group.PropertyAttributes = descriptorAttributes;

                    // Add the method:
                    group.Add(property.ConstantValue as MethodBase);

                    // Force the property to change type:
                    property.ForceChange(group);
                }

                // Add this method to the group:
                group.Add(method);

                if (group.PropertyAttributes != descriptorAttributes)
                {
                    throw new InvalidOperationException("Inconsistant property attributes detected on " + method + ".");
                }
            }
        }