public bool GetGenericMappings(InterfaceGen gen, Dictionary <string, string> mappings) { foreach (ISymbol sym in Interfaces) { if (sym is GenericSymbol) { GenericSymbol gsym = (GenericSymbol)sym; if (gsym.Gen.FullName == gen.FullName) { for (int i = 0; i < gsym.TypeParams.Length; i++) { mappings [gsym.Gen.TypeParameters [i].Name] = gsym.TypeParams [i].FullName; } return(true); } else if (gsym.Gen.GetGenericMappings(gen, mappings)) { string[] keys = new string [mappings.Keys.Count]; mappings.Keys.CopyTo(keys, 0); foreach (string tp in keys) { mappings [tp] = gsym.TypeParams [Array.IndexOf((from gtp in gsym.Gen.TypeParameters select gtp.Name).ToArray(), mappings [tp])].FullName; } return(true); } } } return(false); }
static bool Equals(GenericSymbol g1, GenericSymbol g2) { if (g1.IsConcrete != g2.IsConcrete) { return(false); } if (g1.FullName != g2.FullName) { return(false); } return(true); }
public ISymbol Lookup(string java_type) { string type_params; int ar; bool he; string key = GetSymbolInfo(java_type, out type_params, out ar, out he); ISymbol sym; List <ISymbol> values; if (symbols.TryGetValue(key, out values)) { sym = values [values.Count - 1]; } else { sym = AllRegisteredSymbols().FirstOrDefault(v => v.FullName == key); } ISymbol result; if (sym != null) { if (type_params.Length > 0) { GenBase gen = sym as GenBase; if (gen != null && gen.IsGeneric) { result = new GenericSymbol(gen, type_params); } // In other case, it is still valid to derive from non-generic type. // Generics are likely removed but we should not invalidate such derived classes. else { result = gen; } } // disable this condition; consider that "java.lang.Class[]" can be specified as a parameter type //else if (sym is GenBase && (sym as GenBase).IsGeneric) // return null; else { result = sym; } } else { return(null); } return(result); }
public static ISymbol Lookup(string java_type) { string type_params; int ar; bool he; string key = GetSymbolInfo(java_type, out type_params, out ar, out he); ISymbol result; ISymbol sym = symbols.ContainsKey(key) ? symbols [key] : symbols.FirstOrDefault(s => s.Value.FullName == key).Value; if (sym != null) { if (type_params.Length > 0) { GenBase gen = sym as GenBase; if (gen != null && gen.IsGeneric) { result = new GenericSymbol(gen, type_params); } // In other case, it is still valid to derive from non-generic type. // Generics are likely removed but we should not invalidate such derived classes. else { result = gen; } } // disable this condition; consider that "java.lang.Class[]" can be specified as a parameter type //else if (sym is GenBase && (sym as GenBase).IsGeneric) // return null; else { result = sym; } } else { return(null); } return(result); }
public override void Generate(StreamWriter sw, string indent, CodeGenerationOptions opt, GenerationInfo gen_info) { opt.ContextTypes.Push(this); gen_info.TypeRegistrations.Add(new KeyValuePair <string, string>(RawJniName, AssemblyQualifiedName)); bool is_enum = base_symbol != null && base_symbol.FullName == "Java.Lang.Enum"; if (is_enum) { gen_info.Enums.Add(RawJniName.Replace('/', '.') + ":" + Namespace + ":" + JavaSimpleName); } StringBuilder sb = new StringBuilder(); foreach (ISymbol isym in Interfaces) { GenericSymbol gs = isym as GenericSymbol; InterfaceGen gen = (gs == null ? isym : gs.Gen) as InterfaceGen; if (gen != null && gen.IsConstSugar) { continue; } if (sb.Length > 0) { sb.Append(", "); } sb.Append(opt.GetOutputName(isym.FullName)); } string obj_type = null; if (base_symbol != null) { GenericSymbol gs = base_symbol as GenericSymbol; obj_type = gs != null && gs.IsConcrete ? gs.GetGenericType(null) : opt.GetOutputName(base_symbol.FullName); } sw.WriteLine("{0}// Metadata.xml XPath class reference: path=\"{1}\"", indent, MetadataXPathReference); if (this.IsDeprecated) { sw.WriteLine("{0}[ObsoleteAttribute (@\"{1}\")]", indent, this.DeprecatedComment); } sw.WriteLine("{0}[global::Android.Runtime.Register (\"{1}\", DoNotGenerateAcw=true{2})]", indent, RawJniName, this.AdditionalAttributeString()); if (this.TypeParameters != null && this.TypeParameters.Any()) { sw.WriteLine("{0}{1}", indent, TypeParameters.ToGeneratedAttributeString()); } string inherits = ""; if (inherits_object && obj_type != null) { inherits = ": " + obj_type; } if (sb.Length > 0) { if (string.IsNullOrEmpty(inherits)) { inherits = ": "; } else { inherits += ", "; } } sw.WriteLine("{0}{1} {2}{3}{4}partial class {5} {6}{7} {{", indent, Visibility, needs_new ? "new " : String.Empty, IsAbstract ? "abstract " : String.Empty, IsFinal ? "sealed " : String.Empty, Name, inherits, sb.ToString()); sw.WriteLine(); var seen = new HashSet <string> (); GenFields(sw, indent + "\t", opt, seen); bool haveNested = false; foreach (var iface in GetAllImplementedInterfaces() .Except(BaseGen == null ? new InterfaceGen[0] : BaseGen.GetAllImplementedInterfaces()) .Where(i => i.Fields.Count > 0)) { if (!haveNested) { sw.WriteLine(); sw.WriteLine("{0}\tpublic static class InterfaceConsts {{", indent); haveNested = true; } sw.WriteLine(); sw.WriteLine("{0}\t\t// The following are fields from: {1}", indent, iface.JavaName); iface.GenFields(sw, indent + "\t\t", opt, seen); } if (haveNested) { sw.WriteLine("{0}\t}}\n", indent); } foreach (GenBase nest in NestedTypes) { if (BaseGen != null && BaseGen.ContainsNestedType(nest)) { if (nest is ClassGen) { (nest as ClassGen).needs_new = true; } } nest.Generate(sw, indent + "\t", opt, gen_info); sw.WriteLine(); } if (HasClassHandle) { bool requireNew = false; for (var bg = BaseGen; bg != null && bg is XmlClassGen; bg = bg.BaseGen) { if (bg.HasClassHandle) { requireNew = true; break; } } opt.CodeGenerator.WriteClassHandle(this, sw, indent, opt, requireNew); } GenConstructors(sw, indent + "\t", opt); GenProperties(sw, indent + "\t", opt); GenMethods(sw, indent + "\t", opt); if (IsAbstract) { GenerateAbstractMembers(sw, indent + "\t", opt); } bool is_char_seq = false; foreach (ISymbol isym in Interfaces) { if (isym is GenericSymbol) { GenericSymbol gs = isym as GenericSymbol; if (gs.IsConcrete) { // FIXME: not sure if excluding default methods is a valid idea... foreach (Method m in gs.Gen.Methods.Where(m => !m.IsInterfaceDefaultMethod && !m.IsStatic)) { if (m.IsGeneric) { m.GenerateExplicitIface(sw, indent + "\t", opt, gs); } } } } else if (isym.FullName == "Java.Lang.ICharSequence") { is_char_seq = true; } } if (is_char_seq) { GenCharSequenceEnumerator(sw, indent + "\t", opt); } sw.WriteLine(indent + "}"); if (!AssemblyQualifiedName.Contains('/')) { foreach (InterfaceExtensionInfo nestedIface in GetNestedInterfaceTypes()) { nestedIface.Type.GenerateExtensionsDeclaration(sw, indent, opt, nestedIface.DeclaringType); } } if (IsAbstract) { sw.WriteLine(); GenerateInvoker(sw, indent, opt); } opt.ContextTypes.Pop(); }
public override void FixupExplicitImplementation() { if (fill_explicit_implementation_started) { return; // already done. } fill_explicit_implementation_started = true; if (BaseGen != null && BaseGen.explicitly_implemented_iface_methods == null) { BaseGen.FixupExplicitImplementation(); } foreach (InterfaceGen iface in GetAllDerivedInterfaces()) { if (iface.IsGeneric) { bool skip = false; foreach (ISymbol isym in Interfaces) { var gs = isym as GenericSymbol; if (gs != null && gs.IsConcrete && gs.Gen == iface) { skip = true; } } if (skip) { continue; // we don't handle it here; generic interface methods are generated in different manner. } } if (BaseGen != null && BaseGen.GetAllDerivedInterfaces().Contains(iface)) { continue; // no need to fill members for already-implemented-in-base-class iface. } foreach (var m in iface.Methods.Where(m => !ContainsMethod(m, false, false))) { string sig = m.GetSignature(); bool doExplicitly = false; if (IsCovariantMethod(m)) { doExplicitly = true; } else if (m.IsGeneric) { doExplicitly = true; } if (doExplicitly) { explicitly_implemented_iface_methods.Add(sig); } } } // Keep in sync with Generate() that generates explicit iface method impl. foreach (ISymbol isym in Interfaces) { if (isym is GenericSymbol) { GenericSymbol gs = isym as GenericSymbol; if (gs.IsConcrete) { foreach (Method m in gs.Gen.Methods) { if (m.IsGeneric) { explicitly_implemented_iface_methods.Add(m.GetSignature()); } } } } } foreach (var nt in NestedTypes) { nt.FixupExplicitImplementation(); } }
// This is supposed to generate instantiated generic method output, but I don't think it is done yet. public void GenerateExplicitIface(StreamWriter sw, string indent, CodeGenerationOptions opt, GenericSymbol gen) { sw.WriteLine("{0}// This method is explicitly implemented as a member of an instantiated {1}", indent, gen.FullName); GenerateCustomAttributes(sw, indent); sw.WriteLine("{0}{1} {2}.{3} ({4})", indent, opt.GetOutputName(RetVal.FullName), opt.GetOutputName(gen.Gen.FullName), Name, GenBase.GetSignature(this, opt)); sw.WriteLine("{0}{{", indent); Dictionary <string, string> mappings = new Dictionary <string, string> (); for (int i = 0; i < gen.TypeParams.Length; i++) { mappings [gen.Gen.TypeParameters[i].Name] = gen.TypeParams [i].FullName; } GenerateGenericBody(sw, indent + "\t", opt, null, String.Empty, mappings); sw.WriteLine("{0}}}", indent); sw.WriteLine(); }
public ISymbol Lookup(string java_type) { string type_params; int ar; bool he; string key = GetSymbolInfo(java_type, out type_params, out ar, out he); ISymbol sym; List <ISymbol> values; if (symbols.TryGetValue(key, out values)) { sym = values [values.Count - 1]; } else { // Note we're potentially searching shallow types, but this is only looking at the type name // Anything we find we will populate before returning to the user lock (cache_population_lock) { if (all_symbols_cache == null) { all_symbols_cache = new ConcurrentDictionary <string, ISymbol> (symbols.Values.SelectMany(v => v).GroupBy(s => s.FullName).ToDictionary(s => s.Key, s => s.FirstOrDefault())); } if (!all_symbols_cache.TryGetValue(key, out sym)) { // We may be looking for a type like: // - System.Collections.Generic.IList<Java.Util.Locale.LanguageRange> // Our key is "System.Collections.Generic.IList", but it's stored in // the symbol table with the arity so we need to look for // "System.Collections.Generic.IList`1" to find a match key = AddArity(key, type_params); all_symbols_cache.TryGetValue(key, out sym); } } } ISymbol result; if (sym != null) { if (type_params.Length > 0) { GenBase gen = sym as GenBase; EnsurePopulated(gen); if (gen != null && gen.IsGeneric) { result = new GenericSymbol(gen, type_params); } // In other case, it is still valid to derive from non-generic type. // Generics are likely removed but we should not invalidate such derived classes. else { result = gen; } } // disable this condition; consider that "java.lang.Class[]" can be specified as a parameter type //else if (sym is GenBase && (sym as GenBase).IsGeneric) // return null; else { result = sym; } } else { return(null); } if (result is GenBase gen_base) { EnsurePopulated(gen_base); } return(result); }
public void GenerateExplicitIface(StreamWriter sw, string indent, CodeGenerationOptions opt, GenericSymbol gen, string adapter) { Dictionary <string, string> mappings = new Dictionary <string, string> (); for (int i = 0; i < gen.TypeParams.Length; i++) { mappings [gen.Gen.TypeParameters [i].Name] = gen.TypeParams [i].FullName; } //If the property type is Java.Lang.Object, we don't need to generate an explicit implementation if (Getter?.RetVal.GetGenericType(mappings) == "Java.Lang.Object") { return; } if (Setter?.Parameters[0].GetGenericType(mappings) == "Java.Lang.Object") { return; } sw.WriteLine("{0}// This method is explicitly implemented as a member of an instantiated {1}", indent, gen.FullName); sw.WriteLine("{0}{1} {2}.{3} {{", indent, opt.GetOutputName(Type), opt.GetOutputName(gen.Gen.FullName), AdjustedName); if (Getter != null) { if (gen.Gen.IsGeneratable) { sw.WriteLine("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.Gen.MetadataXPathReference, Getter.JavaName, Getter.Parameters.GetMethodXPathPredicate()); } if (Getter.GenericArguments != null && Getter.GenericArguments.Any()) { sw.WriteLine("{0}{1}", indent, Getter.GenericArguments.ToGeneratedAttributeString()); } sw.WriteLine("{0}\t[Register (\"{1}\", \"{2}\", \"{3}:{4}\"{5})] get {{", indent, Getter.JavaName, Getter.JniSignature, Getter.ConnectorName, Getter.GetAdapterName(opt, adapter), Getter.AdditionalAttributeString()); sw.WriteLine("{0}\t\treturn {1};", indent, Name); sw.WriteLine("{0}\t}}", indent); } if (Setter != null) { if (gen.Gen.IsGeneratable) { sw.WriteLine("{0}\t// Metadata.xml XPath method reference: path=\"{1}/method[@name='{2}'{3}]\"", indent, gen.Gen.MetadataXPathReference, Setter.JavaName, Setter.Parameters.GetMethodXPathPredicate()); } if (Setter.GenericArguments != null && Setter.GenericArguments.Any()) { sw.WriteLine("{0}{1}", indent, Setter.GenericArguments.ToGeneratedAttributeString()); } sw.WriteLine("{0}\t[Register (\"{1}\", \"{2}\", \"{3}:{4}\"{5})] set {{", indent, Setter.JavaName, Setter.JniSignature, Setter.ConnectorName, Setter.GetAdapterName(opt, adapter), Setter.AdditionalAttributeString()); sw.WriteLine("{0}\t\t{1} = {2};", indent, Name, Setter.Parameters.GetGenericCall(opt, mappings)); sw.WriteLine("{0}\t}}", indent); } sw.WriteLine("{0}}}", indent); sw.WriteLine(); }