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

Expose a TypeMarker factory to wrap an arbitrary Type #2264

Merged
merged 2 commits into from
Mar 22, 2024
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
5 changes: 5 additions & 0 deletions changelog/@unreleased/pr-2264.v2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type: improvement
improvement:
description: Expose a TypeMarker factory to wrap an arbitrary Type
links:
- https://github.com/palantir/conjure-java/pull/2264
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Objects;

/**
* Captures generic type information.
Expand Down Expand Up @@ -49,6 +50,10 @@ protected TypeMarker() {
SafeArg.of("typeVariable", type));
}

private TypeMarker(Type type) {
this.type = Preconditions.checkNotNull(type, "Type is required");
}

public final Type getType() {
return type;
}
Expand All @@ -57,4 +62,29 @@ public final Type getType() {
public final String toString() {
return "TypeMarker{type=" + type + '}';
}

/** Create a new {@link TypeMarker} instance wrapping the provided {@link Type}. */
public static TypeMarker<?> of(Type type) {
return new WrappingTypeMarker(type);
}

private static final class WrappingTypeMarker extends TypeMarker<Object> {
private WrappingTypeMarker(Type type) {
super(type);
}

@Override
public int hashCode() {
return getType().hashCode();
}

@Override
public boolean equals(Object other) {
if (other instanceof WrappingTypeMarker) {
WrappingTypeMarker otherMarker = (WrappingTypeMarker) other;
return Objects.equals(getType(), otherMarker.getType());
}
return false;
}
Comment on lines +76 to +88
Copy link
Member

Choose a reason for hiding this comment

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

Should these be moved to TypeMarker? I don't see any reason why we wouldn't want this implementation for all TypeMarker instances.

I guess maybe it's a little weird to consider different anonymous types equal, but that feel like the correct behavior for TypeMarker.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went back and forth on this. We definitely want to allow caches to work correctly for these, where in the usual anonymous class creation path we’d get the same instance and didn’t need to worry about it.
Equals and hashcode are pretty special in that they should take implementation details into account, so I don’t think it would be correct to make them final in the base class.

I think in a follow-up id like to update our caches to create a copy of TypeMarker instances used as keys using TypeMarker.of(marker.getType()) to avoid holding onto encapsulating classes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

}
}