Skip to content

Commit

Permalink
Updating casing of variable names and keys (#2996)
Browse files Browse the repository at this point in the history
  • Loading branch information
BobaFetters authored May 8, 2023
1 parent f50ebaf commit 202894c
Show file tree
Hide file tree
Showing 9 changed files with 296 additions and 19 deletions.
4 changes: 4 additions & 0 deletions Sources/ApolloCodegenLib/TemplateString.swift
Original file line number Diff line number Diff line change
Expand Up @@ -389,4 +389,8 @@ extension String {
return prefix(through: indexToChangeCase).lowercased() +
suffix(from: index(after: indexToChangeCase))
}

var isAllUppercased: Bool {
return self == self.uppercased()
}
}
10 changes: 5 additions & 5 deletions Sources/ApolloCodegenLib/Templates/InputObjectTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ struct InputObjectTemplate: TemplateRenderer {
) -> TemplateString {
TemplateString("""
\(fields.map({
"\($1.name.asInputParameterName): \($1.renderInputValueType(includeDefault: true, config: config.config))"
"\($1.name.asFieldPropertyName): \($1.renderInputValueType(includeDefault: true, config: config.config))"
}), separator: ",\n")
""")
}
Expand All @@ -100,17 +100,17 @@ struct InputObjectTemplate: TemplateRenderer {
_ fields: GraphQLInputFieldDictionary
) -> TemplateString {
TemplateString("""
\(fields.map({ "\"\($1.name)\": \($1.name.asInputParameterName)" }), separator: ",\n")
\(fields.map({ "\"\($1.name)\": \($1.name.asFieldPropertyName)" }), separator: ",\n")
""")
}

