NullabilityDetector.java
package org.mozilla.javascript;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public interface NullabilityDetector {
NullabilityAccessor getParameterNullability(Method method);
NullabilityAccessor getParameterNullability(Constructor<?> constructor);
interface NullabilityAccessor {
NullabilityAccessor TRUE = (ignored) -> true;
NullabilityAccessor FALSE = (ignored) -> false;
NullabilityAccessor INDEX_OUT_OF_BOUNDS =
(i) -> {
throw new IndexOutOfBoundsException(
String.format("Index %s out of bounds [0,0)", i));
};
/**
* Note: The return value when providing out-of-bound index is "not defined". There's no
* guarantee that it will provide a result that makes sense, or throw an {@link
* IndexOutOfBoundsException} when providing out-of-bound index
*
* @param index parameter index
* @return {@code true} if the parameter at specified index is nullable, {@code false}
* otherwise
* @throws IndexOutOfBoundsException if index is out of bounds of the method/constructor
* parameters
*/
boolean isNullable(int index);
static NullabilityAccessor compress(boolean[] values) {
var length = values.length;
// empty
if (length == 0) {
return INDEX_OUT_OF_BOUNDS;
}
// single element
if (length == 1) {
return values[0] ? TRUE : FALSE;
}
// same elements
Boolean allMatch = values[0];
for (var value : values) {
if (allMatch != value) {
allMatch = null;
break;
}
}
if (allMatch != null) {
return allMatch ? TRUE : FALSE;
}
// use smaller object (int) as backend
if (length < 32) { // length: [2, 31]
var compressed = 0;
for (int i = 0; i < length; i++) {
if (values[i]) {
compressed |= (1 << i);
}
}
final var compressedFinal = compressed;
return i -> ((compressedFinal >> i) & 1) != 0;
}
// fallback
return i -> values[i];
}
}
}