Ejemplo n.º 1
0
        /// <summary>
        /// Do prop1 and prop2 have the same name and signature?
        /// </summary>
        internal static bool AreSame(this NetPropertyDefinition prop1, NetPropertyDefinition prop2)
        {
            if (prop1.Name != prop2.Name)
            {
                return(false);
            }
            if (!prop1.PropertyType.AreSame(prop2.PropertyType))
            {
                return(false);
            }
            var count = prop1.Parameters.Count;

            if (count != prop2.Parameters.Count)
            {
                return(false);
            }
            for (var i = 0; i < count; i++)
            {
                if (!prop1.Parameters[i].ParameterType.AreSame(prop2.Parameters[i].ParameterType))
                {
                    return(false);
                }
            }
            return(true);
        }
Ejemplo n.º 2
0
 private void RemoveProperty(NetPropertyDefinition prop)
 {
     if (prop.Getter != null)
     {
         prop.Getter.Property = null;
     }
     if (prop.Setter != null)
     {
         prop.Setter.Property = null;
     }
     typeDef.Properties.Remove(prop);
 }
Ejemplo n.º 3
0
        public static bool IsNameClash(NetTypeDefinition typeDef, NetPropertyDefinition prop)
        {
            if ((prop.Getter ?? prop.Setter).InterfaceType != null)
            {
                return(false);
            }

            var name = prop.Name;

            return(prop.Name == typeDef.Name ||
                   typeDef.NestedTypes.Any(x => x.Name == name) ||
                   typeDef.Methods.Any(x => (x != prop.Getter && x != prop.Setter) && (x.Name == name)));
        }
Ejemplo n.º 4
0
            private void AddToProperty(NetTypeDefinition typeDef, NetMethodDefinition method, MethodDefinition ilMethod)
            {
                var ilProp = ilMethod.DeclaringType.Properties.First(p => p.SetMethod == ilMethod || p.GetMethod == ilMethod);

                if (ilProp.Parameters.Count > 0) //no need to handle indexers for now
                {
                    return;
                }

                var propType = ilMethod.IsGetter ? method.ReturnType : method.Parameters[0].ParameterType;

                var prop = typeDef.Properties.FirstOrDefault(p => p.Name == ilProp.Name
                                                             //&& p.Parameters.Count == ilProp.Parameters.Count
                                                             && p.PropertyType == propType &&
                                                             p.MainMethod.InterfaceType.AreSame(method.InterfaceType));

                if (prop == null)
                {
                    prop                      = new NetPropertyDefinition();
                    prop.Name                 = ilProp.Name;
                    prop.Description          = method.Description;
                    prop.DeclaringType        = method.DeclaringType;
                    prop.EditorBrowsableState = method.EditorBrowsableState;
                    prop.CustomAttributes.AddRange(method.CustomAttributes);
                    typeDef.Properties.Add(prop);
                }

                if (ilMethod.IsGetter)
                {
                    prop.Getter = method;
                }
                else
                {
                    prop.Setter = method;
                }
            }
