Skip to content

Conversation

@sebthom
Copy link
Contributor

@sebthom sebthom commented Oct 25, 2025

  • Replace reversed isAssignableFrom checks with instanceof to correctly handle subclasses (e.g., CreateFile derivatives) in write(...)
  • Add explicit JsonParseException for unknown ResourceOperation subtypes in write(...) to mirror read(...) and avoid silent malformed JSON
  • Improves protocol correctness and failure transparency when encountering unsupported operations

Tests: add ResourceOperationTypeAdapterTest covering subclass serialization and unknown subtype failure

@pisv
Copy link
Contributor

pisv commented Oct 28, 2025

@sebthom Good catch, thank you for the fix! 👍

It is already a great improvement, but would not it even better to check that the type passed to ResourceOperationTypeAdapter.create is assignable to CreateFile or DeleteFile or RenameFile? This would make it unnecessary to throw JsonParseException from InnerResourceOperationTypeAdapter.write.

(I don't quite like throwing JsonParseException from InnerResourceOperationTypeAdapter.write. According to its Javadoc, this exception is raised if there is a serious issue that occurs during parsing of a Json string. If anything, I'd prefer to throw AssertionError in this case.)

@sebthom
Copy link
Contributor Author

sebthom commented Oct 28, 2025

Would that mean the ResourceOperationTypeAdapter.create should throw an error instead of returning null when the type does not match? And if so which Exception type? IllegalArgumentException, JsonParseException, JsonSyntaxException?

@pisv
Copy link
Contributor

pisv commented Oct 28, 2025

Would that mean the ResourceOperationTypeAdapter.create should throw an error instead of returning null when the type does not match?

As far as I can see, ResourceOperationTypeAdapter.create should just return null when the type does not match, just as it does currently. That is, I'd suggest to replace

		if (!ResourceOperation.class.isAssignableFrom(type.getRawType())) {
			return null;
		}

with

		if (!CreateFile.class.isAssignableFrom(type.getRawType()) &&
			!DeleteFile.class.isAssignableFrom(type.getRawType()) &&
			!RenameFile.class.isAssignableFrom(type.getRawType())) {
			return null;
		}

@sebthom
Copy link
Contributor Author

sebthom commented Oct 28, 2025

This does not work type.getRawType() is always ResourceOperation.class and never one of the sub classes. I verified that via the debugger.

@pisv
Copy link
Contributor

pisv commented Oct 29, 2025

Thank you for verifying it. Looks like it was not a good idea, then.

What do you think about throwing IllegalArgumentException instead of JsonParseException from the write method?

@sebthom
Copy link
Contributor Author

sebthom commented Oct 29, 2025

Thank you for verifying it. Looks like it was not a good idea, then.

What do you think about throwing IllegalArgumentException instead of JsonParseException from the write method?

I have no strong opinion about this. I am also fine the way it is.

@pisv
Copy link
Contributor

pisv commented Oct 29, 2025

Just looking through the GSON source code, it seems that the JsonParseException is thrown strictly from parse or read methods, as also specified in its Javadoc. That's why I'm not quite happy about throwing it from the write method here. It is a minor thing, of course.

@sebthom
Copy link
Contributor Author

sebthom commented Oct 29, 2025

Just looking through the GSON source code, it seems that the JsonParseException is thrown strictly from parse or read methods, as also specified in its Javadoc. That's why I'm not quite happy about throwing it from the write method here. It is a minor thing, of course.

Does it have any practical relevance which one is thrown? Both are not recoverable or?

@pisv
Copy link
Contributor

pisv commented Oct 29, 2025

It does have a practical relevance by setting a precedent of throwing JsonParseException in write methods in the project's code base. By doing so, it sets an example that probably will be copied in the future.

Otherwise, we could just as well throw a RuntimeException (or any subclass of it) in this case.

@sebthom
Copy link
Contributor Author

sebthom commented Oct 29, 2025

Maybe this should be discussed separately and addressed in a separate PR? I can see other places where JsonParseException is thrown in a similar manner, like in EitherTypeAdapter.create or MessageTypeAdapter.createMessage. So if this is changed than probably better everywhere at once.

@pisv
Copy link
Contributor

pisv commented Oct 30, 2025

Thank you for discussing it in detail. The only reason for this discussion is that I could find no prior cases of throwing JsonParseException from write (serialization) methods neither in GSON itself nor in LSP4J. (The methods you mentioned where JsonParseException is thrown are only called from read methods.) That's why I'm concerned that this PR is setting a precedent in throwing JsonParseException from a write method.

@sebthom
Copy link
Contributor Author

sebthom commented Oct 30, 2025

I change it to whatever you feel comfortable. Shall I go for IllegalArgumentException?

@pisv
Copy link
Contributor

pisv commented Oct 30, 2025

I'd suggest throwing IllegalArgumentException instead of JsonParseException in this case. So, yes, please. Thank you!

@sebthom sebthom force-pushed the ResourceOperationTypeAdapter branch from 6e38fd4 to aa32c3e Compare October 30, 2025 12:48
@sebthom
Copy link
Contributor Author

sebthom commented Oct 30, 2025

@pisv done

- Replace reversed `isAssignableFrom` checks with `instanceof` to
correctly handle subclasses (e.g., `CreateFile` derivatives) in
write(...)
- Add explicit `JsonParseException` for unknown `ResourceOperation`
subtypes in write(...) to mirror read(...) and avoid silent malformed
JSON
- Improves protocol correctness and failure transparency when
encountering unsupported operations

Tests: add `ResourceOperationTypeAdapterTest` covering subclass serialization and unknown subtype failure
@sebthom sebthom force-pushed the ResourceOperationTypeAdapter branch from aa32c3e to 86a1073 Compare October 30, 2025 13:08
@pisv
Copy link
Contributor

pisv commented Oct 30, 2025

@sebthom I have made minor updates to ResourceOperationTypeAdapterTest, mostly removed references to 'current buggy implementation`, which is no longer buggy. Please have a look and if you are fine with my changes, I'll approve and merge this PR. Thanks!

@sebthom
Copy link
Contributor Author

sebthom commented Oct 30, 2025

Looks good. Thanks!

Copy link
Contributor

@pisv pisv left a comment

Choose a reason for hiding this comment

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

LGTM, thanks! 👍 And sorry for the extensive discussion of a small thing that mattered to me.

@pisv pisv merged commit ec0979b into eclipse-lsp4j:main Oct 30, 2025
4 checks passed
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