From 3dad2c2c9667b5cb94e145afebd1fe2297a71b65 Mon Sep 17 00:00:00 2001 From: Michael Wintermeyer Date: Tue, 7 Dec 2021 12:39:18 -0500 Subject: [PATCH] Add deprecated annotation on all completed stage builder methods (#1569) All completed stage builder methods now properly include deprecation annotations, if relevant. Previously, they could be missing for some methods. --- changelog/@unreleased/pr-1569.v2.yml | 6 + .../palantir/product/ManyFieldExample.java | 6 + .../product/MultipleFieldsOnlyFinalStage.java | 229 +++++++++++++++++- .../product/MultipleOrderedStages.java | 91 ++++++- .../palantir/product/ManyFieldExample.java | 6 + .../conjure/java/types/BeanGenerator.java | 5 + .../test/resources/example-staged-types.yml | 15 ++ .../src/test/resources/example-types.yml | 1 + 8 files changed, 343 insertions(+), 16 deletions(-) create mode 100644 changelog/@unreleased/pr-1569.v2.yml diff --git a/changelog/@unreleased/pr-1569.v2.yml b/changelog/@unreleased/pr-1569.v2.yml new file mode 100644 index 000000000..079dc19de --- /dev/null +++ b/changelog/@unreleased/pr-1569.v2.yml @@ -0,0 +1,6 @@ +type: improvement +improvement: + description: All completed stage builder methods now properly include deprecation + annotations, if relevant. Previously, they could be missing for some methods. + links: + - https://github.com/palantir/conjure-java/pull/1569 diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/ManyFieldExample.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/ManyFieldExample.java index 65a6d3494..3df9148b5 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/ManyFieldExample.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/ManyFieldExample.java @@ -88,9 +88,11 @@ public double getDoubleValue() { /** * docs for optionalItem field + * @deprecated an optional field is deprecated */ @JsonProperty("optionalItem") @JsonInclude(JsonInclude.Include.NON_ABSENT) + @Deprecated public Optional getOptionalItem() { return this.optionalItem; } @@ -279,7 +281,9 @@ public Builder doubleValue(double doubleValue) { /** * docs for optionalItem field + * @deprecated an optional field is deprecated */ + @Deprecated @JsonSetter(value = "optionalItem", nulls = Nulls.SKIP) public Builder optionalItem(@Nonnull Optional optionalItem) { checkNotBuilt(); @@ -289,7 +293,9 @@ public Builder optionalItem(@Nonnull Optional optionalItem) { /** * docs for optionalItem field + * @deprecated an optional field is deprecated */ + @Deprecated public Builder optionalItem(@Nonnull String optionalItem) { checkNotBuilt(); this.optionalItem = Optional.of(Preconditions.checkNotNull(optionalItem, "optionalItem cannot be null")); diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/MultipleFieldsOnlyFinalStage.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/MultipleFieldsOnlyFinalStage.java index 4617761e9..59dfe7e66 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/MultipleFieldsOnlyFinalStage.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/MultipleFieldsOnlyFinalStage.java @@ -33,15 +33,34 @@ public final class MultipleFieldsOnlyFinalStage { private final Set itemsSet; + private final List itemsOld; + + private final Map itemsMapOld; + + private final Optional optionalItemOld; + + private final Set itemsSetOld; + private int memoizedHashCode; private MultipleFieldsOnlyFinalStage( - List items, Map itemsMap, Optional optionalItem, Set itemsSet) { - validateFields(items, itemsMap, optionalItem, itemsSet); + List items, + Map itemsMap, + Optional optionalItem, + Set itemsSet, + List itemsOld, + Map itemsMapOld, + Optional optionalItemOld, + Set itemsSetOld) { + validateFields(items, itemsMap, optionalItem, itemsSet, itemsOld, itemsMapOld, optionalItemOld, itemsSetOld); this.items = Collections.unmodifiableList(items); this.itemsMap = Collections.unmodifiableMap(itemsMap); this.optionalItem = optionalItem; this.itemsSet = Collections.unmodifiableSet(itemsSet); + this.itemsOld = Collections.unmodifiableList(itemsOld); + this.itemsMapOld = Collections.unmodifiableMap(itemsMapOld); + this.optionalItemOld = optionalItemOld; + this.itemsSetOld = Collections.unmodifiableSet(itemsSetOld); } @JsonProperty("items") @@ -65,6 +84,43 @@ public Set getItemsSet() { return this.itemsSet; } + /** + * @deprecated this list is deprecated + */ + @JsonProperty("itemsOld") + @Deprecated + public List getItemsOld() { + return this.itemsOld; + } + + /** + * @deprecated this map is deprecated + */ + @JsonProperty("itemsMapOld") + @Deprecated + public Map getItemsMapOld() { + return this.itemsMapOld; + } + + /** + * @deprecated this optional is deprecated + */ + @JsonProperty("optionalItemOld") + @JsonInclude(JsonInclude.Include.NON_ABSENT) + @Deprecated + public Optional getOptionalItemOld() { + return this.optionalItemOld; + } + + /** + * @deprecated this set is deprecated + */ + @JsonProperty("itemsSetOld") + @Deprecated + public Set getItemsSetOld() { + return this.itemsSetOld; + } + @Override public boolean equals(Object other) { return this == other @@ -75,14 +131,26 @@ private boolean equalTo(MultipleFieldsOnlyFinalStage other) { return this.items.equals(other.items) && this.itemsMap.equals(other.itemsMap) && this.optionalItem.equals(other.optionalItem) - && this.itemsSet.equals(other.itemsSet); + && this.itemsSet.equals(other.itemsSet) + && this.itemsOld.equals(other.itemsOld) + && this.itemsMapOld.equals(other.itemsMapOld) + && this.optionalItemOld.equals(other.optionalItemOld) + && this.itemsSetOld.equals(other.itemsSetOld); } @Override public int hashCode() { int result = memoizedHashCode; if (result == 0) { - result = Objects.hash(this.items, this.itemsMap, this.optionalItem, this.itemsSet); + result = Objects.hash( + this.items, + this.itemsMap, + this.optionalItem, + this.itemsSet, + this.itemsOld, + this.itemsMapOld, + this.optionalItemOld, + this.itemsSetOld); memoizedHashCode = result; } return result; @@ -91,16 +159,28 @@ public int hashCode() { @Override public String toString() { return "MultipleFieldsOnlyFinalStage{items: " + items + ", itemsMap: " + itemsMap + ", optionalItem: " - + optionalItem + ", itemsSet: " + itemsSet + '}'; + + optionalItem + ", itemsSet: " + itemsSet + ", itemsOld: " + itemsOld + ", itemsMapOld: " + itemsMapOld + + ", optionalItemOld: " + optionalItemOld + ", itemsSetOld: " + itemsSetOld + '}'; } private static void validateFields( - List items, Map itemsMap, Optional optionalItem, Set itemsSet) { + List items, + Map itemsMap, + Optional optionalItem, + Set itemsSet, + List itemsOld, + Map itemsMapOld, + Optional optionalItemOld, + Set itemsSetOld) { List missingFields = null; missingFields = addFieldIfMissing(missingFields, items, "items"); missingFields = addFieldIfMissing(missingFields, itemsMap, "itemsMap"); missingFields = addFieldIfMissing(missingFields, optionalItem, "optionalItem"); missingFields = addFieldIfMissing(missingFields, itemsSet, "itemsSet"); + missingFields = addFieldIfMissing(missingFields, itemsOld, "itemsOld"); + missingFields = addFieldIfMissing(missingFields, itemsMapOld, "itemsMapOld"); + missingFields = addFieldIfMissing(missingFields, optionalItemOld, "optionalItemOld"); + missingFields = addFieldIfMissing(missingFields, itemsSetOld, "itemsSetOld"); if (missingFields != null) { throw new SafeIllegalArgumentException( "Some required fields have not been set", SafeArg.of("missingFields", missingFields)); @@ -111,7 +191,7 @@ private static List addFieldIfMissing(List prev, Object fieldVal List missingFields = prev; if (fieldValue == null) { if (missingFields == null) { - missingFields = new ArrayList<>(4); + missingFields = new ArrayList<>(8); } missingFields.add(fieldName); } @@ -135,6 +215,14 @@ public static final class Builder { private Set itemsSet = new LinkedHashSet<>(); + private List itemsOld = new ArrayList<>(); + + private Map itemsMapOld = new LinkedHashMap<>(); + + private Optional optionalItemOld = Optional.empty(); + + private Set itemsSetOld = new LinkedHashSet<>(); + private Builder() {} public Builder from(MultipleFieldsOnlyFinalStage other) { @@ -143,6 +231,10 @@ public Builder from(MultipleFieldsOnlyFinalStage other) { itemsMap(other.getItemsMap()); optionalItem(other.getOptionalItem()); itemsSet(other.getItemsSet()); + itemsOld(other.getItemsOld()); + itemsMapOld(other.getItemsMapOld()); + optionalItemOld(other.getOptionalItemOld()); + itemsSetOld(other.getItemsSetOld()); return this; } @@ -219,10 +311,131 @@ public Builder itemsSet(String itemsSet) { return this; } + /** + * @deprecated this list is deprecated + */ + @Deprecated + @JsonSetter(value = "itemsOld", nulls = Nulls.SKIP) + public Builder itemsOld(@Nonnull Iterable itemsOld) { + checkNotBuilt(); + this.itemsOld.clear(); + ConjureCollections.addAll(this.itemsOld, Preconditions.checkNotNull(itemsOld, "itemsOld cannot be null")); + return this; + } + + /** + * @deprecated this list is deprecated + */ + @Deprecated + public Builder addAllItemsOld(@Nonnull Iterable itemsOld) { + checkNotBuilt(); + ConjureCollections.addAll(this.itemsOld, Preconditions.checkNotNull(itemsOld, "itemsOld cannot be null")); + return this; + } + + /** + * @deprecated this list is deprecated + */ + @Deprecated + public Builder itemsOld(String itemsOld) { + checkNotBuilt(); + this.itemsOld.add(itemsOld); + return this; + } + + /** + * @deprecated this map is deprecated + */ + @Deprecated + @JsonSetter(value = "itemsMapOld", nulls = Nulls.SKIP) + public Builder itemsMapOld(@Nonnull Map itemsMapOld) { + checkNotBuilt(); + this.itemsMapOld.clear(); + this.itemsMapOld.putAll(Preconditions.checkNotNull(itemsMapOld, "itemsMapOld cannot be null")); + return this; + } + + /** + * @deprecated this map is deprecated + */ + @Deprecated + public Builder putAllItemsMapOld(@Nonnull Map itemsMapOld) { + checkNotBuilt(); + this.itemsMapOld.putAll(Preconditions.checkNotNull(itemsMapOld, "itemsMapOld cannot be null")); + return this; + } + + /** + * @deprecated this map is deprecated + */ + @Deprecated + public Builder itemsMapOld(String key, int value) { + checkNotBuilt(); + this.itemsMapOld.put(key, value); + return this; + } + + /** + * @deprecated this optional is deprecated + */ + @Deprecated + @JsonSetter(value = "optionalItemOld", nulls = Nulls.SKIP) + public Builder optionalItemOld(@Nonnull Optional optionalItemOld) { + checkNotBuilt(); + this.optionalItemOld = Preconditions.checkNotNull(optionalItemOld, "optionalItemOld cannot be null"); + return this; + } + + /** + * @deprecated this optional is deprecated + */ + @Deprecated + public Builder optionalItemOld(@Nonnull String optionalItemOld) { + checkNotBuilt(); + this.optionalItemOld = + Optional.of(Preconditions.checkNotNull(optionalItemOld, "optionalItemOld cannot be null")); + return this; + } + + /** + * @deprecated this set is deprecated + */ + @Deprecated + @JsonSetter(value = "itemsSetOld", nulls = Nulls.SKIP) + public Builder itemsSetOld(@Nonnull Iterable itemsSetOld) { + checkNotBuilt(); + this.itemsSetOld.clear(); + ConjureCollections.addAll( + this.itemsSetOld, Preconditions.checkNotNull(itemsSetOld, "itemsSetOld cannot be null")); + return this; + } + + /** + * @deprecated this set is deprecated + */ + @Deprecated + public Builder addAllItemsSetOld(@Nonnull Iterable itemsSetOld) { + checkNotBuilt(); + ConjureCollections.addAll( + this.itemsSetOld, Preconditions.checkNotNull(itemsSetOld, "itemsSetOld cannot be null")); + return this; + } + + /** + * @deprecated this set is deprecated + */ + @Deprecated + public Builder itemsSetOld(String itemsSetOld) { + checkNotBuilt(); + this.itemsSetOld.add(itemsSetOld); + return this; + } + public MultipleFieldsOnlyFinalStage build() { checkNotBuilt(); this._buildInvoked = true; - return new MultipleFieldsOnlyFinalStage(items, itemsMap, optionalItem, itemsSet); + return new MultipleFieldsOnlyFinalStage( + items, itemsMap, optionalItem, itemsSet, itemsOld, itemsMapOld, optionalItemOld, itemsSetOld); } private void checkNotBuilt() { diff --git a/conjure-java-core/src/integrationInput/java/com/palantir/product/MultipleOrderedStages.java b/conjure-java-core/src/integrationInput/java/com/palantir/product/MultipleOrderedStages.java index 676c76ffc..3b4594662 100644 --- a/conjure-java-core/src/integrationInput/java/com/palantir/product/MultipleOrderedStages.java +++ b/conjure-java-core/src/integrationInput/java/com/palantir/product/MultipleOrderedStages.java @@ -1,6 +1,7 @@ package com.palantir.product; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.Nulls; @@ -18,6 +19,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import javax.annotation.Generated; import javax.annotation.Nonnull; @@ -33,15 +35,22 @@ public final class MultipleOrderedStages { private final Map mappedRids; + private final Optional optionalItem; + private int memoizedHashCode; private MultipleOrderedStages( - OneField token, String item, Set items, Map mappedRids) { - validateFields(token, item, items, mappedRids); + OneField token, + String item, + Set items, + Map mappedRids, + Optional optionalItem) { + validateFields(token, item, items, mappedRids, optionalItem); this.token = token; this.item = item; this.items = Collections.unmodifiableSet(items); this.mappedRids = Collections.unmodifiableMap(mappedRids); + this.optionalItem = optionalItem; } @JsonProperty("token") @@ -64,6 +73,16 @@ public Map getMappedRids() { return this.mappedRids; } + /** + * @deprecated this optional is deprecated + */ + @JsonProperty("optionalItem") + @JsonInclude(JsonInclude.Include.NON_ABSENT) + @Deprecated + public Optional getOptionalItem() { + return this.optionalItem; + } + @Override public boolean equals(Object other) { return this == other || (other instanceof MultipleOrderedStages && equalTo((MultipleOrderedStages) other)); @@ -73,14 +92,15 @@ private boolean equalTo(MultipleOrderedStages other) { return this.token.equals(other.token) && this.item.equals(other.item) && this.items.equals(other.items) - && this.mappedRids.equals(other.mappedRids); + && this.mappedRids.equals(other.mappedRids) + && this.optionalItem.equals(other.optionalItem); } @Override public int hashCode() { int result = memoizedHashCode; if (result == 0) { - result = Objects.hash(this.token, this.item, this.items, this.mappedRids); + result = Objects.hash(this.token, this.item, this.items, this.mappedRids, this.optionalItem); memoizedHashCode = result; } return result; @@ -89,16 +109,21 @@ public int hashCode() { @Override public String toString() { return "MultipleOrderedStages{token: " + token + ", item: " + item + ", items: " + items + ", mappedRids: " - + mappedRids + '}'; + + mappedRids + ", optionalItem: " + optionalItem + '}'; } private static void validateFields( - OneField token, String item, Set items, Map mappedRids) { + OneField token, + String item, + Set items, + Map mappedRids, + Optional optionalItem) { List missingFields = null; missingFields = addFieldIfMissing(missingFields, token, "token"); missingFields = addFieldIfMissing(missingFields, item, "item"); missingFields = addFieldIfMissing(missingFields, items, "items"); missingFields = addFieldIfMissing(missingFields, mappedRids, "mappedRids"); + missingFields = addFieldIfMissing(missingFields, optionalItem, "optionalItem"); if (missingFields != null) { throw new SafeIllegalArgumentException( "Some required fields have not been set", SafeArg.of("missingFields", missingFields)); @@ -109,7 +134,7 @@ private static List addFieldIfMissing(List prev, Object fieldVal List missingFields = prev; if (fieldValue == null) { if (missingFields == null) { - missingFields = new ArrayList<>(4); + missingFields = new ArrayList<>(5); } missingFields.add(fieldName); } @@ -144,6 +169,18 @@ public interface Completed_StageBuilder { Completed_StageBuilder putAllMappedRids(@Nonnull Map mappedRids); Completed_StageBuilder mappedRids(ResourceIdentifier key, String value); + + /** + * @deprecated this optional is deprecated + */ + @Deprecated + Completed_StageBuilder optionalItem(@Nonnull Optional optionalItem); + + /** + * @deprecated this optional is deprecated + */ + @Deprecated + Completed_StageBuilder optionalItem(@Nonnull OneField optionalItem); } public interface Builder extends TokenStageBuilder, ItemStageBuilder, Completed_StageBuilder { @@ -168,6 +205,13 @@ public interface Builder extends TokenStageBuilder, ItemStageBuilder, Completed_ @Override Builder putAllMappedRids(@Nonnull Map mappedRids); + /** + * @deprecated this optional is deprecated + */ + @Deprecated + @Override + Builder optionalItem(@Nonnull Optional optionalItem); + @Override Builder token(@Nonnull OneField token); @@ -176,6 +220,13 @@ public interface Builder extends TokenStageBuilder, ItemStageBuilder, Completed_ @Override Builder item(@Nonnull String item); + + /** + * @deprecated this optional is deprecated + */ + @Deprecated + @Override + Builder optionalItem(@Nonnull OneField optionalItem); } @Generated("com.palantir.conjure.java.types.BeanBuilderGenerator") @@ -191,6 +242,8 @@ static final class DefaultBuilder implements Builder { private Map mappedRids = new LinkedHashMap<>(); + private Optional optionalItem = Optional.empty(); + private DefaultBuilder() {} public Builder from(MultipleOrderedStages other) { @@ -199,6 +252,7 @@ public Builder from(MultipleOrderedStages other) { item(other.getItem()); items(other.getItems()); mappedRids(other.getMappedRids()); + optionalItem(other.getOptionalItem()); return this; } @@ -256,10 +310,31 @@ public Builder mappedRids(ResourceIdentifier key, String value) { return this; } + /** + * @deprecated this optional is deprecated + */ + @Deprecated + @JsonSetter(value = "optionalItem", nulls = Nulls.SKIP) + public Builder optionalItem(@Nonnull Optional optionalItem) { + checkNotBuilt(); + this.optionalItem = Preconditions.checkNotNull(optionalItem, "optionalItem cannot be null"); + return this; + } + + /** + * @deprecated this optional is deprecated + */ + @Deprecated + public Builder optionalItem(@Nonnull OneField optionalItem) { + checkNotBuilt(); + this.optionalItem = Optional.of(Preconditions.checkNotNull(optionalItem, "optionalItem cannot be null")); + return this; + } + public MultipleOrderedStages build() { checkNotBuilt(); this._buildInvoked = true; - return new MultipleOrderedStages(token, item, items, mappedRids); + return new MultipleOrderedStages(token, item, items, mappedRids, optionalItem); } private void checkNotBuilt() { diff --git a/conjure-java-core/src/integrationInput/java/test/prefix/com/palantir/product/ManyFieldExample.java b/conjure-java-core/src/integrationInput/java/test/prefix/com/palantir/product/ManyFieldExample.java index ec6fd51f5..538dd3da5 100644 --- a/conjure-java-core/src/integrationInput/java/test/prefix/com/palantir/product/ManyFieldExample.java +++ b/conjure-java-core/src/integrationInput/java/test/prefix/com/palantir/product/ManyFieldExample.java @@ -89,9 +89,11 @@ public double getDoubleValue() { /** * docs for optionalItem field + * @deprecated an optional field is deprecated */ @JsonProperty("optionalItem") @JsonInclude(JsonInclude.Include.NON_ABSENT) + @Deprecated public Optional getOptionalItem() { return this.optionalItem; } @@ -281,7 +283,9 @@ public Builder doubleValue(double doubleValue) { /** * docs for optionalItem field + * @deprecated an optional field is deprecated */ + @Deprecated @JsonSetter(value = "optionalItem", nulls = Nulls.SKIP) public Builder optionalItem(@Nonnull Optional optionalItem) { checkNotBuilt(); @@ -291,7 +295,9 @@ public Builder optionalItem(@Nonnull Optional optionalItem) { /** * docs for optionalItem field + * @deprecated an optional field is deprecated */ + @Deprecated public Builder optionalItem(@Nonnull String optionalItem) { checkNotBuilt(); this.optionalItem = Optional.of(Preconditions.checkNotNull(optionalItem, "optionalItem cannot be null")); diff --git a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/BeanGenerator.java b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/BeanGenerator.java index 5340bf9cf..968c5850b 100644 --- a/conjure-java-core/src/main/java/com/palantir/conjure/java/types/BeanGenerator.java +++ b/conjure-java-core/src/main/java/com/palantir/conjure/java/types/BeanGenerator.java @@ -297,6 +297,7 @@ private static List generateMethodsForFinalStageField( EnrichedField enriched, TypeMapper typeMapper, ClassName returnClass) { List methodSpecs = new ArrayList<>(); Type type = enriched.conjureDef().getType(); + FieldDefinition definition = enriched.conjureDef(); methodSpecs.add(MethodSpec.methodBuilder(JavaNameSanitizer.sanitize(enriched.fieldName())) .addParameter(ParameterSpec.builder( @@ -305,6 +306,10 @@ private static List generateMethodsForFinalStageField( JavaNameSanitizer.sanitize(enriched.fieldName())) .addAnnotation(Nonnull.class) .build()) + .addJavadoc(Javadoc.render(definition.getDocs(), definition.getDeprecated()) + .map(rendered -> CodeBlock.of("$L", rendered)) + .orElseGet(() -> CodeBlock.builder().build())) + .addAnnotations(ConjureAnnotations.deprecation(definition.getDeprecated())) .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT) .returns(returnClass.box()) .build()); diff --git a/conjure-java-core/src/test/resources/example-staged-types.yml b/conjure-java-core/src/test/resources/example-staged-types.yml index c052f826b..b200b5d28 100644 --- a/conjure-java-core/src/test/resources/example-staged-types.yml +++ b/conjure-java-core/src/test/resources/example-staged-types.yml @@ -14,9 +14,24 @@ types: itemsMap: map optionalItem: optional itemsSet: set + itemsOld: + type: list + deprecated: this list is deprecated + itemsMapOld: + type: map + deprecated: this map is deprecated + optionalItemOld: + type: optional + deprecated: this optional is deprecated + itemsSetOld: + type: set + deprecated: this set is deprecated MultipleOrderedStages: fields: token: OneField item: string items: set mappedRids: map + optionalItem: + type: optional + deprecated: this optional is deprecated diff --git a/conjure-java-core/src/test/resources/example-types.yml b/conjure-java-core/src/test/resources/example-types.yml index d3061c217..5d36e127b 100644 --- a/conjure-java-core/src/test/resources/example-types.yml +++ b/conjure-java-core/src/test/resources/example-types.yml @@ -170,6 +170,7 @@ types: docs: docs for doubleValue field optionalItem: type: optional + deprecated: an optional field is deprecated docs: docs for optionalItem field items: type: list