Git Product home page Git Product logo

service-model-swift-code-generate's Introduction

Build - main Branch Swift 5.6, 5.7 and 5.8 Tested Join the Smoke Server Side community on gitter Apache 2

ServiceModelSwiftCodeGenerate

ServiceModelSwiftCodeGenerate is a foundational code generation library that can be used to generate code based on different service models. This library can be integrated into higher level code generation applications and provides some standard generation functions that can be called.

Getting Started

Step 1: Add the ServiceModelSwiftCodeGenerate dependency

ServiceModelSwiftCodeGenerate uses the Swift Package Manager. To use the framework, add the following dependency to your Package.swift-

dependencies: [
    .package(url: "https://github.com/amzn/service-model-swift-code-generate.git", from: "3.0.0")
]

Step 2: Use the library to generate code

The easiest way to integrate ServiceModelSwiftCodeGenerate into a higher level code generation application is to use ServiceModelGenerate.generateFromModel. This function takes a file path to a xml, json or yaml encoded service model, will attempt to parse that file into the required service model type and will then pass that model and a ServiceModelCodeGenerator to the provided function which can call any required generation functions.

extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetSupport & ClientTargetSupport {
    
    func generateFromModel<ModelType: ServiceModel>(serviceModel: ModelType,
                                                    ...) throws {
        let myClientDelegate = ...
        let myModelErrorsDelegate = ...
        let defaultTraceContextType = DefaultTraceContextType(...)
        let operationsReportingType = OperationsReportingType(...)
        let invocationReportingType = InvocationReportingType(...)

        generateClient(delegate: myClientDelegate, fileType: .clientImplementation, 
            defaultTraceContextType: defaultTraceContextType)
        generateModelOperationsEnum()
        generateOperationsReporting(operationsReportingType: operationsReportingType)
        generateInvocationsReporting(invocationReportingType: invocationReportingType)
        generateModelOperationClientInput()
        generateModelOperationClientOutput()
        generateModelOperationHTTPInput()
        generateModelOperationHTTPOutput()
        generateModelStructures()
        generateModelTypes()
        generateModelErrors(delegate: myModelErrorsDelegate)
        generateDefaultInstances(generationType: .internalTypes)

        // Call any custom generation functions as required
    }
}

public struct MyCodeGeneration {    
    public static func generateFromModel<ModelType: ServiceModel>(
        modelFilePath: String,
        modelType: ModelType.Type,
        customizations: CodeGenerationCustomizations,
        applicationDescription: ApplicationDescription,
        modelOverride: ModelOverride?,
        ...) throws 
    -> ModelType {
        return try ServiceModelGenerate.generateFromModel(
            modelFilePath: modelFilePath,
            customizations: customizations,
            applicationDescription: applicationDescription,
            modelOverride: modelOverride) { (codeGenerator, serviceModel) in
                try codeGenerator.generateFromModel(serviceModel: serviceModel, ...)
        }
    }
}

By default, the code generator will use \(applicationDescription.baseName)Model for the name of the model target and \(applicationDescription.baseName)Client for the name of the client target. You can override these defaults by using the ModelAndClientTargetSupport type.

public struct MyCodeGeneration {
    public static func generateFromModel<ModelType: ServiceModel>(
        modelFilePath: String,
        modelType: ModelType.Type,
        modelTargetName: String, clientTargetName: String,
        customizations: CodeGenerationCustomizations,
        applicationDescription: ApplicationDescription,
        modelOverride: ModelOverride?,
        ...) throws 
    -> ModelType {
        let targetSupport = ModelAndClientTargetSupport(modelTargetName: modelTargetName,
                                                        clientTargetName: clientTargetName)
                                                        
        return try ServiceModelGenerate.generateFromModel(
            modelFilePath: modelFilePath,
            customizations: customizations,
            applicationDescription: applicationDescription,
            targetSupport: targetSupport,
            modelOverride: modelOverride) { (codeGenerator, serviceModel) in
                try codeGenerator.generateFromModel(serviceModel: serviceModel, ...)
        }
    }
}

