public void FixupMethodOverrides(CodeGenerationOptions opt) { foreach (var m in Methods.Where(m => !m.IsStatic && !m.IsInterfaceDefaultMethod)) { for (var bt = GetBaseGen(opt); bt != null; bt = bt.GetBaseGen(opt)) { var bm = bt.Methods.FirstOrDefault(mm => mm.Name == m.Name && mm.Visibility == m.Visibility && ParameterList.Equals(mm.Parameters, m.Parameters)); if (bm != null && bm.RetVal.FullName == m.RetVal.FullName) // if return type is different, it could be still "new", not "override". { m.IsOverride = true; break; } } } // Interface default methods can be overriden. We want to process them differently. var checkDimOverrideTargets = opt.SupportDefaultInterfaceMethods ? Methods : Methods.Where(m => m.IsInterfaceDefaultMethod); // We need to check all the implemented interfaces of all the base types. var allIfaces = new List <InterfaceGen> (); for (var gen = this; gen != null; gen = gen.BaseGen) { gen.GetAllDerivedInterfaces(allIfaces); } foreach (var m in checkDimOverrideTargets.Where(m => !m.IsStatic)) { foreach (var bt in allIfaces.Distinct()) { // We mark a method as an override if (1) it is a DIM, or (2) if the base method is DIM // (i.e. we don't mark as override if a class method "implements" normal iface method.) var bm = bt.Methods.FirstOrDefault(mm => (m.IsInterfaceDefaultMethod || !mm.IsAbstract) && mm.Name == m.Name && ParameterList.Equals(mm.Parameters, m.Parameters)); if (bm != null) { m.OverriddenInterfaceMethod = bm; break; } } } foreach (var m in Methods) { if (m.Name == Name || ContainsProperty(m.Name, true) || HasNestedType(m.Name)) { m.Name = "Invoke" + m.Name; } if ((m.Name == "ToString" && m.Parameters.Count == 0) || (BaseGen != null && BaseGen.ContainsMethod(m, true))) { m.IsOverride = true; } } foreach (var nt in NestedTypes) { nt.FixupMethodOverrides(opt); } }
public void FixupMethodOverrides(CodeGenerationOptions opt) { foreach (Method m in methods.Where(m => !m.IsInterfaceDefaultMethod)) { for (var bt = this.GetBaseGen(opt); bt != null; bt = bt.GetBaseGen(opt)) { var bm = bt.Methods.FirstOrDefault(mm => mm.Name == m.Name && mm.Visibility == m.Visibility && ParameterList.Equals(mm.Parameters, m.Parameters)); if (bm != null && bm.RetVal.FullName == m.RetVal.FullName) // if return type is different, it could be still "new", not "override". { m.IsOverride = true; break; } } } // Interface default methods can be overriden. We want to process them differently. foreach (Method m in methods.Where(m => m.IsInterfaceDefaultMethod)) { foreach (var bt in this.GetAllDerivedInterfaces()) { var bm = bt.Methods.FirstOrDefault(mm => mm.Name == m.Name && ParameterList.Equals(mm.Parameters, m.Parameters)); if (bm != null) { m.IsInterfaceDefaultMethodOverride = true; break; } } } foreach (Method m in methods) { if (m.Name == Name || ContainsProperty(m.Name, true) || HasNestedType(m.Name)) { m.Name = "Invoke" + m.Name; } if ((m.Name == "ToString" && m.Parameters.Count == 0) || (BaseGen != null && BaseGen.ContainsMethod(m, true))) { m.IsOverride = true; } } foreach (var nt in NestedTypes) { nt.FixupMethodOverrides(opt); } }
void AddPropertyAccessors() { // First pass extracts getters and creates property hash List <Method> unmatched = new List <Method> (); foreach (Method m in Methods) { if (m.IsPropertyAccessor) { string prop_name = m.PropertyName; if (m.CanSet || prop_name == string.Empty || Name == prop_name || m.Name == "GetHashCode" || HasNestedType(prop_name) || IsInfrastructural(prop_name)) { unmatched.Add(m); } else if (BaseGen != null && !BaseGen.prop_hash.ContainsKey(prop_name) && BaseGen.Methods.Any(mm => mm.Name == m.Name && ReturnTypeMatches(m, mm) && ParameterList.Equals(mm.Parameters, m.Parameters))) { // this is to filter out those method that was *not* a property // in the base type for some reason (e.g. name overlap). // For example, android.graphics.drawable.BitmapDrawable#getConstantState() // ContainsProperty() check is required here to not exclude such methods // that are known to be property. AbstractSelectionKey.IsValid is an example. unmatched.Add(m); } else { if (prop_hash.ContainsKey(prop_name)) { if (m.Name.StartsWith("Get")) { unmatched.Add(m); } else { unmatched.Add(prop_hash [prop_name].Getter); prop_hash [prop_name].Getter = m; } } else { var prop = new Property(prop_name) { Getter = m }; prop_hash [prop_name] = prop; } } } else { unmatched.Add(m); } } Methods = unmatched; // Second pass adds setters unmatched = new List <Method> (); foreach (Method m in Methods) { if (!m.CanSet) { unmatched.Add(m); continue; } if (Ancestors().All(a => !a.prop_hash.ContainsKey(m.PropertyName)) && Ancestors().Any(a => a.Methods.Any(mm => mm.Name == m.Name && ReturnTypeMatches(m, mm) && ParameterList.Equals(mm.Parameters, m.Parameters)))) { unmatched.Add(m); // base setter exists, and it was not a property. } else if (prop_hash.ContainsKey(m.PropertyName)) { Property baseProp = BaseGen?.Properties.FirstOrDefault(p => p.Name == m.PropertyName); var prop = prop_hash [m.PropertyName]; if (prop.Getter.RetVal.FullName == m.Parameters [0].Type && prop.Getter.IsAbstract == m.IsAbstract && // SearchIterator abstract getIndex() and non-abstract setIndex() prop.Getter.Visibility == m.Visibility && (baseProp == null || baseProp.Setter != null) && prop.Getter.SourceApiLevel <= m.SourceApiLevel) { prop.Setter = m; } else { unmatched.Add(m); } } else if (prop_hash.ContainsKey("Is" + m.PropertyName)) { var prop = prop_hash ["Is" + m.PropertyName]; if (prop.Getter.RetVal.FullName == m.Parameters [0].Type && prop.Getter.Visibility == m.Visibility && CanMethodBeIsStyleSetter(m) && prop.Getter.SourceApiLevel <= m.SourceApiLevel) { prop.Name = m.PropertyName; prop.Setter = m; prop_hash [m.PropertyName] = prop; prop_hash.Remove("Is" + m.PropertyName); } else { unmatched.Add(m); } } else { unmatched.Add(m); } if (m.GenerateDispatchingSetter && prop_hash.ContainsKey(m.PropertyName)) { prop_hash [m.PropertyName].GenerateDispatchingSetter = true; } } Methods = unmatched; }
public bool IsCovariantMethod(Method method) { return(Methods.Any(m => m.Name == method.Name && ParameterList.Equals(m.Parameters, method.Parameters))); // TODO: check that method.ReturnType is a superclass of m.ReturnType }