Skip to content

Commit d90b304

Browse files
authored
fix(java): improve property override detection (#692)
The previous code only checked whether a methodd name was a get/setter by checking if it's name started by `get` or `set` and was at least 4 characters long. This is insufficient, as a method called `settings` would be misidentified. Changed to expect getters to have zero parameters, and setters to have exactly one parameter and to match a corresponding getter.
1 parent e8b5a35 commit d90b304

File tree

9 files changed

+46
-376
lines changed

9 files changed

+46
-376
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ script:
1414
- docker build --pull --build-arg BUILD_TIMESTAMP=$(date -u +'%Y-%m-%dT%H:%M:%SZ') --build-arg COMMIT_ID="${TRAVIS_COMMIT}" -t "jsii/superchain:nightly" ./superchain
1515
# Building jsii itself within the Docker image
1616
- docker run --rm -it --net=host -v ${PWD}:${PWD} -w ${PWD} jsii/superchain:nightly ./build.sh
17-
# Make sure the build did not change the source tree (git diff-index will return non-zero if that's the case)
18-
- git diff-index --exit-code --ignore-space-at-eol --stat HEAD
17+
# Make sure the build did not change the source tree
18+
- git update-index --refresh
19+
- git diff-index --exit-code --stat HEAD
1920
- untracked=$(git ls-files --others --exclude-standard) && echo "${untracked}" && test -z "${untracked}"
2021
# Publish the image to DockerHub when relevant
2122
- echo "TRAVIS_PULL_REQUEST = ${TRAVIS_PULL_REQUEST:-}"

packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/JsiiEngine.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,8 @@ private static Collection<JsiiOverride> discoverOverrides(final Class<?> classTo
491491
String methodName = method.getName();
492492

493493
// check if this is a property ("getXXX" or "setXXX", oh java!)
494-
if (isJavaPropertyMethod(methodName)) {
495-
String propertyName = javaPropertyToJSProperty(methodName);
494+
if (isJavaPropertyMethod(method)) {
495+
String propertyName = javaPropertyToJSProperty(method);
496496

497497
// skip if this property is already in the overrides list
498498
if (overrides.containsKey(propertyName)) {

packages/jsii-java-runtime/project/src/main/java/software/amazon/jsii/Util.java

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.IOException;
44
import java.io.InputStream;
5+
import java.lang.reflect.Method;
56
import java.nio.file.Files;
67
import java.nio.file.Path;
78
import java.nio.file.Paths;
@@ -42,21 +43,51 @@ static String readString(final InputStream is) {
4243

4344
/**
4445
* Checks if the method name looks like a java property getter (getXxx).
45-
* @param methodName The name of the method.
46-
* @return True if the name looks like getXxx.
46+
* @param method The reflected method that may be a get/setter
47+
* @return true if the method is a get/setter.
4748
*/
48-
static boolean isJavaPropertyMethod(final String methodName) {
49-
return (methodName.length() > PROPERTY_METHOD_PREFIX_LEN
50-
&& (methodName.startsWith("get") || methodName.startsWith(("set"))));
49+
static boolean isJavaPropertyMethod(final Method method) {
50+
final String methodName = method.getName();
51+
if (methodName.length() <= PROPERTY_METHOD_PREFIX_LEN) {
52+
// Needs to have at least one character after the "get" or "set" prefix
53+
return false;
54+
}
55+
if (methodName.startsWith("get") && method.getParameterCount() == 0) {
56+
// Require something else than a lowercase letter after the "get" prefix
57+
return !Character.isLowerCase(methodName.charAt(3));
58+
}
59+
if (methodName.startsWith("set") && method.getParameterCount() == 1) {
60+
// Require something else than a lowercase letter after the "get" prefix
61+
return !Character.isLowerCase(methodName.charAt(3))
62+
// Require a matching getter
63+
&& isMatchingGetterPresent(method.getName().replaceFirst("set", "get"),
64+
method.getParameterTypes()[0],
65+
method.getDeclaringClass());
66+
}
67+
return false;
68+
}
69+
70+
private static boolean isMatchingGetterPresent(final String getterName, final Class<?> returnType, final Class<?> declaring) {
71+
try {
72+
final Method getter = declaring.getDeclaredMethod(getterName);
73+
return getter.getReturnType().equals(returnType);
74+
} catch (final NoSuchMethodException nsme) {
75+
return declaring.equals(Object.class)
76+
? false
77+
: isMatchingGetterPresent(getterName,
78+
returnType,
79+
declaring.getSuperclass());
80+
}
5181
}
5282

5383
/**
5484
* Convert a java property method name (getXxx/setXxx) to a javascript property name (xxx).
55-
* @param getterSetterMethod The java method name
85+
* @param method The reflected method (assumed to be a get/setter according to #isJavaPropertyMethod)
5686
* @return The javascript property name
5787
*/
58-
static String javaPropertyToJSProperty(final String getterSetterMethod) {
59-
if (!isJavaPropertyMethod(getterSetterMethod)) {
88+
static String javaPropertyToJSProperty(final Method method) {
89+
final String getterSetterMethod = method.getName();
90+
if (!isJavaPropertyMethod(method)) {
6091
throw new JsiiException("Invalid getter/setter method. Must start with get/set");
6192
}
6293

packages/jsii-pacmak/package-lock.json

Lines changed: 0 additions & 100 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/jsii-reflect/package-lock.json

Lines changed: 0 additions & 94 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/jsii-ruby-runtime/project/Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
jsii_runtime (0.14.2)
4+
jsii_runtime (0.14.3)
55

66
GEM
77
remote: https://rubygems.org/
@@ -34,4 +34,4 @@ DEPENDENCIES
3434
test-unit (~> 3.3.3)
3535

3636
BUNDLED WITH
37-
1.17.2
37+
1.17.3

0 commit comments

Comments
 (0)