Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// OperationGenerationModel.swift
//
//
//
// Created by Александр Кравченков on 19.10.2021.
//
Expand Down Expand Up @@ -63,11 +63,13 @@ public struct OperationGenerationModel: Encodable {
public let requestModel: Reference<RequestModel>?

public let pathParameters: [ParameterModel]
public let headerParameters: [ParameterModel]
public let queryParameters: [ParameterModel]
public let requestGenerationModel: DataGenerationModel?
public let responseGenerationModel: Keyed<DataGenerationModel>?

public let allGenerationResponses: [ResponseGenerationModel]?
public let id: String?

init(operationModel: OperationModel) {
self.httpMethod = operationModel.httpMethod
Expand All @@ -82,6 +84,7 @@ public struct OperationGenerationModel: Encodable {
.map { $0.value }
.sorted { $0.name < $1.name }
self.pathParameters = allParameters.filter { $0.location == .path }
self.headerParameters = allParameters.filter { $0.location == .header }
self.queryParameters = allParameters.filter { $0.location == .query }

let request = operationModel.requestModel?.value
Expand All @@ -108,6 +111,7 @@ public struct OperationGenerationModel: Encodable {
responses: response.values.map { DataGenerationModel(dataModel: $0) }
)
}
self.id = operationModel.id
}
}

