static SLFile GenerateStubsFromTypes(TypeAggregator types, PlatformName platform, List <string> namespaces) { var imports = ImportsForPlatform(platform, types.AllTypes); SLConditionalCompilation.If(PlatformCondition(platform)).AttachBefore(imports); new SLComment(kRobotText, true).AttachBefore(imports); var slfile = new SLFile(imports); slfile.Functions.AddRange(MetaWrapperForFunc(platform, types.PublicEnums, TypeType.Enum, namespaces)); slfile.Functions.AddRange(MetaWrapperForFunc(platform, types.PublicStructs, TypeType.Struct, namespaces)); // can't do ordinal because function names can have Bockovers slfile.Functions.Sort((func1, func2) => String.Compare(func1.Name.Name, func2.Name.Name, StringComparison.InvariantCulture)); slfile.Trailer.Add(SLConditionalCompilation.Endif); // can't do ordinal because module names can have Bockovers imports.Sort((import1, import2) => String.Compare(import1.Module, import2.Module, StringComparison.InvariantCulture)); return(slfile); }
/// <summary> /// Creates a hash table for all types, and a function to access them. /// </summary> /// <param name="types">Aggregated types, a subset of which are included</param> /// <param name="platform">Platform targeted (typically iOS or Mac)</param> /// <param name="namespaces">Namespaces to include</param> /// <returns>SLFile which, when written, has hash table and function as described in summary</returns> static SLFile GenerateSwiftHashTableFromTypes(TypeAggregator types, PlatformName platform, List <string> namespaces) { var imports = ImportsForPlatform(platform, types.AllTypes); SLConditionalCompilation.If(PlatformCondition(platform)).AttachBefore(imports); new SLComment(kRobotText, true).AttachBefore(imports); var slfile = new SLFile(imports); // collect and filter types var selectedTypes = new List <TypeDefinition> (); selectedTypes.AddRange(types.PublicEnums); selectedTypes.AddRange(types.PublicStructs); selectedTypes = selectedTypes.FindAll(type => IncludeType(type, namespaces, platform)); selectedTypes.Sort((type1, type2) => String.CompareOrdinal(type1.FullName, type2.FullName)); // sort types into respective availability categories var availableCategories = new Dictionary <string, List <TypeDefinition> > (); foreach (var type in selectedTypes) { var typeAttributeObj = AvailableAttributeForType(platform, type); var typeAttribute = typeAttributeObj == null ? "" : typeAttributeObj.StringRep; List <TypeDefinition> otherTypes; if (availableCategories.TryGetValue(typeAttribute, out otherTypes)) { otherTypes.Add(type); } else { otherTypes = new List <TypeDefinition> { type }; availableCategories.Add(typeAttribute, otherTypes); } } // debug //foreach (var pair in availableCategories) { // Console.WriteLine ($"Available attribute \"{pair.Key}\": {pair.Value.Aggregate("", (str, type) => str + ", " + type.Name).Substring(2)} (length: {pair.Value.Count})"); //} // add map for each availability status var maps = new StringBuilder(); var mergeFns = new StringBuilder(); mergeFns.AppendLine("private func addToTypes() {"); foreach (var category in availableCategories) { var availableInfo = category.Key; var modifier = "public"; var prefix = ""; var header = ""; if (availableInfo != "") { modifier = "private"; prefix = AvailableDictPrefix(availableInfo); header = $"@{availableInfo}"; } if (header != "") { maps.AppendLine(header); } maps.AppendLine($"{modifier} var {prefix}types: [String:Any.Type] = ["); maps.AppendLine(MapBodyForTypes(category.Value, platform)); maps.AppendLine("]"); maps.AppendLine(); if (availableInfo != "") { mergeFns.AppendLine($" if #{availableInfo} {{"); mergeFns.AppendLine($" types.merge({AvailableDictPrefix (availableInfo)}types) {{ (_, newer) in newer }}"); mergeFns.AppendLine(" }"); } } if (!availableCategories.ContainsKey("")) { maps.AppendLine("public var types = [String:Any.Type]()"); } mergeFns.AppendLine("}"); slfile.Declarations.Add(new SLLine(new SLIdentifier(maps.ToString()), false)); slfile.Declarations.Add(new SLLine(new SLIdentifier(mergeFns.ToString()), false)); // add function to fetch type var handleTranslation = @" private var merged = false public func getSwiftType(str: UnsafeMutablePointer<String>, result: UnsafeMutablePointer<Any.Type>) -> Bool { if !merged { merged = true addToTypes() } if let mt = types[str.pointee] { result.initialize(to: mt) return true } return false }"; slfile.Declarations.Add(new SLLine(new SLIdentifier(handleTranslation), false)); slfile.Trailer.Add(SLConditionalCompilation.Endif); // can't do ordinal because module names can have Bockovers imports.Sort((import1, import2) => String.Compare(import1.Module, import2.Module, StringComparison.InvariantCulture)); return(slfile); }