Ejemplo n.º 5
0
        /// <summary>
        /// Build properties for the given type
        /// </summary>
        internal void BuildProperties(TargetFramework target, MethodRenamer methodRenamer)
        {
            if (typeDef.IsInterface)
            {
                return;
            }

            var getters        = typeDef.Methods.Where(IsGetter).ToList();
            var setters        = typeDef.Methods.Where(IsSetter).ToList();
            var generatedNames = new HashSet <string>();

            foreach (var getMethod in getters)
            {
                // Get the name of the property
                var name = GetPropertyName(getMethod);

                // If there are other methods with same name, we do not create a property
                if (typeDef.Methods.Any(x => (x != getMethod) && (x.Name == name)))
                {
                    continue;
                }
                if (typeDef.NestedTypes.Any(x => x.Name == name))
                {
                    continue;
                }
                if (typeDef.Name == name)
                {
                    continue;
                }
                if (typeDef.Fields.Any(x => x.Name == name))
                {
                    continue;
                }
                if (!generatedNames.Add(name + "_" + getMethod.Parameters.Count))
                {
                    continue;
                }

                // Create property
                var prop = new NetPropertyDefinition {
                    Name = name, Getter = getMethod, Description = getMethod.Description
                };

                AddCustomAttributes(getMethod, prop.CustomAttributes);

                // Clone parameters
                if (getMethod.Parameters.Any())
                {
                    prop.Parameters.AddRange(getMethod.Parameters.Select(x => new NetParameterDefinition(x.Name, x.ParameterType, false)));
                    prop.Name = "this";
                }

                // Rename getMethod if needed
                if (getMethod.Name == prop.Name)
                {
                    methodRenamer.Rename(getMethod, "Get" + getMethod.Name);
                }

                // Find setter
                var setMethod = FindSetter(getMethod, setters);
                if (setMethod != null)
                {
                    prop.Setter = setMethod;

                    // Rename setMethod if needed
                    if (setMethod.Name == prop.Name)
                    {
                        methodRenamer.Rename(setMethod, "Set" + setMethod.Name);
                    }
                }

                // Add property
                typeDef.Properties.Add(prop);
            }
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Should the given property be excluded from fixup?
 /// </summary>
 private static bool DoNotFixOverridenProperty(NetPropertyDefinition prop)
 {
     return(prop.Name == "Adapter");
 }
Ejemplo n.º 7
0
        /// <summary>
        /// Create code for the given property
        /// </summary>
        private void CreatePropertyCode(NetPropertyDefinition prop)
        {
            CreateComments(prop.Description, prop.Getter.OriginalJavaName);
            CreateAttributes(prop.CustomAttributes, prop);
            writer.Write(indent);
            writer.Write(Convert(prop.Getter, prop.Getter.Attributes, context.GenerateExternalMethods, true));
            writer.Write(CreateRef(prop.PropertyType, true, true, true, false, prop.DeclaringType, target));
            writer.Write(" ");
            writer.Write(prop.Name);

            if (prop.Parameters.Any())
            {
                writer.Write("[");
                var needComma = false;
                var pIndex    = 0;
                foreach (var p in prop.Parameters)
                {
                    if (needComma)
                    {
                        writer.Write(", ");
                    }
                    writer.Write(CreateRef(p.ParameterType, false, true, true, false, prop.DeclaringType, target));
                    writer.Write(pIndex == 0 ? " index" : string.Format(" p{0}", pIndex));
                    pIndex++;
                    needComma = true;
                }
                writer.Write("]");
            }

            // Create method body
            var isAbstract = prop.Getter.IsAbstract;

            writer.WriteLine();

            writer.Write(indent);
            writer.WriteLine("{");

            CreateAttributes(prop.Getter.CustomAttributes, prop.Getter);
            writer.Write(indent);
            writer.Write("\t\tget");

            bool isEmptyMethod = false; // isAbstract || context.GenerateExternalMethods;

            if (!isEmptyMethod)
            {
                ////writer.Write("{ return default(");
                ////writer.Write(CreateRef(prop.PropertyType, false, true, true, prop.DeclaringType));
                ////writer.Write("); }");
                writer.Write("{{ return {0}({1}); }}", prop.Getter.Name, string.Join(", ", prop.Getter.Parameters.Select((x, i) => (i == 0) ? "index" : x.Name)));
            }
            else
            {
                writer.Write(";");
            }
            writer.WriteLine();

            if (prop.Setter != null)
            {
                CreateAttributes(prop.Setter.CustomAttributes, prop.Setter);
                writer.Write(indent);
                writer.Write("\t\tset");
                if (!isEmptyMethod)
                {
                    writer.Write("{{ {0}({1}); }}", prop.Setter.Name,
                                 string.Join(", ", prop.Setter.Parameters.Select((x, i) => (i == 0) ? "value" : x.Name)));
                }
                else
                {
                    writer.Write(";");
                }
                ////writer.Write(!isAbstract && !context.GenerateExternalMethods ? "{ }" : ";");
                writer.WriteLine();
            }

            writer.Write(indent);
            writer.WriteLine("}");

            writer.WriteLine();
        }
Ejemplo n.º 8
0
 private static bool IsAnyOverride(NetPropertyDefinition prop)
 {
     return((prop.Getter != null && prop.Getter.IsOverride) ||
            (prop.Setter != null && prop.Setter.IsOverride));
 }
Ejemplo n.º 9
0
        /// <summary>
        /// Remove all properties that override / implement a property that does not exist.
        ///
        /// Will also fix property visibility.
        /// </summary>
        private void FixOverridenProperties(MethodRenamer methodRenamer, TargetFramework target)
        {
            if (!typeDef.Properties.Any())
            {
                return;
            }

            // handle overiding properties
            var allBaseTypes      = typeDef.GetBaseTypes(true);
            var allBaseProperties = allBaseTypes.SelectMany(x => x.GetElementType().Properties).ToList();

            var overridingProperties = typeDef.Properties.Where(x => IsAnyOverride(x) && !DoNotFixOverridenProperty(x)).ToList();

            for (int i = 0; i < overridingProperties.Count; ++i)
            {
                var prop = overridingProperties[i];

                NetPropertyDefinition matchingBaseProp = null;

                if (prop.Getter != null)
                {
                    // Note: this logic might need to be also applied for the "lone" setter logic below.
                    foreach (var baseProp in allBaseProperties.Where(p => p.Name == prop.Name))
                    {
                        var basePropType = GenericParameters.Resolve(baseProp.PropertyType, prop.DeclaringType, target.TypeNameMap);
                        if (!prop.PropertyType.AreSame(basePropType))
                        {
                            continue;
                        }
                        matchingBaseProp = baseProp;
                        break;
                    }

                    // Check for existing property in base class
                    if (matchingBaseProp == null)
                    {
                        // implement as normal method.
                        RemoveProperty(prop);
                        continue;
                    }

                    // Check for base property with setter
                    if (prop.Setter != null)
                    {
                        if (matchingBaseProp.Setter == null)
                        {
                            // Remove setter
                            prop.Setter.Property = null;
                            prop.Setter          = null;
                            continue;
                        }
                    }
                }
                else
                {
                    // this is a "lone" setter. for boolean setters, the name might have changed.
                    // try to match all base properties, update the name if neccessary.
                    foreach (var baseProp in allBaseProperties.Where(g => g.Getter != null && g.Setter != null))
                    {
                        if (FindSetter(baseProp.Getter, new[] { prop.Setter }, true) != null)
                        {
                            if (baseProp.Setter.IsVirtual)
                            {
                                if (matchingBaseProp == null || prop.Name == baseProp.Name)
                                {
                                    matchingBaseProp = baseProp;
                                }
                            }
                        }
                    }
                    if (matchingBaseProp == null)
                    {
                        // remove the property alltogether
                        prop.Setter.Property = null;
                        typeDef.Properties.Remove(prop);
                        continue;
                    }

                    prop.Name = matchingBaseProp.Name;
                }


                // We  must implement the property, since we inherited it.
                // Fix up any clashes.

                // clashes with explicit implementations should not occur.
                if ((prop.Getter ?? prop.Setter).InterfaceType != null)
                {
                    continue;
                }

                var propName = prop.Name;
                if (propName == typeDef.Name)
                {
                    if (!matchingBaseProp.DeclaringType.IsInterface)
                    {
                        Console.Error.WriteLine("Warning: Inherited property {0}::{1} clashes with type name. Skipping generation of property and methods.", typeDef.FullName, propName);
                        typeDef.Properties.Remove(prop);
                        typeDef.Methods.Remove(prop.Getter);
                        typeDef.Methods.Remove(prop.Setter);
                        continue;
                    }

                    // make this an explicit interface implementtion.

                    // TODO: We might also want to keep a renamed property in this case,
                    //       too allow access to the property from the class.
                    //       Also, the explicit implementation does not need a "JavaImport" attribute.
                    Console.Error.WriteLine("Warning: Inherited property {0}::{1} clashes with type name. Generating explicit implementation.", typeDef.FullName, propName);

                    if (prop.Getter != null)
                    {
                        if (matchingBaseProp.Getter != null)
                        {
                            prop.Getter.SetExplicitImplementation(matchingBaseProp.Getter, matchingBaseProp.DeclaringType);
                        }
                        else
                        {
                            prop.Getter = null;
                        }
                    }
                    if (prop.Setter != null)
                    {
                        if (matchingBaseProp.Setter != null)
                        {
                            prop.Setter.SetExplicitImplementation(matchingBaseProp.Setter, matchingBaseProp.DeclaringType);
                        }
                        else
                        {
                            prop.Setter = null;
                        }
                    }
                    continue;
                }

                if (typeDef.NestedTypes.Any(x => x.Name == propName))
                {
                    Console.Error.WriteLine("Warning: Inherited property {0}::{1} clashes with nested type. Renaming nested type, but consider renaming the property instead.", typeDef.FullName, propName);
                    typeDef.NestedTypes.Where(x => x.Name == propName).ForEach(t => t.Name += "FixMe");
                }

                foreach (var clash in typeDef.Properties.Where(x => x != prop && x.Name == propName).ToList())
                {
                    if (clash.Parameters.Count != prop.Parameters.Count)
                    {
                        continue;
                    }
                    if ((clash.Getter ?? clash.Setter).InterfaceType != null)
                    {
                        continue;
                    }

                    if (prop.PropertyType.AreSame(clash.PropertyType) &&
                        prop.MainMethod.CreateReason == "TypeBuilder.AddAbstractInterfaceMethods")
                    {
                        // it appears that the method does have an implementation!
                        typeDef.Properties.Remove(prop);
                        typeDef.Methods.Remove(prop.Getter);
                        typeDef.Methods.Remove(prop.Setter);
                        overridingProperties.RemoveAt(i);
                        i -= 1;
                        goto continue_outer;
                    }

                    if (overridingProperties.Contains(clash))
                    {
                        // This would have probably been removed later anyways.
                        //Console.Error.WriteLine("Warning: duplicate property names {0}::{1}. Not generating property for one of the clashes.", typeDef.FullName, propName);
                        RemoveProperty(clash);
                        overridingProperties.Remove(clash); // this must come after us.
                        continue;
                    }

                    // else remove other property
                    RemoveProperty(clash);
                }

                if (typeDef.Methods.Any(x => x != prop.Setter && x != prop.Getter && x.Name == propName))
                {
                    Console.Error.WriteLine("Warning: Inherited property {0}::{1} clashes with methods. Prepending \"Invoke\" prefix to methods.", typeDef.FullName, propName);
                    typeDef.Methods.Where(x => x != prop.Setter && x != prop.Getter && x.Name == propName)
                    .ForEach(m => methodRenamer.Rename(m, "Invoke" + m.Name));
                }
                continue_outer :;
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Build properties for the given type
        /// </summary>
        internal void BuildProperties(TargetFramework target, MethodRenamer methodRenamer)
        {
            var getters = typeDef.Methods.Where(IsGetter).ToList();
            var setters = typeDef.Methods.Where(IsSetter).ToList();

            foreach (var getMethod in getters)
            {
                // Get the name of the property
                var name = GetPropertyName(getMethod);

                // other clashes must be handled later.
                if (getMethod.InterfaceType == null)
                {
                    typeDef.Fields.Where(x => x.Name == name).ForEach(RenameClashingField);
                }

                // Create property
                var prop = new NetPropertyDefinition
                {
                    Name        = name,
                    Getter      = getMethod,
                    Description = getMethod.Description,
                };

                AddCustomAttributes(getMethod, prop.CustomAttributes);

                // Clone parameters
                if (getMethod.Parameters.Any())
                {
                    prop.Parameters.AddRange(getMethod.Parameters.Select(x => new NetParameterDefinition(x.Name, x.ParameterType, false)));
                    prop.Name = "this";
                }

                getMethod.Property = prop;

                // Find setter
                var setMethod = FindSetter(getMethod, setters);
                if (setMethod != null)
                {
                    prop.Setter        = setMethod;
                    setMethod.Property = prop;

                    setters.Remove(setMethod);
                }

                // Add property
                typeDef.Properties.Add(prop);
            }

            // create properties for lone setters that override a base setter
            foreach (var setMethod in setters.Where(s => s.IsOverride))
            {
                var name = GetPropertyName(setMethod);

                // other clashes must be handled in FixOverrides
                if (setMethod.InterfaceType == null)
                {
                    typeDef.Fields.Where(x => x.Name == name).ForEach(RenameClashingField);
                }

                // Create property
                var prop = new NetPropertyDefinition {
                    Name = name, Setter = setMethod, Description = setMethod.Description
                };
                setMethod.Property = prop;

                AddCustomAttributes(setMethod, prop.CustomAttributes);

                // Clone parameters
                if (setMethod.Parameters.Skip(1).Any())
                {
                    prop.Parameters.AddRange(setMethod.Parameters.Skip(1).Select(x => new NetParameterDefinition(x.Name, x.ParameterType, false)));
                    prop.Name = "this";
                }

                typeDef.Properties.Add(prop);
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Create code for the given property
        /// </summary>
        private void CreatePropertyCode(NetPropertyDefinition prop)
        {
            var mainMethod = prop.MainMethod;

            CreateComments(prop.Description, mainMethod.OriginalJavaName);
            CreateAttributes(prop.CustomAttributes, prop);
            writer.Write(indent);

            if (mainMethod.InterfaceMethod == null)
            {
                writer.Write(Convert(mainMethod, mainMethod.Attributes, context.GenerateExternalMethods, false));
                writer.Write(CreateRef(prop.PropertyType, true, true, true, false, prop.DeclaringType, target));
                writer.Write(" ");
            }
            else
            {
                writer.Write(CreateRef(prop.PropertyType, true, true, true, false, prop.DeclaringType, target));
                writer.Write(" ");
                writer.Write(CreateRef(mainMethod.InterfaceType, false, true, true, false, mainMethod.DeclaringType, target));
                writer.Write(".");
            }

            writer.Write(prop.Name);

            if (prop.Parameters.Any())
            {
                writer.Write("[");
                var needComma = false;
                var pIndex    = 0;
                foreach (var p in prop.Parameters)
                {
                    if (needComma)
                    {
                        writer.Write(", ");
                    }
                    writer.Write(CreateRef(p.ParameterType, false, true, true, false, prop.DeclaringType, target));
                    writer.Write(pIndex == 0 ? " index" : string.Format(" p{0}", pIndex));
                    pIndex++;
                    needComma = true;
                }
                writer.Write("]");
            }

            // Create method body
            var isAbstract  = mainMethod.IsAbstract;
            var isInterface = mainMethod.DeclaringType.IsInterface;

            writer.WriteLine();

            writer.Write(indent);
            writer.WriteLine("{");

            // increase indent
            var oldIndent = indent;

            indent += "\t\t";

            try
            {
                if (prop.Getter != null)
                {
                    CreateAttributes(mainMethod.CustomAttributes, prop.Getter);
                    writer.Write(indent);
                    writer.Write("get");

                    bool isEmptyMethod = isAbstract || isInterface || context.GenerateExternalMethods;

                    if (!isEmptyMethod)
                    {
                        writer.Write("{ return default(");
                        writer.Write(CreateRef(prop.PropertyType, false, true, true, false, prop.Getter.DeclaringType,
                                               target));
                        writer.Write("); }");
                        //writer.Write("{{ return {0}({1}); }}", prop.Getter.Name, string.Join(", ", prop.Getter.Parameters.Select((x, i) => (i == 0) ? "index" : x.Name)));
                    }
                    else
                    {
                        writer.Write(";");
                    }
                    writer.WriteLine();
                }

                if (prop.Setter != null)
                {
                    CreateAttributes(prop.Setter.CustomAttributes, prop.Setter);
                    writer.Write(indent);
                    writer.Write("set");
                    //if (!isEmptyMethod)
                    //{
                    //    writer.Write("{{ {0}({1}); }}", prop.Setter.Name,
                    //        string.Join(", ", prop.Setter.Parameters.Select((x, i) => (i == 0) ? "value" : x.Name)));
                    //}
                    //else
                    //{
                    //    writer.Write(";");
                    //}
                    writer.Write(!isAbstract && !context.GenerateExternalMethods ? "{ }" : ";");
                    writer.WriteLine();
                }
            }
            finally
            {
                indent = indent = oldIndent;
            }
            // restore indent
            writer.Write(indent);
            writer.WriteLine("}");

            writer.WriteLine();
        }