From bb29084392356cc43ef756e3a08f26058df786aa Mon Sep 17 00:00:00 2001 From: isaac <> Date: Tue, 21 Apr 2026 15:24:14 +0400 Subject: [PATCH] SwiftTL: thread apiPrefix, drop dead CLI flags and LegacyOrderParser Preparation for layered schema generation. Threads apiPrefix: String through CodeGenerator.generate / generateMainFile / generateImplFile / typeReferenceRepresentation so the output's namespace name can come from the --api-prefix= CLI flag rather than a hard-coded "Api". Drops the --stub-functions and --print-constructors=N-M flags (both unused) and the LegacyOrderParser.swift file (obsolete migration helper that re-parsed hand-emitted Api0.swift). No behavior change for the flat Api*.swift output when --api-prefix=Api (the default). Enables the upcoming layered secret- scheme pipeline to reuse the same generator helpers. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Sources/SwiftTL/CodeGeneration.swift | 95 +++++-------- .../Sources/SwiftTL/DescriptionParsing.swift | 2 - .../Sources/SwiftTL/LegacyOrderParser.swift | 128 ------------------ .../SwiftTL/Sources/SwiftTL/main.swift | 50 ++----- 4 files changed, 44 insertions(+), 231 deletions(-) delete mode 100644 build-system/SwiftTL/Sources/SwiftTL/LegacyOrderParser.swift diff --git a/build-system/SwiftTL/Sources/SwiftTL/CodeGeneration.swift b/build-system/SwiftTL/Sources/SwiftTL/CodeGeneration.swift index 2e3c43482e..053234602e 100644 --- a/build-system/SwiftTL/Sources/SwiftTL/CodeGeneration.swift +++ b/build-system/SwiftTL/Sources/SwiftTL/CodeGeneration.swift @@ -87,7 +87,7 @@ private struct CodeWriter { } }*/ -private func typeReferenceRepresentation(_ type: Resolver.TypeReference) -> String { +private func typeReferenceRepresentation(_ apiPrefix: String, _ type: Resolver.TypeReference) -> String { switch type { case .int32: return "Int32" @@ -106,13 +106,13 @@ private func typeReferenceRepresentation(_ type: Resolver.TypeReference) -> Stri case .boolTrue: return "bool" case let .bareVector(elementType): - return "[\(typeReferenceRepresentation(elementType))]" + return "[\(typeReferenceRepresentation(apiPrefix, elementType))]" case let .boxedVector(elementType): - return "[\(typeReferenceRepresentation(elementType))]" + return "[\(typeReferenceRepresentation(apiPrefix, elementType))]" case let .bareConstructor(typeName, _): - return "Api.\(typeName)" + return "\(apiPrefix).\(typeName)" case let .boxedType(typeName): - return "Api.\(typeName)" + return "\(apiPrefix).\(typeName)" } } @@ -184,22 +184,22 @@ enum CodeGenerator { } } - static func generate(types: [Resolver.SumType], functions: [Resolver.Function], constructorOrder: [(typeName: QualifiedName, constructorName: String)], typeOrder: [(types: [(typeName: QualifiedName, constructorNames: [String])], functions: [QualifiedName])], stubFunctions: Bool = false) throws -> [String: String] { + static func generate(apiPrefix: String, types: [Resolver.SumType], functions: [Resolver.Function], constructorOrder: [(typeName: QualifiedName, constructorName: String)], typeOrder: [(types: [(typeName: QualifiedName, constructorNames: [String])], functions: [QualifiedName])]) throws -> [String: String] { var files: [String: String] = [:] var functions = functions functions.append(Resolver.Function(name: QualifiedName(namespace: "help", value: "test"), id: UInt32(bitPattern: -1058929929), arguments: [], result: .boxedType(QualifiedName(namespace: nil, value: "Bool")))) - files["Api0.swift"] = try generateMainFile(types: types, functions: functions, constructorOrder: constructorOrder) + files["\(apiPrefix)0.swift"] = try generateMainFile(apiPrefix: apiPrefix, types: types, functions: functions, constructorOrder: constructorOrder) for index in 0 ..< typeOrder.count { - files["Api\(index + 1).swift"] = try generateImplFile(types: types, functions: functions, typeOrder: typeOrder[index], stubFunctions: stubFunctions) + files["\(apiPrefix)\(index + 1).swift"] = try generateImplFile(apiPrefix: apiPrefix, types: types, functions: functions, typeOrder: typeOrder[index]) } return files } - private static func generateMainFile(types: [Resolver.SumType], functions: [Resolver.Function], constructorOrder: [(typeName: QualifiedName, constructorName: String)]) throws -> String { + private static func generateMainFile(apiPrefix: String, types: [Resolver.SumType], functions: [Resolver.Function], constructorOrder: [(typeName: QualifiedName, constructorName: String)]) throws -> String { var writer = CodeWriter() writer.line() @@ -218,7 +218,7 @@ enum CodeGenerator { } } - writer.line("public enum Api {") + writer.line("public enum \(apiPrefix) {") writer.indent() for namespace in namespaces.sorted(by: { $0 < $1 }) { writer.line("public enum \(namespace) {}") @@ -258,7 +258,7 @@ enum CodeGenerator { for (_, constructor) in type.constructors { if constructor.name.value == constructorName { found = true - writer.line("dict[\(Int32(bitPattern: constructor.id))] = { return Api.\(type.name).parse_\(constructor.name.value)($0) }") + writer.line("dict[\(Int32(bitPattern: constructor.id))] = { return \(apiPrefix).\(type.name).parse_\(constructor.name.value)($0) }") break } } @@ -274,7 +274,7 @@ enum CodeGenerator { writer.line() - writer.line("public extension Api {") + writer.line("public extension \(apiPrefix) {") writer.indent() writer.line("static func parse(_ buffer: Buffer) -> Any? {") @@ -344,7 +344,7 @@ enum CodeGenerator { writer.dedent() writer.line("} else {") writer.indent() - writer.line("if let item = Api.parse(reader, signature: signature) as? T {") + writer.line("if let item = \(apiPrefix).parse(reader, signature: signature) as? T {") writer.indent() writer.line("array.append(item)") writer.dedent() @@ -378,7 +378,7 @@ enum CodeGenerator { throw CodeGenerationError(text: "Type \(typeName) not found") } - writer.line("case let _1 as Api.\(type.name):") + writer.line("case let _1 as \(apiPrefix).\(type.name):") writer.indent() writer.line("_1.serialize(buffer, boxed)") writer.dedent() @@ -398,7 +398,7 @@ enum CodeGenerator { return writer.output() } - private static func generateImplFile(types: [Resolver.SumType], functions: [Resolver.Function], typeOrder: (types: [(typeName: QualifiedName, constructorNames: [String])], functions: [QualifiedName]), stubFunctions: Bool) throws -> String { + private static func generateImplFile(apiPrefix: String, types: [Resolver.SumType], functions: [Resolver.Function], typeOrder: (types: [(typeName: QualifiedName, constructorNames: [String])], functions: [QualifiedName])) throws -> String { var writer = CodeWriter() var typeMap: [QualifiedName: Resolver.SumType] = [:] @@ -407,7 +407,7 @@ enum CodeGenerator { } for (typeName, constructorNames) in typeOrder.types { - writer.line("public extension Api\(typeName.namespace.flatMap { "." + $0 } ?? "") {") + writer.line("public extension \(apiPrefix)\(typeName.namespace.flatMap { "." + $0 } ?? "") {") writer.indent() guard let type = typeMap[typeName] else { @@ -448,7 +448,7 @@ enum CodeGenerator { } let fieldName = argument.name.camelCasedAndEscaped - let fieldType = typeReferenceRepresentation(argument.type) + (argument.condition != nil ? "?" : "") + let fieldType = typeReferenceRepresentation(apiPrefix, argument.type) + (argument.condition != nil ? "?" : "") if !fieldsString.isEmpty { fieldsString.append("\n") @@ -509,7 +509,7 @@ enum CodeGenerator { argumentsString.append(argument.name.camelCased) argumentsString.append(": ") - argumentsString.append(typeReferenceRepresentation(argument.type)) + argumentsString.append(typeReferenceRepresentation(apiPrefix, argument.type)) if argument.condition != nil { argumentsString.append("?") } @@ -522,13 +522,6 @@ enum CodeGenerator { writer.line() writer.line("public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {") writer.indent() - if stubFunctions { - writer.line("#if DEBUG") - writer.line("preconditionFailure()") - writer.line("#else") - writer.line("error") - writer.line("#endif") - } else { writer.line("switch self {") for constructor in sortedConstructors { @@ -608,20 +601,12 @@ enum CodeGenerator { } writer.line("}") - } // end if !stubFunctions writer.dedent() writer.line("}") writer.line() writer.line("public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {") writer.indent() - if stubFunctions { - writer.line("#if DEBUG") - writer.line("preconditionFailure()") - writer.line("#else") - writer.line("error") - writer.line("#endif") - } else { writer.line("switch self {") for constructor in sortedConstructors { @@ -673,7 +658,6 @@ enum CodeGenerator { } writer.line("}") - } // end if !stubFunctions for descriptionFields writer.dedent() writer.line("}") @@ -682,14 +666,6 @@ enum CodeGenerator { for constructor in sortedConstructors { writer.line("public static func parse_\(constructor.name.value)(_ reader: BufferReader) -> \(typeName.value)? {") writer.indent() - if stubFunctions { - writer.line("#if DEBUG") - writer.line("preconditionFailure()") - writer.line("#else") - writer.line("error") - writer.line("#endif") - } else { - if constructor.arguments.contains(where: { if case .boolTrue = $0.type { return false } else { return true } }) { var argumentIndex = 0 var argumentCheckString = "" @@ -699,7 +675,7 @@ enum CodeGenerator { continue } - writer.line("var _\(argumentIndex + 1): \(typeReferenceRepresentation(argument.type))?") + writer.line("var _\(argumentIndex + 1): \(typeReferenceRepresentation(apiPrefix, argument.type))?") if let condition = argument.condition { guard let fieldIndex = constructor.arguments.filter({ if case .boolTrue = $0.type { return false } else { return true } }).firstIndex(where: { $0.name == condition.fieldName }) else { @@ -708,11 +684,11 @@ enum CodeGenerator { writer.line("if Int(_\(fieldIndex + 1)!) & Int(1 << \(condition.bitIndex)) != 0 {") writer.indent() - try generateFieldParsing(writer: &writer, typeMap: typeMap, argument: argument, argumentAccessor: "_\(argumentIndex + 1)") + try generateFieldParsing(apiPrefix: apiPrefix, writer: &writer, typeMap: typeMap, argument: argument, argumentAccessor: "_\(argumentIndex + 1)") writer.dedent() writer.line("}") } else { - try generateFieldParsing(writer: &writer, typeMap: typeMap, argument: argument, argumentAccessor: "_\(argumentIndex + 1)") + try generateFieldParsing(apiPrefix: apiPrefix, writer: &writer, typeMap: typeMap, argument: argument, argumentAccessor: "_\(argumentIndex + 1)") } if !argumentCheckString.isEmpty { @@ -753,9 +729,9 @@ enum CodeGenerator { writer.line("if \(argumentCheckString) {") writer.indent() if useStructPattern && !argumentCollectionString.isEmpty { - writer.line("return Api.\(typeName).\(constructor.name.value)(Cons_\(constructor.name.value)(\(argumentCollectionString)))") + writer.line("return \(apiPrefix).\(typeName).\(constructor.name.value)(Cons_\(constructor.name.value)(\(argumentCollectionString)))") } else { - writer.line("return Api.\(typeName).\(constructor.name.value)\(argumentCollectionString.isEmpty ? "" : "(\(argumentCollectionString))")") + writer.line("return \(apiPrefix).\(typeName).\(constructor.name.value)\(argumentCollectionString.isEmpty ? "" : "(\(argumentCollectionString))")") } writer.dedent() writer.line("}") @@ -765,10 +741,9 @@ enum CodeGenerator { writer.dedent() writer.line("}") } else { - writer.line("return Api.\(typeName).\(constructor.name.value)") + writer.line("return \(apiPrefix).\(typeName).\(constructor.name.value)") } - } // end if !stubFunctions writer.dedent() writer.line("}") } @@ -781,7 +756,7 @@ enum CodeGenerator { if !typeOrder.functions.isEmpty { for functionName in typeOrder.functions { - writer.line("public extension Api.functions\(functionName.namespace.flatMap { "." + $0 } ?? "") {") + writer.line("public extension \(apiPrefix).functions\(functionName.namespace.flatMap { "." + $0 } ?? "") {") writer.indent() var foundFunction: Resolver.Function? @@ -807,13 +782,13 @@ enum CodeGenerator { argumentsString.append(argument.name.camelCasedAndEscaped) argumentsString.append(": ") - argumentsString.append(typeReferenceRepresentation(argument.type)) + argumentsString.append(typeReferenceRepresentation(apiPrefix, argument.type)) if argument.condition != nil { argumentsString.append("?") } } - writer.line("static func \(function.name.value)(\(argumentsString)) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<\(typeReferenceRepresentation(function.result))>) {") + writer.line("static func \(function.name.value)(\(argumentsString)) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<\(typeReferenceRepresentation(apiPrefix, function.result))>) {") writer.indent() writer.line("let buffer = Buffer()") writer.line("buffer.appendInt32(\(Int32(bitPattern: function.id)))") @@ -847,12 +822,12 @@ enum CodeGenerator { argumentSerializationString.append("(\"\(argument.name.camelCasedAndEscaped)\", ConstructorParameterDescription(\(argument.name.camelCasedAndEscaped)))") } - writer.line("return (FunctionDescription(name: \"\(function.name)\", parameters: [\(argumentSerializationString)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> \(typeReferenceRepresentation(function.result))? in") + writer.line("return (FunctionDescription(name: \"\(function.name)\", parameters: [\(argumentSerializationString)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> \(typeReferenceRepresentation(apiPrefix, function.result))? in") writer.indent() writer.line("let reader = BufferReader(buffer)") - writer.line("var result: \(typeReferenceRepresentation(function.result))?") + writer.line("var result: \(typeReferenceRepresentation(apiPrefix, function.result))?") - try generateFieldParsing(writer: &writer, typeMap: typeMap, argument: Resolver.Argument(name: "result", type: function.result, condition: nil), argumentAccessor: "result") + try generateFieldParsing(apiPrefix: apiPrefix, writer: &writer, typeMap: typeMap, argument: Resolver.Argument(name: "result", type: function.result, condition: nil), argumentAccessor: "result") writer.line("return result") writer.dedent() @@ -904,7 +879,7 @@ enum CodeGenerator { } } - private static func generateFieldParsing(writer: inout CodeWriter, typeMap: [QualifiedName: Resolver.SumType], argument: Resolver.Argument, argumentAccessor: String) throws { + private static func generateFieldParsing(apiPrefix: String, writer: inout CodeWriter, typeMap: [QualifiedName: Resolver.SumType], argument: Resolver.Argument, argumentAccessor: String) throws { switch argument.type { case .int32: writer.line("\(argumentAccessor) = reader.readInt32()") @@ -961,11 +936,11 @@ enum CodeGenerator { if case .boxedVector = argument.type { writer.line("if let _ = reader.readInt32() {") writer.indent() - writer.line("\(argumentAccessor) = Api.parseVector(reader, elementSignature: \(elementSignature), elementType: \(typeReferenceRepresentation(elementType)).self)") + writer.line("\(argumentAccessor) = \(apiPrefix).parseVector(reader, elementSignature: \(elementSignature), elementType: \(typeReferenceRepresentation(apiPrefix, elementType)).self)") writer.dedent() writer.line("}") } else { - writer.line("\(argumentAccessor) = Api.parseVector(reader, elementSignature: \(elementSignature), elementType: \(typeReferenceRepresentation(elementType)).self)") + writer.line("\(argumentAccessor) = \(apiPrefix).parseVector(reader, elementSignature: \(elementSignature), elementType: \(typeReferenceRepresentation(apiPrefix, elementType)).self)") } case let .bareConstructor(typeName, name): guard let type = typeMap[typeName] else { @@ -974,11 +949,11 @@ enum CodeGenerator { guard let constructor = type.constructors[name] else { throw CodeGenerationError(text: "Type \(typeName) not found") } - writer.line("\(argumentAccessor) = Api.parse(reader, signature: \(Int32(bitPattern: constructor.id)) as? \(typeReferenceRepresentation(argument.type))") + writer.line("\(argumentAccessor) = \(apiPrefix).parse(reader, signature: \(Int32(bitPattern: constructor.id)) as? \(typeReferenceRepresentation(apiPrefix, argument.type))") case .boxedType: writer.line("if let signature = reader.readInt32() {") writer.indent() - writer.line("\(argumentAccessor) = Api.parse(reader, signature: signature) as? \(typeReferenceRepresentation(argument.type))") + writer.line("\(argumentAccessor) = \(apiPrefix).parse(reader, signature: signature) as? \(typeReferenceRepresentation(apiPrefix, argument.type))") writer.dedent() writer.line("}") } diff --git a/build-system/SwiftTL/Sources/SwiftTL/DescriptionParsing.swift b/build-system/SwiftTL/Sources/SwiftTL/DescriptionParsing.swift index e3b12d3a42..c4acdbe363 100644 --- a/build-system/SwiftTL/Sources/SwiftTL/DescriptionParsing.swift +++ b/build-system/SwiftTL/Sources/SwiftTL/DescriptionParsing.swift @@ -31,8 +31,6 @@ enum DescriptionParser { var functionLines: [String] = [] let skipPrefixes: [String] = [ - //"boolFalse#bc799737 = Bool;", - //"boolTrue#997275b5 = Bool;", "true#3fedd339 = True;", "vector#1cb5c415 {t:Type} # [ t ] = Vector t;", "error#c4b9f9bb code:int text:string = Error;", diff --git a/build-system/SwiftTL/Sources/SwiftTL/LegacyOrderParser.swift b/build-system/SwiftTL/Sources/SwiftTL/LegacyOrderParser.swift deleted file mode 100644 index 4a4feb1570..0000000000 --- a/build-system/SwiftTL/Sources/SwiftTL/LegacyOrderParser.swift +++ /dev/null @@ -1,128 +0,0 @@ -import Foundation - -enum LegacyOrderParser { - struct LegacyOrderParsingError: Error, CustomStringConvertible { - var text: String - - var description: String { - return self.text - } - } - - static func parseConstructorOrder(data: String) throws -> [(typeName: QualifiedName, constructorName: String)] { - let lines = data.split(separator: "\n") - - var result: [(typeName: QualifiedName, constructorName: String)] = [] - - for line in lines { - if let startRange = line.range(of: " = { return Api."), let endRange = line.range(of: "($0) }", options: [.backwards], range: nil) { - let parseString = line[startRange.upperBound ..< endRange.lowerBound] - let components = parseString.components(separatedBy: ".parse_") - if components.count != 2 { - continue - } - - result.append((QualifiedName(string: components[0]), components[1])) - } - } - - return result - } - - static func parseTypeOrder(data: String) throws -> (types: [(typeName: QualifiedName, constructorNames: [String])], functions: [QualifiedName]) { - var resultTypes: [(typeName: QualifiedName, constructorNames: [String])] = [] - var resultFunctions: [QualifiedName] = [] - - let namespaces = data.components(separatedBy: "public extension Api {\n") - - enum ParseSection { - case types - case functions - } - - for namespaceData in namespaces { - if namespaceData.isEmpty { - continue - } - guard let firstNewline = namespaceData.range(of: "\n") else { - throw LegacyOrderParsingError(text: "No newline in the beginning of the namespace section") - } - let namespaceName: String? - let namespaceContentData: String - let parseSection: ParseSection - if let prefixRange = namespaceData.range(of: " public enum ", options: [], range: namespaceData.startIndex ..< firstNewline.lowerBound), prefixRange.lowerBound == namespaceData.startIndex { - namespaceName = nil - namespaceContentData = namespaceData - parseSection = .types - } else if let prefixRange = namespaceData.range(of: " indirect public enum ", options: [], range: namespaceData.startIndex ..< firstNewline.lowerBound), prefixRange.lowerBound == namespaceData.startIndex { - namespaceName = nil - namespaceContentData = namespaceData - parseSection = .types - } else if let prefixRange = namespaceData.range(of: " public struct functions {", options: [], range: namespaceData.startIndex ..< firstNewline.lowerBound), prefixRange.upperBound == firstNewline.lowerBound { - namespaceName = nil - namespaceContentData = namespaceData - parseSection = .functions - } else { - guard let prefixRange = namespaceData.range(of: "public struct ", options: [], range: namespaceData.startIndex ..< firstNewline.lowerBound), prefixRange.lowerBound == namespaceData.startIndex else { - throw LegacyOrderParsingError(text: "Missing header prefix in the beginning of the namespace section") - } - guard let trailerRange = namespaceData.range(of: " {", options: [], range: prefixRange.upperBound ..< firstNewline.lowerBound) else { - throw LegacyOrderParsingError(text: "Missing trailing suffix in the beginning of the namespace section") - } - namespaceName = String(namespaceData[prefixRange.upperBound ..< trailerRange.lowerBound]) - namespaceContentData = String(namespaceData[firstNewline.upperBound...]) - parseSection = .types - } - - let namespaceContentLines = namespaceContentData.split(separator: "\n") - - switch parseSection { - case .types: - var currentType: (typeName: QualifiedName, constructorNames: [String])? - for line in namespaceContentLines { - if let typePrefixRange = line.range(of: " public enum "), typePrefixRange.lowerBound == line.startIndex, let typeSuffixRange = line.range(of: ": TypeConstructorDescription {"), typeSuffixRange.upperBound == line.endIndex { - let typeName = String(line[typePrefixRange.upperBound ..< typeSuffixRange.lowerBound]) - if let currentType = currentType { - resultTypes.append(currentType) - } - currentType = (QualifiedName(namespace: namespaceName, value: typeName), []) - } else if let typePrefixRange = line.range(of: " indirect public enum "), typePrefixRange.lowerBound == line.startIndex, let typeSuffixRange = line.range(of: ": TypeConstructorDescription {"), typeSuffixRange.upperBound == line.endIndex { - let typeName = String(line[typePrefixRange.upperBound ..< typeSuffixRange.lowerBound]) - if let currentType = currentType { - resultTypes.append(currentType) - } - currentType = (QualifiedName(namespace: namespaceName, value: typeName), []) - } else if currentType != nil, let constructorPrefixRange = line.range(of: " case "), constructorPrefixRange.lowerBound == line.startIndex { - let constructorName: String - if let bracketRange = line.range(of: "(") { - constructorName = String(line[constructorPrefixRange.upperBound ..< bracketRange.lowerBound]) - } else { - constructorName = String(line[constructorPrefixRange.upperBound...]) - } - currentType?.constructorNames.append(constructorName) - } - } - if let currentType = currentType { - resultTypes.append(currentType) - } - case .functions: - var currentNamespace: String? - for line in namespaceContentLines { - if let namespacePrefixRange = line.range(of: " public struct "), namespacePrefixRange.lowerBound == line.startIndex, let namespaceSuffixRange = line.range(of: " {"), namespaceSuffixRange.upperBound == line.endIndex { - currentNamespace = String(line[namespacePrefixRange.upperBound ..< namespaceSuffixRange.lowerBound]) - } else if let functionPrefixRange = line.range(of: " public static func "), functionPrefixRange.lowerBound == line.startIndex { - let functionName: String - if let bracketRange = line.range(of: "(") { - functionName = String(line[functionPrefixRange.upperBound ..< bracketRange.lowerBound]) - } else { - functionName = String(line[functionPrefixRange.upperBound...]) - } - resultFunctions.append(QualifiedName(namespace: currentNamespace, value: functionName)) - } - } - } - } - - return (resultTypes, resultFunctions) - } -} diff --git a/build-system/SwiftTL/Sources/SwiftTL/main.swift b/build-system/SwiftTL/Sources/SwiftTL/main.swift index 30aa736667..c861eeb6b6 100644 --- a/build-system/SwiftTL/Sources/SwiftTL/main.swift +++ b/build-system/SwiftTL/Sources/SwiftTL/main.swift @@ -27,26 +27,15 @@ if CommandLine.arguments.count < 3 { let schemeFilePath = CommandLine.arguments[1] let outputDirectoryPath = CommandLine.arguments[2] +var apiPrefix = "Api" -var stubFunctions = false -var printConstructorsRange: (start: Int, end: Int)? = nil -for arg in CommandLine.arguments { - if arg == "--stub-functions" { - stubFunctions = true - } - if arg.hasPrefix("--print-constructors=") { - let value = String(arg.dropFirst("--print-constructors=".count)) - let parts = value.split(separator: "-") - if parts.count == 2, let start = Int(parts[0]), let end = Int(parts[1]) { - if start > end { - print("Error: Invalid range for --print-constructors: start (\(start)) must be <= end (\(end))") - exit(1) - } - printConstructorsRange = (start, end) - } else { - print("Error: Invalid format for --print-constructors. Expected: --print-constructors=N-M (e.g., --print-constructors=0-10)") - exit(1) - } +for arg in CommandLine.arguments[3...] { + if arg.hasPrefix("--api-prefix=") { + let value = String(arg.dropFirst("--api-prefix=".count)) + apiPrefix = value + } else { + print("Error: Unknown argument: \(arg)") + exit(1) } } @@ -67,27 +56,6 @@ do { let sortedTypes = resolvedTypes.sorted(by: { $0.name < $1.name }) - if let range = printConstructorsRange { - print("--- CONSTRUCTORS ---") - for (index, type) in sortedTypes.enumerated() { - if index >= range.start && index < range.end { - for constructor in type.constructors.values.sorted(by: { $0.name < $1.name }) { - let storedArguments = constructor.arguments.filter { - if case .boolTrue = $0.type { return false } - return true - } - if !storedArguments.isEmpty { - let fieldNames = storedArguments.map { $0.name.camelCased } - print("\(constructor.name.value):\(fieldNames.joined(separator: ","))") - } - } - } - } - print("--- END CONSTRUCTORS ---") - print("Total types: \(sortedTypes.count)") - exit(0) - } - for type in sortedTypes { for constructor in type.constructors.values.sorted(by: { $0.name < $1.name }) { constructorOrder.append((type.name, constructor.name.value)) @@ -118,7 +86,7 @@ do { try FileManager.default.createDirectory(at: URL(fileURLWithPath: outputDirectoryPath), withIntermediateDirectories: true, attributes: nil) - let generatedFiles = try CodeGenerator.generate(types: resolvedTypes, functions: resolvedFunctions, constructorOrder: constructorOrder, typeOrder: typeOrder, stubFunctions: stubFunctions) + let generatedFiles = try CodeGenerator.generate(apiPrefix: apiPrefix, types: resolvedTypes, functions: resolvedFunctions, constructorOrder: constructorOrder, typeOrder: typeOrder) for (name, fileData) in generatedFiles { let filePath = URL(fileURLWithPath: outputDirectoryPath).appendingPathComponent(name).path