8000 Enhance type safety when getting tag values by dwalluck · Pull Request #63 · eclipse/packager · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Enhance type safety when getting tag values #63

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

8000
Merged
merged 5 commits into from
Apr 10, 2025

Conversation

dwalluck
Copy link
Contributor

This removes all uses of ReadableHeader::getValue which returns Object and replaces them with methods that return specific types. This simplifies the code and eliminates the need for the caller to cast the result.

The method RpmBaseTag::getDataType was added to store the tag's data type. The tag's data type is checked when the various ReadableHeader methods are called.

@dwalluck dwalluck requested a review from ctron April 12, 2024 21:59
This removes all uses of `ReadableHeader::getValue` which returns
`Object` and replaces them with methods that return specific types.
This simplifies the code and eliminates the need for the caller to
cast the result.

The method `RpmBaseTag::getDataType` was added to store the tag's
data type. The tag's data type is checked when the various
`ReadableHeader` methods are called.
Copy link
Contributor
@ctron ctron left a comment

Choose a reason for hiding this comment

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

I think it's an overall improvement. However, I think that the way generics/type arguments are being used isn't how Java works. I think we need some more work in this to provide some more type safety.

result.add(new Dependency(name, version, flagSet));
}
return result;
final List<String> names = header.getStringList(namesTag);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we make some breaking changes on how this function behaves. Which is ok. However, I also think we should document that.

So far, to my understanding, the function simply ignored unexpected values and types. Now it will throw an exception. And while it's a private method, I think it makese sense adding a note and tracing calls that lead to this call and put a note on the API.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the change is to throw the IllegalArgumentException instead of ignoring it. You mean to add javadoc for it (although it's an unchecked exception)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is the current javadoc acceptable? I put it in the main text now as @throws because it's unchecked, but I wasn't sure about that.

}

public Object getTagOrDefault(final T tag, final Object defaultValue) {
return getOptionalTag(tag).orElse(defaultValue);
@SuppressWarnings("unchecked")
Copy link
Contributor

Choose a reason for hiding this comment

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

Same for the next method, I think we should add an actual type check. IIRC, you can use dataType.cast(..) for this. However IIRC using (HeaderValue<E>) won't work, because that's simply being erased and becomes HeaderValue.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, I will try to use .cast() here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, now we're just returning HeaderValue with no type, so there's nothing to cast, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's still some inconsistency in my current code which still has:

public <E> Optional<HeaderValue> getOptionalTag(final T tag, Class<E> dataType);
private Optional<HeaderValue> getEntry(final int tag, Class<?> dataType);

Are you sure nothing is gained by HeaderValue<?>, then we'd have the type <E>, which says that the type in header value should match the type in the class argument.

<E> Optional<HeaderValue<E>> getOptionalTag(final T tag, Class<E> dataType);

Copy link
Contributor

Choose a reason for hiding this comment

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

Using:

<E> Optional<HeaderValue<E>> getOptionalTag(final T tag, Class<E> dataType);

would actually have a benefit if the type of the value really is being limited to E. That requires casting using dataType.cast(..). It would also be required to handle the case when the value is not of type E. Throw an exception, return None would both work.

The question is just if that makes the code calling into it much better?

Given Java's new pattern type construct (not sure I got the name right) one should be able to do something like:

if  (headers.getEntry(Tags.MyTag) instanceof String s) {
 // do something with s
}

When reading, the header can basically carry anything, and we can't control that. Only when creating a header, we could enforce (via the type system) that we user cannot create wrong headers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

would actually have a benefit if the type of the value really is being limited to E. That requires casting using dataType.cast(..). It would also be required to handle the case when the value is not of type E. Throw an exception, return None would both work.

My thoughts:

Adding a type parameter, say <E>, only seems to change two methods, getEntry and getOptionalTag, to take a Class<E> parameter. For the datatype.cast(), this doesn't work because the datatype is E, but we need HeaderValue<E>?

Also, now we're adding a type parameter to HeaderValue which never gets used by the class itself. This is different from adding it to RpmTagValue, where it is actually used.

@dwalluck
Copy link
Contributor Author

@ctron Diff in response to comments is ee04664

@dwalluck dwalluck merged commit 128a9ed into eclipse:master Apr 10, 2025
4 checks passed
@dwalluck dwalluck deleted the rpm-tag-value branch April 10, 2025 15:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0