Further, if you are generating additional targets, you can use a custom type that provides the name of additional targets. This type will have to conform to the ModelTargetSupport and ClientTargetSupport protocols.

extension ServiceModelCodeGenerator where TargetSupportType: ModelTargetSupport & ClientTargetSupport & MyCustomTargetSupport {
    
    func generateFromModel<ModelType: ServiceModel>(serviceModel: ModelType,
                                                    ...) throws {
        let myClientDelegate = ...
        let myModelErrorsDelegate = ...

        generateClient(delegate: myClientDelegate)
        generateModelOperationsEnum()
        generateOperationsReporting()
        generateModelOperationClientInput()
        generateModelOperationClientOutput()
        generateModelOperationHTTPInput()
        generateModelOperationHTTPOutput()
        generateModelStructures()
        generateModelTypes()
        generateModelErrors(delegate: myModelErrorsDelegate)
        generateDefaultInstances(generationType: .internalTypes)

        // Call any custom generation functions as required
        // The `targetSupport` attribute will conform to the `MyCustomTargetSupport` protocol.
    }
}

public protocol MyCustomTargetSupport {
    var myCustomTargetName: String { get }
}

public struct MyTargetSupport: ModelTargetSupport, ClientTargetSupport, MyCustomTargetSupport {
    public let modelTargetName: String
    public let clientTargetName: String
    public let myCustomTargetName: String
    
    public init(modelTargetName: String, clientTargetName: String,
                    myCustomTargetName: String) {
        self.modelTargetName = modelTargetName
        self.clientTargetName = clientTargetName
        self.myCustomTargetName = myCustomTargetName
    }
}

public struct MyCodeGeneration {    
    public static func generateFromModel<ModelType: ServiceModel>(
        modelFilePath: String,
        modelType: ModelType.Type,
        modelTargetName: String, clientTargetName: String,
        myCustomTargetName: String,
        customizations: CodeGenerationCustomizations,
        applicationDescription: ApplicationDescription,
        modelOverride: ModelOverride?,
        ...) throws 
    -> ModelType {
        let targetSupport = MyTargetSupport(modelTargetName: modelTargetName,
                                            clientTargetName: clientTargetName,
                                            myCustomTargetName: myCustomTargetName)
                                                        
        return try ServiceModelGenerate.generateFromModel(
            modelFilePath: modelFilePath,
            customizations: customizations,
            applicationDescription: applicationDescription,
            targetSupport: targetSupport,
            modelOverride: modelOverride) { (codeGenerator, serviceModel) in
                try codeGenerator.generateFromModel(serviceModel: serviceModel, ...)
        }
    }
}

Further Concepts

The ServiceModel Protocol

The ServiceModel protocol represents the parsed service model and provides access to descriptions of the operations, fields and errors.

The ModelClientDelegate protocol

The ModelClientDelegate protocol provides customization points for the creation of service clients.

The ModelErrorsDelegate protocol

The ModelErrorsDelegate protocol provides customization points for handling errors returned from an application endpoint conforming to the service model.

The ModelOverride type

The ModelOverride type provides the opportunity to override values from the service model.

License

This library is licensed under the Apache 2.0 License.

service-model-swift-code-generate's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

service-model-swift-code-generate's Issues

Redundant use of public in generated default instances.

When generating default structure instances the public modifier is used redundantly in that it is on both the generated extension and the generated static method. This causes compiler warnings in the generated project for each model.

I recommend removing public from the generated static method. I can submit a PR for this change but I wanted to discuss it here first.

Come up with a way to provide default keys for a map based on the type of the key where multiple keys required

Come up with a way to provide default keys for a map based on the type of the key where multiple keys required.

Most resent attempt:

#76

if requiredSize == 1 {
let defaultKeyValue = getDefaultValue(type: keyType, fileBuilder: fileBuilder)
mapConstructor.append("\(defaultKeyValue): \(defaultValue)")
} else {
for index in 0..<requiredSize {
mapConstructor.append("\"Entry_\(index)\": \(defaultValue)")
}
}

The branch handling requiredSize > 1 can be improved by handling enum cases and values other than strings.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.