private func FieldPropertyTemplate(_ field: GraphQLInputField) -> TemplateString {
"""
\(documentation: field.documentation, config: config)
\(deprecationReason: field.deprecationReason, config: config)
public var \(field.name.asInputParameterName): \(field.renderInputValueType(config: config.config)) {
get { __data["\(field.name.firstLowercased)"] }
set { __data["\(field.name.firstLowercased)"] = newValue }
public var \(field.name.asFieldPropertyName): \(field.renderInputValueType(config: config.config)) {
get { __data["\(field.name)"] }
set { __data["\(field.name)"] = newValue }
}
"""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extension OperationTemplateRenderer {
return """
\(`init`)(\(list: variables.map(VariableParameter))) {
\(variables.map {
let name = $0.name.asInputParameterName
let name = $0.name.asFieldPropertyName
return "self.\(name) = \(name)"
}, separator: "\n")
}
Expand All @@ -24,15 +24,15 @@ extension OperationTemplateRenderer {
_ variables: [CompilationResult.VariableDefinition]
) -> TemplateString {
"""
\(variables.map { "public var \($0.name.asInputParameterName): \($0.type.rendered(as: .inputValue, config: config.config))"}, separator: "\n")
\(variables.map { "public var \($0.name.asFieldPropertyName): \($0.type.rendered(as: .inputValue, config: config.config))"}, separator: "\n")
"""
}

func VariableParameter(
_ variable: CompilationResult.VariableDefinition
) -> TemplateString {
"""
\(variable.name.asInputParameterName): \(variable.type.rendered(as: .inputValue, config: config.config))\
\(variable.name.asFieldPropertyName): \(variable.type.rendered(as: .inputValue, config: config.config))\
\(if: variable.defaultValue != nil, " = " + variable.renderVariableDefaultValue(config: config.config))
"""
}
Expand All @@ -46,7 +46,7 @@ extension OperationTemplateRenderer {
}

return """
public var __variables: \(if: !graphQLOperation, "GraphQLOperation.")Variables? { [\(list: variables.map { "\"\($0.name)\": \($0.name.asInputParameterName)"})] }
public var __variables: \(if: !graphQLOperation, "GraphQLOperation.")Variables? { [\(list: variables.map { "\"\($0.name)\": \($0.name.asFieldPropertyName)"})] }
"""
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import Foundation
extension String {
/// Renders the string as the property name for a field accessor on a generated `SelectionSet`.
/// This escapes the names of properties that would conflict with Swift reserved keywords.
var asFieldAccessorPropertyName: String {
escapeIf(in: SwiftKeywords.FieldAccessorNamesToEscape)
var asFieldPropertyName: String {
let str = self.isAllUppercased ? self.lowercased() : self.firstLowercased
return str.escapeIf(in: SwiftKeywords.FieldAccessorNamesToEscape)
}

var asEnumCaseName: String {
Expand All @@ -16,11 +17,7 @@ extension String {
SwiftKeywords.SelectionSetTypeNamesToSuffix.contains(self) ?
"\(self)_SelectionSet" : self
}

var asInputParameterName: String {
escapeIf(in: SwiftKeywords.InputParameterNamesToEscape).firstLowercased
}


var asTestMockFieldPropertyName: String {
escapeIf(in: SwiftKeywords.TestMockFieldNamesToEscape)
}
Expand Down
6 changes: 3 additions & 3 deletions Sources/ApolloCodegenLib/Templates/SelectionSetTemplate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ struct SelectionSetTemplate {
return """
\(documentation: field.underlyingField.documentation, config: config)
\(deprecationReason: field.underlyingField.deprecationReason, config: config)
public var \(field.responseKey.firstLowercased.asFieldAccessorPropertyName): \
public var \(field.responseKey.asFieldPropertyName): \
\(typeName(for: field, forceOptional: field.isConditionallyIncluded(in: scope))) {\
\(if: isMutable,
"""
Expand Down Expand Up @@ -426,7 +426,7 @@ struct SelectionSetTemplate {
) -> TemplateString {
let isOptional: Bool = field.type.isNullable || field.isConditionallyIncluded(in: scope)
return """
\(field.responseKey.asInputParameterName): \(typeName(for: field, forceOptional: isOptional))\
\(field.responseKey.asFieldPropertyName): \(typeName(for: field, forceOptional: isOptional))\
\(if: isOptional, " = nil")
"""
}
Expand Down Expand Up @@ -459,7 +459,7 @@ struct SelectionSetTemplate {
}()

return """
"\(field.responseKey)": \(field.responseKey.asInputParameterName)\
"\(field.responseKey)": \(field.responseKey.asFieldPropertyName)\
\(if: isEntityField, "._fieldData")
"""
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,66 @@ class InputObjectTemplateTests: XCTestCase {
// then
expect(actual).to(equalLineByLine(expected, atLine: 8, ignoringExtraLines: false))
}

func test__render__givenSingleFieldTypeInMixedCase__generatesParameterAndInitializerWithCorrectCasing() throws {
// given
buildSubject(fields: [
GraphQLInputField.mock("Field", type: .scalar(.string()), defaultValue: nil)
])

let expected = """
public init(
field: GraphQLNullable<String> = nil
) {
__data = InputDict([
"Field": field
])
}
public var field: GraphQLNullable<String> {
get { __data["Field"] }
set { __data["Field"] = newValue }
}
}
"""

// when
let actual = renderSubject()

// then
expect(actual).to(equalLineByLine(expected, atLine: 8, ignoringExtraLines: false))
}

func test__render__givenSingleFieldTypeInAllUppercase__generatesParameterAndInitializerWithCorrectCasing() throws {
// given
buildSubject(fields: [
GraphQLInputField.mock("FIELDNAME", type: .scalar(.string()), defaultValue: nil)
])

let expected = """
public init(
fieldname: GraphQLNullable<String> = nil
) {
__data = InputDict([
"FIELDNAME": fieldname
])
}
public var fieldname: GraphQLNullable<String> {
get { __data["FIELDNAME"] }
set { __data["FIELDNAME"] = newValue }
}
}
"""

// when
let actual = renderSubject()

// then
expect(actual).to(equalLineByLine(expected, atLine: 8, ignoringExtraLines: false))
}

func test__render__givenAllPossibleSchemaInputFieldTypes__generatesCorrectParametersAndInitializer() throws {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,90 @@ class OperationDefinition_VariableDefinition_Tests: XCTestCase {
// then
expect(actual).to(equal(expected))
}

func test__renderOperationVariableProperty_givenAllUppercaseVariableName_generatesCorrectlyCasedVariable() throws {
// given
subject = .mock("VARIABLE", type: .string(), defaultValue: nil)

let expected = "public var variable: GraphQLNullable<String>"

// when
buildTemplate()
let actual = template.VariableProperties([subject]).description

// then
expect(actual).to(equal(expected))
}

func test__renderOperationVariableProperty_givenMixedCaseVariableName_generatesCorrectlyCasedVariable() throws {
// given
subject = .mock("VariableName", type: .string(), defaultValue: nil)

let expected = "public var variableName: GraphQLNullable<String>"

// when
buildTemplate()
let actual = template.VariableProperties([subject]).description

// then
expect(actual).to(equal(expected))
}

func test__renderOperationVariableParameter_givenAllUppercaseVariableName_generatesCorrectlyCasedVariable() throws {
// given
subject = .mock("VARIABLE", type: .string(), defaultValue: nil)

let expected = "variable: GraphQLNullable<String>"

// when
buildTemplate()
let actual = template.VariableParameter(subject).description

// then
expect(actual).to(equal(expected))
}

func test__renderOperationVariableParameter_givenMixedCaseVariableName_generatesCorrectlyCasedVariable() throws {
// given
subject = .mock("VariableName", type: .string(), defaultValue: nil)

let expected = "variableName: GraphQLNullable<String>"

// when
buildTemplate()
let actual = template.VariableParameter(subject).description

// then
expect(actual).to(equal(expected))
}

func test__renderOperationVariableAccessor_givenAllUppercaseVariableName_generatesCorrectlyCasedVariable() throws {
// given
subject = .mock("VARIABLE", type: .string(), defaultValue: nil)

let expected = "public var __variables: Variables? { [\"VARIABLE\": variable] }"

// when
buildTemplate()
let actual = template.VariableAccessors([subject]).description

// then
expect(actual).to(equal(expected))
}

func test__renderOperationVariableAccessor_givenMixedCaseVariableName_generatesCorrectlyCasedVariable() throws {
// given
subject = .mock("VariableName", type: .string(), defaultValue: nil)

let expected = "public var __variables: Variables? { [\"VariableName\": variableName] }"

// when
buildTemplate()
let actual = template.VariableAccessors([subject]).description

// then
expect(actual).to(equal(expected))
}

func test__renderOperationVariableParameter_includeDefaultTrue__givenAllInputFieldTypes_nilDefaultValues__generatesCorrectParametersWithoutInitializer() throws {
// given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,45 @@ class SelectionSetTemplateTests: XCTestCase {
// then
expect(actual).to(equalLineByLine(expected, atLine: 7, ignoringExtraLines: true))
}

func test__render_selections__givenAllUppercase_generatesCorrectCasing() throws {
// given
schemaSDL = """
type Query {
allAnimals: [Animal!]
}
type Animal {
FIELDNAME: String
}
"""

document = """
query TestOperation {
allAnimals {
FIELDNAME
}
}
"""

let expected = """
public static var __selections: [ApolloAPI.Selection] { [
.field("__typename", String.self),
.field("FIELDNAME", String?.self),
] }
"""

// when
try buildSubjectAndOperation()
let allAnimals = try XCTUnwrap(
operation[field: "query"]?[field: "allAnimals"] as? IR.EntityField
)

let actual = subject.render(field: allAnimals)

// then
expect(actual).to(equalLineByLine(expected, atLine: 7, ignoringExtraLines: true))
}

func test__render_selections__givenCustomScalar_rendersFieldSelectionsWithNamespaceInAllConfigurations() throws {
// given
Expand Down Expand Up @@ -2405,6 +2444,42 @@ class SelectionSetTemplateTests: XCTestCase {
// then
expect(actual).to(equalLineByLine(expected, atLine: 12, ignoringExtraLines: true))
}

func test__render_fieldAccessors__givenFieldWithAllUpperCaseName_rendersFieldAccessorWithLowercaseName() throws {
// given
schemaSDL = """
type Query {
AllAnimals: [Animal!]
}
type Animal {
FIELDNAME: String!
}
"""

document = """
query TestOperation {
AllAnimals {
FIELDNAME
}
}
"""

let expected = """
public var fieldname: String { __data["FIELDNAME"] }
"""

// when
try buildSubjectAndOperation()
let allAnimals = try XCTUnwrap(
operation[field: "query"]?[field: "AllAnimals"] as? IR.EntityField
)

let actual = subject.render(field: allAnimals)

// then
expect(actual).to(equalLineByLine(expected, atLine: 12, ignoringExtraLines: true))
}

func test__render_fieldAccessors__givenFieldWithAlias_rendersAllFieldAccessors() throws {
// given
Expand Down Expand Up @@ -4068,6 +4143,8 @@ class SelectionSetTemplateTests: XCTestCase {
// then
expect(actual).to(equalLineByLine(expected, atLine: 8, ignoringExtraLines: true))
}



// MARK: - Inline Fragment Accessors

Expand Down
Loading

0 comments on commit 202894c

Please sign in to comment.