Expand Down
20 changes: 19 additions & 1 deletion Sources/CodeGenerator/Models/PropertyModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ public struct PropertyModel {
public let type: PossibleType
public let isNullable: Bool
public let pattern: String?
public let example: Any?
public let format: String?
public let minimum: Int?
public let maximum: Int?
public let maxLength: Int?
public let minLength: Int?

/// This value will be used as type for generation
public let typeModel: ItemTypeModel
Expand All @@ -88,7 +94,13 @@ public struct PropertyModel {
description: String?,
type: PropertyModel.PossibleType,
isNullable: Bool,
pattern: String?) {
pattern: String?,
example: Any?,
format: String?,
minimum: Int?,
maximum: Int?,
minLength: Int?,
maxLength: Int?) {
self.name = name
self.description = description
self.type = type
Expand All @@ -99,6 +111,12 @@ public struct PropertyModel {
enumTypeName: type.enumTypeName,
aliasTypeName: type.aliasTypeName)
self.pattern = pattern
self.example = example
self.format = format
self.minimum = minimum
self.maximum = maximum
self.minLength = minLength
self.maxLength = maxLength
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// OperationModel.swift
//
//
//
// Created by Александр Кравченков on 17.12.2020.
//
Expand Down Expand Up @@ -56,19 +56,21 @@ public struct OperationModel: Encodable {
public let parameters: [Reference<ParameterModel>]?
public let responses: [Reference<ResponseModel>]?
public let requestModel: Reference<RequestModel>?
public let id: String?

init(httpMethod: String,
summary: String?,
description: String?,
parameters: [Reference<ParameterModel>]?,
responses: [Reference<ResponseModel>]?,
requestModel: Reference<RequestModel>?) {
requestModel: Reference<RequestModel>?,
id: String?) {
self.httpMethod = httpMethod
self.summary = summary

self.description = description
self.parameters = parameters
self.responses = responses
self.requestModel = requestModel
self.id = id
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ public class DefaultTemplateFiller: TemplateFiller {
$0.withEscapedCharacters()
}

templateExtension.registerStringFilter("splitByHyphenAndGetLastNonEmpty") {
$0.splitByHyphenAndGetLastNonEmpty()
}

templateExtension.registerStringFilter("splitByUppercaseAndGetLast") {
$0.splitByUppercaseAndGetLast()
}

return templateExtension
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,25 @@ public class Resolver {
description: property.description,
type: .array(.init(name: "", itemsType: try arrayItemTypeUnwrapper(arr.itemsType))),
isNullable: property.nullable,
pattern: property.pattern)
pattern: property.pattern,
example: property.example,
format: property.format,
minimum: property.minimum,
maximum: property.maximum,
minLength: property.minLength,
maxLength: property.maxLength)
case .simple(let val):
return .init(name: property.name,
description: property.description,
type: try propertyTypeUnwrapper(val),
isNullable: property.nullable,
pattern: property.pattern)
pattern: property.pattern,
example: property.example,
format: property.format,
minimum: property.minimum,
maximum: property.maximum,
minLength: property.minLength,
maxLength: property.maxLength)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// File.swift
//
//
//
// Created by Александр Кравченков on 17.12.2020.
//
Expand Down Expand Up @@ -67,7 +67,7 @@ public struct TreeParser {
func parse(operation: OperationNode, current: DependencyWithTree, other: [DependencyWithTree]) throws -> OperationModel {

let params = try operation.parameters.map { parameter -> Reference<ParameterModel> in

return try wrap(
self.parametersParser.parse(parameter: parameter, current: current, other: other),
message: "While parsing parameter \(parameter.view)")
Expand All @@ -94,7 +94,8 @@ public struct TreeParser {
description: operation.description,
parameters: params,
responses: responses,
requestModel: requestBody
requestModel: requestBody,
id: operation.id
)
}
}
43 changes: 43 additions & 0 deletions Sources/Common/Extensions/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,49 @@ extension String {
.joined()
}

/// Splits string by '-' and returns last element.
public func splitByHyphenAndGetLastNonEmpty() -> String {
let parts = self.components(separatedBy: "-").filter { !$0.isEmpty }
return parts.last ?? ""
}

/// Splits string by Uppercase letter and returns last element.
/// Example: UpdateProfileRequest returns Request
public func splitByUppercaseAndGetLast() -> String {
do {
let pattern = "(?<!^)(?=[A-Z])"
let regex = try NSRegularExpression(pattern: pattern, options: [])

let matches = regex.matches(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count))

var splitIndices = [String.Index]()
for match in matches {
let range = match.range
if let index = Range(range, in: self)?.lowerBound {
splitIndices.append(index)
}
}

var parts = [String]()
var previousIndex = self.startIndex

for index in splitIndices {
let part = String(self[previousIndex..<index])
parts.append(part)
previousIndex = index
}

parts.append(String(self[previousIndex...]))

let nonEmptyParts = parts.filter { !$0.isEmpty }
return nonEmptyParts.last ?? ""

} catch {
print("Regex error: \(error)")
return ""
}
Comment on lines +156 to +187

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Кажется, можно сильно упростить

Suggested change
do {
let pattern = "(?<!^)(?=[A-Z])"
let regex = try NSRegularExpression(pattern: pattern, options: [])
let matches = regex.matches(in: self, options: [], range: NSRange(location: 0, length: self.utf16.count))
var splitIndices = [String.Index]()
for match in matches {
let range = match.range
if let index = Range(range, in: self)?.lowerBound {
splitIndices.append(index)
}
}
var parts = [String]()
var previousIndex = self.startIndex
for index in splitIndices {
let part = String(self[previousIndex..<index])
parts.append(part)
previousIndex = index
}
parts.append(String(self[previousIndex...]))
let nonEmptyParts = parts.filter { !$0.isEmpty }
return nonEmptyParts.last ?? ""
} catch {
print("Regex error: \(error)")
return ""
}
guard let lastUppercaseIndex = self.lastIndex(where: \.isUppercase) else {
return self
}
return String(self[lastUppercaseIndex...])

}

private func pathToCamelCase() -> String {
return self
.split(whereSeparator: { $0 == "/" || $0 == "_" })
Expand Down
58 changes: 45 additions & 13 deletions Sources/GASTBuilder/Builders/AnySchemaBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,34 +161,66 @@ public struct AnySchemaBuilder: SchemaBuilder {

func build(object: ObjectSchema, meta: Metadata, name: String, apiDefinitionFileRef: String) throws -> SchemaModelNode {
let properties = try object.properties.map { property -> PropertyNode in
let type = try wrap(property.schema.extractType(),
message: "In object \(name), in property \(property.name)")

let schema = property.schema
let type = try wrap(
schema.extractType(),
message: "In object \(name), in property \(property.name)"
)

var isNullable = property.isNullable

if self.useNewNullableDeterminationStrategy {
isNullable = property.schema.metadata.nullable
isNullable = schema.metadata.nullable
}

var pattern: String?
var format: String?
var minimum: Int?
var maximum: Int?
var minLength: Int?
var maxLength: Int?

switch property.schema.type {
switch schema.type {
case .string(let stringSchema):
pattern = stringSchema.pattern
format = stringSchema.format?.rawValue
minLength = stringSchema.minLength
maxLength = stringSchema.maxLength

case .number(let numberSchema):
format = numberSchema.format?.rawValue
minimum = numberSchema.minimum.flatMap { Int($0) }
maximum = numberSchema.maximum.flatMap { Int($0) }

case .integer(let integerSchema):
format = integerSchema.format?.rawValue
minimum = integerSchema.minimum
maximum = integerSchema.maximum

default:
break
}

return PropertyNode(name: property.name,
type: type,
description: property.schema.metadata.description,
example: property.schema.metadata.example,
nullable: isNullable,
pattern: pattern)
return PropertyNode(
name: property.name,
type: type,
description: schema.metadata.description,
example: schema.metadata.example,
nullable: isNullable,
pattern: pattern,
format: format,
minimum: minimum,
maximum: maximum,
maxLength: maxLength,
minLength: minLength
)
}

return SchemaModelNode(name: name, properties: properties, description: meta.description, apiDefinitionFileRef: apiDefinitionFileRef)
return SchemaModelNode(
name: name,
properties: properties,
description: meta.description,
apiDefinitionFileRef: apiDefinitionFileRef
)
}

func build(array: ArraySchema, name: String, apiDefinitionFileRef: String) throws -> SchemaArrayNode {
Expand Down
8 changes: 4 additions & 4 deletions Sources/GASTBuilder/Builders/AnyServiceBuilder.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// AnyServiceBuilder.swift
//
//
//
// Created by Александр Кравченков on 14.12.2020.
//
Expand All @@ -17,7 +17,7 @@ public protocol ServiceBuilder {
}

/// Default implementation for `ServiceBuilder`
///
///
/// Builds `path` elements of Open-API spec
///
/// **WARNING**
Expand All @@ -34,7 +34,6 @@ public struct AnyServiceBuilder: ServiceBuilder {
let schemaBuilder: SchemaBuilder
let requestBodyBuilder: RequestBodyBuilder
let responseBuilder: ResponseBuilder

public init(parameterBuilder: ParametersBuilder,
schemaBuilder: SchemaBuilder,
requestBodyBuilder: RequestBodyBuilder,
Expand Down Expand Up @@ -93,7 +92,8 @@ extension AnyServiceBuilder {
summary: operation.summary,
parameters: params,
requestBody: requestBody,
responses: responses)
responses: responses,
id: operation.generatedIdentifier)
}
}

Expand Down
17 changes: 16 additions & 1 deletion Sources/GASTTree/PropertyNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,34 @@ public struct PropertyNode {
public let example: Any?
public let nullable: Bool
public let pattern: String?
public let format: String?
public let minimum: Int?
public let maximum: Int?
public let maxLength: Int?
public let minLength: Int?

public init(name: String,
type: PossibleType,
description: String?,
example: Any?,
nullable: Bool,
pattern: String?) {
pattern: String?,
format: String?,
minimum: Int?,
maximum: Int?,
maxLength: Int?,
minLength: Int?) {
self.name = name
self.type = type
self.description = description
self.example = example
self.nullable = nullable
self.pattern = pattern
self.format = format
self.minimum = minimum
self.maximum = maximum
self.minLength = minLength
self.maxLength = maxLength
}
}

Expand Down
Loading