Skip to content

Commit

Permalink
Add support for OptionalDouble, OptionalInt, OptionalLong
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Ernst <mernst@cs.washington.edu>
  • Loading branch information
smillst and mernst committed Dec 13, 2023
1 parent 17226ff commit ae8a6e1
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.util.TreePath;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
Expand Down Expand Up @@ -401,6 +404,10 @@ public void handleCreationElimination(MethodInvocationTree tree) {
}
ExpressionTree receiver = TreeUtils.getReceiverTree(tree);
while (true) {
if (receiver == null) {
// The receiver can be null if the receiver is the implicit "this.".
return;
}
if (receiver.getKind() != Tree.Kind.METHOD_INVOCATION) {
return;
}
Expand Down Expand Up @@ -546,14 +553,33 @@ public Void visitDeclared(AnnotatedDeclaredType type, Tree tree) {
}
}

/** Return true if tm represents a subtype of Collection (other than the Null type). */
/**
* Return true if tm is a subtype of Collection (other than the Null type).
*
* @param tm a type
* @return true if the given type is a subtype of Collection
*/
private boolean isCollectionType(TypeMirror tm) {
return tm.getKind() == TypeKind.DECLARED && types.isSubtype(tm, collectionType);
}

/** Return true if tm represents java.util.Optional. */
/** The fully-qualified names of the 4 optional classes in java.util. */
private static final Set<String> fqOptionalTypes =
new HashSet<>(
Arrays.asList(
"java.util.Optional",
"java.util.OptionalDouble",
"java.util.OptionalInt",
"java.util.OptionalLong"));

/**
* Return true if tm is class Optional, OptionalDouble, OptionalInt, or OptionalLong in java.util.
*
* @param tm a type
* @return true if the given type is Optional, OptionalDouble, OptionalInt, or OptionalLong
*/
private boolean isOptionalType(TypeMirror tm) {
return TypesUtils.isDeclaredOfName(tm, "java.util.Optional");
return TypesUtils.isDeclaredOfName(tm, fqOptionalTypes);
}

/**
Expand Down
10 changes: 10 additions & 0 deletions checker/tests/optional/Marks4.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ String process_bad(String s) {
return Optional.ofNullable(s).orElseGet(this::getDefault);
}

String process_bad2(String s) {
// :: warning: (introduce.eliminate)
return Optional.<String>empty().orElseGet(this::getDefault);
}

String process_bad3(String s) {
// :: warning: (introduce.eliminate)
return Optional.of(s).orElseGet(this::getDefault);
}

String process_good(String s) {
return (s != null) ? s : getDefault();
}
Expand Down
24 changes: 24 additions & 0 deletions checker/tests/optional/OptionalBoxed.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.OptionalInt;
import java.util.OptionalLong;

class OptionalBoxed {

// :: warning: (optional.field)
OptionalDouble aField;

// :: warning: (optional.parameter)
void m(OptionalInt aParam) {
// :: warning: (introduce.eliminate)
int x = OptionalLong.of(1L).hashCode();
// :: warning: (introduce.eliminate)
long y = OptionalLong.of(1L).orElse(2L);
// :: warning: (introduce.eliminate)
boolean b = Optional.empty().isPresent();
// :: warning: (introduce.eliminate)
OptionalDouble.empty().ifPresent(d -> {});
// :: warning: (introduce.eliminate)
boolean b4 = OptionalLong.empty().isPresent();
}
}

0 comments on commit ae8a6e1

Please sign in to comment.