diff --git a/src/main/java/org/codehaus/plexus/build/BuildContext.java b/src/main/java/org/codehaus/plexus/build/BuildContext.java index f132223..ffefd24 100644 --- a/src/main/java/org/codehaus/plexus/build/BuildContext.java +++ b/src/main/java/org/codehaus/plexus/build/BuildContext.java @@ -167,10 +167,16 @@ public interface BuildContext { * * @see #setValue(String, Object) * @see #isIncremental() + *

+ * The return type is inferred from the assignment target and is not checked here: a value of another type + * than the one the caller expects fails with a {@link ClassCastException} at the call site. + *

+ * + * @param the expected type of the value * @param key a {@link java.lang.String} object. - * @return a {@link java.lang.Object} object. + * @return the value, or {@code null} if there is none */ - Object getValue(String key); + T getValue(String key); /** *

addWarning.

diff --git a/src/main/java/org/codehaus/plexus/build/DefaultBuildContext.java b/src/main/java/org/codehaus/plexus/build/DefaultBuildContext.java index 5cde79a..5257358 100644 --- a/src/main/java/org/codehaus/plexus/build/DefaultBuildContext.java +++ b/src/main/java/org/codehaus/plexus/build/DefaultBuildContext.java @@ -152,11 +152,12 @@ public boolean isIncremental() { } /** {@inheritDoc} */ - public Object getValue(String key) { + @SuppressWarnings("unchecked") + public T getValue(String key) { if (isDefaultImplementation()) { - return contextMap.get(key); + return (T) contextMap.get(key); } - return legacy.getValue(key); + return (T) legacy.getValue(key); } /** {@inheritDoc} */ diff --git a/src/test/java/org/codehaus/plexus/build/BuildContextGetValueTypingTest.java b/src/test/java/org/codehaus/plexus/build/BuildContextGetValueTypingTest.java new file mode 100644 index 0000000..305df03 --- /dev/null +++ b/src/test/java/org/codehaus/plexus/build/BuildContextGetValueTypingTest.java @@ -0,0 +1,29 @@ +package org.codehaus.plexus.build; + +/** + * Compile-time check that {@link BuildContext#getValue(String)} infers its result type from the assignment target, and + * that an implementation declaring the pre-generic {@code Object getValue(String)} still compiles. The module skips + * test execution, so this fails the build by not compiling. + */ +final class BuildContextGetValueTypingTest { + + private BuildContextGetValueTypingTest() {} + + static String inferredFromAssignment(BuildContext context) { + String value = context.getValue("key"); + return value; + } + + static Object plainObjectStillWorks(BuildContext context) { + Object value = context.getValue("key"); + return value; + } + + @SuppressWarnings({"unchecked", "rawtypes"}) + abstract static class PreGenericImplementation implements BuildContext { + @Override + public Object getValue(String key) { + return null; + } + } +}