Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For Boolean, Double and Integer properties, getters should be NonNull #178

Merged
merged 2 commits into from
Mar 13, 2019
Merged
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
12 changes: 6 additions & 6 deletions Examples/Java/Sources/Everything.java
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ public int hashCode() {
return this.arrayProp;
}

public @Nullable Boolean getBooleanProp() {
return this.booleanProp;
public @NonNull Boolean getBooleanProp() {
return this.booleanProp == null ? Boolean.FALSE : this.booleanProp;
}

public @Nullable Date getDateProp() {
Expand All @@ -300,8 +300,8 @@ public int hashCode() {
return this.intEnum;
}

public @Nullable Integer getIntProp() {
return this.intProp;
public @NonNull Integer getIntProp() {
return this.intProp == null ? 0 : this.intProp;
}

public @Nullable List<Object> getListPolymorphicValues() {
Expand Down Expand Up @@ -356,8 +356,8 @@ public int hashCode() {
return this.mapWithPrimitiveValues;
}

public @Nullable Double getNumberProp() {
return this.numberProp;
public @NonNull Double getNumberProp() {
return this.numberProp == null ? 0 : this.numberProp;
}

public @Nullable User getOtherModelProp() {
Expand Down
8 changes: 4 additions & 4 deletions Examples/Java/Sources/Image.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,16 @@ public int hashCode() {
width);
}

public @Nullable Integer getHeight() {
return this.height;
public @NonNull Integer getHeight() {
return this.height == null ? 0 : this.height;
}

public @Nullable String getUrl() {
return this.url;
}

public @Nullable Integer getWidth() {
return this.width;
public @NonNull Integer getWidth() {
return this.width == null ? 0 : this.width;
}

public boolean getHeightIsSet() {
Expand Down
16 changes: 8 additions & 8 deletions Examples/Java/Sources/VariableSubtitution.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,20 +94,20 @@ public int hashCode() {
newProp);
}

public @Nullable Integer getAllocProp() {
return this.allocProp;
public @NonNull Integer getAllocProp() {
return this.allocProp == null ? 0 : this.allocProp;
}

public @Nullable Integer getCopyProp() {
return this.copyProp;
public @NonNull Integer getCopyProp() {
return this.copyProp == null ? 0 : this.copyProp;
}

public @Nullable Integer getMutableCopyProp() {
return this.mutableCopyProp;
public @NonNull Integer getMutableCopyProp() {
return this.mutableCopyProp == null ? 0 : this.mutableCopyProp;
}

public @Nullable Integer getNewProp() {
return this.newProp;
public @NonNull Integer getNewProp() {
return this.newProp == null ? 0 : this.newProp;
}

public boolean getAllocPropIsSet() {
Expand Down
43 changes: 32 additions & 11 deletions Sources/Core/JavaIR.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,24 @@ struct JavaModifier: OptionSet {
}
}

enum JavaAnnotation: String {
case override = "Override"
case nullable = "Nullable"
case nonnull = "NonNull"
enum JavaAnnotation: Hashable {
case override
case nullable
case nonnull
case serializedName(name: String)

var rendered: String {
switch self {
case .override:
return "Override"
case .nullable:
return "Nullable"
case .nonnull:
return "NonNull"
case let .serializedName(name):
return "SerializedName(\"\(name)\")"
}
}
}

public struct JavaIR {
Expand All @@ -38,16 +52,19 @@ public struct JavaIR {
let modifiers: JavaModifier
let body: [String]
let signature: String
let throwableExceptions: [String]

func render() -> [String] {
// HACK: We should actually have an enum / optionset that we can check for abstract, static, ...
let annotationLines = annotations.map { "@\($0.rawValue)" }
let annotationLines = annotations.map { "@\($0.rendered)" }

let throwsString = throwableExceptions.isEmpty ? "" : " throws " + throwableExceptions.joined(separator: ", ")

if modifiers.contains(.abstract) {
return annotationLines + ["\(modifiers.render()) \(signature);"]
return annotationLines + ["\(modifiers.render()) \(signature)\(throwsString);"]
}

var toRender = annotationLines + ["\(modifiers.render()) \(signature) {"]
var toRender = annotationLines + ["\(modifiers.render()) \(signature)\(throwsString) {"]

if !body.isEmpty {
toRender.append(-->body)
Expand All @@ -59,7 +76,7 @@ public struct JavaIR {
}

public struct Property {
let annotations: Set<String>
let annotations: Set<JavaAnnotation>
let modifiers: JavaModifier
let type: String
let name: String
Expand All @@ -68,7 +85,7 @@ public struct JavaIR {
func render() -> String {
var prop = ""
if !annotations.isEmpty {
prop.append(annotations.map { "@\($0)" }.joined(separator: " ") + " ")
prop.append(annotations.map { "@\($0.rendered)" }.joined(separator: " ") + " ")
}
prop.append("\(modifiers.render()) \(type) \(name)")
if !initialValue.isEmpty {
Expand All @@ -80,7 +97,11 @@ public struct JavaIR {
}

static func method(annotations: Set<JavaAnnotation> = [], _ modifiers: JavaModifier, _ signature: String, body: () -> [String]) -> JavaIR.Method {
return JavaIR.Method(annotations: annotations, modifiers: modifiers, body: body(), signature: signature)
return JavaIR.Method(annotations: annotations, modifiers: modifiers, body: body(), signature: signature, throwableExceptions: [])
}

static func methodThatThrows(annotations: Set<JavaAnnotation> = [], _ modifiers: JavaModifier, _ signature: String, _ throwableExceptions: [String], body: () -> [String]) -> JavaIR.Method {
return JavaIR.Method(annotations: annotations, modifiers: modifiers, body: body(), signature: signature, throwableExceptions: throwableExceptions)
}

static func ifBlock(condition: String, body: () -> [String]) -> String {
Expand Down Expand Up @@ -181,7 +202,7 @@ public struct JavaIR {

let extendsStmt = extends.map { " extends \($0) " } ?? ""

var lines = annotations.map { "@\($0.rawValue)" } + [
var lines = annotations.map { "@\($0.rendered)" } + [
"\(modifiers.render()) class \(name)\(extendsStmt)\(implementsStmt) {",
]

Expand Down
52 changes: 41 additions & 11 deletions Sources/Core/JavaModelRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public struct JavaModelRenderer: JavaFileRenderer {

func renderModelProperties(modifiers _: JavaModifier = [.private]) -> [[JavaIR.Property]] {
let props = transitiveProperties.map { param, schemaObj in
JavaIR.Property(annotations: ["SerializedName(\"\(param)\")"], modifiers: [.private], type: self.typeFromSchema(param, schemaObj), name: param.snakeCaseToPropertyName(), initialValue: "")
JavaIR.Property(annotations: [.serializedName(name: param)], modifiers: [.private], type: self.typeFromSchema(param, schemaObj), name: param.snakeCaseToPropertyName(), initialValue: "")
}

let bits = JavaIR.Property(annotations: [], modifiers: [.private], type: "int", name: "_bits", initialValue: "0")
Expand All @@ -76,11 +76,39 @@ public struct JavaModelRenderer: JavaFileRenderer {
return [props, bitmasks, [bits]]
}

func renderModelGetters(modifiers: JavaModifier = [.public]) -> [JavaIR.Method] {
func propertyGetterForParam(param: String, schemaObj: SchemaObjectProperty) -> JavaIR.Method {
let propertyName = param.snakeCaseToPropertyName()
let capitalizedPropertyName = param.snakeCaseToCapitalizedPropertyName()

// For Booleans, Integers and Doubles, make the getter method @NonNull and squash to a default value if necessary.
// This makes callers less susceptible to null pointer exceptions.
switch schemaObj.schema {
rahul-malik marked this conversation as resolved.
Show resolved Hide resolved
case .boolean:
rahul-malik marked this conversation as resolved.
Show resolved Hide resolved
return JavaIR.method([.public], "@NonNull Boolean get" + capitalizedPropertyName + "()") { [
"return this." + propertyName + " == null ? Boolean.FALSE : this." + propertyName + ";",
]
}
case .integer:
return JavaIR.method([.public], "@NonNull Integer get" + capitalizedPropertyName + "()") { [
"return this." + propertyName + " == null ? 0 : this." + propertyName + ";",
]
}
case .float:
return JavaIR.method([.public], "@NonNull Double get" + capitalizedPropertyName + "()") { [
"return this." + propertyName + " == null ? 0 : this." + propertyName + ";",
]
}
default:
return JavaIR.method([.public], typeFromSchema(param, schemaObj) + " get" + capitalizedPropertyName + "()") { [
"return this." + propertyName + ";",
]
}
}
}

func renderModelPropertyGetters() -> [JavaIR.Method] {
let getters = transitiveProperties.map { param, schemaObj in
JavaIR.method(modifiers, self.typeFromSchema(param, schemaObj) + " get" + param.snakeCaseToCapitalizedPropertyName() + "()") { [
"return this." + param.snakeCaseToPropertyName() + ";",
] }
propertyGetterForParam(param: param, schemaObj: schemaObj)
}
return getters
}
Expand Down Expand Up @@ -164,7 +192,7 @@ public struct JavaModelRenderer: JavaFileRenderer {

func renderBuilderProperties(modifiers _: JavaModifier = [.private]) -> [[JavaIR.Property]] {
let props = transitiveProperties.map { param, schemaObj in
JavaIR.Property(annotations: ["SerializedName(\"\(param)\")"], modifiers: [.private], type: self.typeFromSchema(param, schemaObj), name: param.snakeCaseToPropertyName(), initialValue: "")
JavaIR.Property(annotations: [.serializedName(name: param)], modifiers: [.private], type: self.typeFromSchema(param, schemaObj), name: param.snakeCaseToPropertyName(), initialValue: "")
}

let bits = JavaIR.Property(annotations: [], modifiers: [.private], type: "int", name: "_bits", initialValue: "0")
Expand Down Expand Up @@ -215,18 +243,20 @@ public struct JavaModelRenderer: JavaFileRenderer {
"this.elementTypeAdapter = gson.getAdapter(JsonElement.class);",
] }

let write = JavaIR.method(
let write = JavaIR.methodThatThrows(
annotations: [JavaAnnotation.override],
[.public],
"void write(JsonWriter writer, " + className + " value) throws IOException"
"void write(JsonWriter writer, " + className + " value)",
["IOException"]
) { [
"this.delegateTypeAdapter.write(writer, value);",
] }

let read = JavaIR.method(
let read = JavaIR.methodThatThrows(
annotations: [JavaAnnotation.override],
[.public],
className + " read(JsonReader reader) throws IOException"
className + " read(JsonReader reader)",
["IOException"]
) { [
"JsonElement tree = this.elementTypeAdapter.read(reader);",
className + " model = this.delegateTypeAdapter.fromJsonTree(tree);",
Expand Down Expand Up @@ -378,7 +408,7 @@ public struct JavaModelRenderer: JavaFileRenderer {
self.renderModelEquals(),
self.renderModelHashCode(),
] +
renderModelGetters() +
renderModelPropertyGetters() +
renderModelIsSetCheckers(),
enums: enumProps,
innerClasses: [
Expand Down