Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.checkerframework.framework.util.AnnotatedTypes;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
import org.checkerframework.javacutil.UserError;
Expand Down Expand Up @@ -115,7 +116,7 @@ public void handleBuilderBuildMethod(AnnotatedExecutableType builderBuildType) {

@Override
public boolean isToBuilderMethod(ExecutableElement candidateToBuilderElement) {
if (!"toBuilder".equals(candidateToBuilderElement.getSimpleName().toString())) {
if (!InternalUtils.sameName(candidateToBuilderElement.getSimpleName(), "toBuilder")) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;

import java.beans.Introspector;
import java.util.ArrayList;
Expand Down Expand Up @@ -132,7 +133,7 @@ public void handleBuilderBuildMethod(AnnotatedExecutableType builderBuildType) {

@Override
public boolean isToBuilderMethod(ExecutableElement candidateToBuilderElement) {
return candidateToBuilderElement.getSimpleName().contentEquals("toBuilder")
return InternalUtils.sameName(candidateToBuilderElement.getSimpleName(), "toBuilder")
&& (ElementUtils.hasAnnotation(candidateToBuilderElement, "lombok.Generated")
|| ElementUtils.hasAnnotation(
candidateToBuilderElement.getEnclosingElement(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.checkerframework.framework.type.treeannotator.TreeAnnotator;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreeUtils;

import javax.lang.model.element.Element;
Expand Down Expand Up @@ -76,8 +77,8 @@ private void computeFieldAccessType(ExpressionTree tree, AnnotatedTypeMirror typ
// (e.g., constructor calls or uses of an outer this).
if (tree instanceof IdentifierTree) {
IdentifierTree identTree = (IdentifierTree) tree;
if (identTree.getName().contentEquals("this")
|| identTree.getName().contentEquals("super")) {
if (InternalUtils.isThisName(identTree.getName())
|| InternalUtils.isSuperName(identTree.getName())) {
return;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
Expand Down Expand Up @@ -414,7 +415,7 @@ protected boolean isUnused(
Name when = AnnotationUtils.getElementValueClassName(unused, unusedWhenElement);
for (AnnotationMirror anno : receiverAnnos) {
Name annoName = ((TypeElement) anno.getAnnotationType().asElement()).getQualifiedName();
if (annoName.contentEquals(when)) {
if (InternalUtils.sameName(annoName, when)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.checkerframework.dataflow.expression.JavaExpression;
import org.checkerframework.framework.flow.CFAbstractTransfer;
import org.checkerframework.framework.flow.CFValue;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;

Expand Down Expand Up @@ -75,7 +76,7 @@ protected List<VariableElement> initializedFieldsAfterCall(MethodInvocationNode
List<VariableElement> result = new ArrayList<>();
MethodInvocationTree tree = node.getTree();
ExecutableElement method = TreeUtils.elementFromUse(tree);
boolean isConstructor = method.getSimpleName().contentEquals("<init>");
boolean isConstructor = InternalUtils.isInitName(method.getSimpleName());
Node receiver = node.getTarget().getReceiver();

if (isConstructor && receiver instanceof ThisNode) {
Expand All @@ -84,14 +85,14 @@ protected List<VariableElement> initializedFieldsAfterCall(MethodInvocationNode
(methodSelect instanceof IdentifierTree)
? ((IdentifierTree) methodSelect).getName()
: ((MemberSelectTree) methodSelect).getIdentifier();
if (methodName.contentEquals("this")) {
if (InternalUtils.isThisName(methodName)) {
// Case 1: After a call to the constructor of the same class, all
// fields are guaranteed to be initialized.
ClassTree clazz =
TreePathUtil.enclosingClass(analysis.getTypeFactory().getPath(tree));
TypeElement clazzElem = TreeUtils.elementFromDeclaration(clazz);
markFieldsAsInitialized(result, clazzElem);
} else if (methodName.contentEquals("super")) {
} else if (InternalUtils.isSuperName(methodName)) {
// Case 4: After a call to the constructor of the super class, all
// fields of any super class are guaranteed to be initialized.
ClassTree clazz =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationMirrorSet;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;

Expand Down Expand Up @@ -335,8 +336,8 @@ private boolean isReferenceEqualityImplementation(MethodTree equalsMethod) {
Name leftName = ((IdentifierTree) lhsTree).getName();
Name rightName = ((IdentifierTree) rhsTree).getName();
Name paramName = equalsMethod.getParameters().get(0).getName();
if ((leftName.contentEquals("this") && rightName == paramName)
|| (leftName == paramName && rightName.contentEquals("this"))) {
if ((InternalUtils.isThisName(leftName) && rightName == paramName)
|| (leftName == paramName && InternalUtils.isThisName(rightName))) {
return true;
}
}
Expand Down Expand Up @@ -928,7 +929,7 @@ private boolean classIsAnnotated(AnnotatedTypeMirror type) {
*/
private @Nullable Element getThis(Scope scope) {
for (Element e : scope.getLocalElements()) {
if (e.getSimpleName().contentEquals("this")) {
if (InternalUtils.isThisName(e.getSimpleName())) {
return e;
}
}
Expand All @@ -952,7 +953,8 @@ private boolean overrides(ExecutableElement e, Class<?> clazz, String method) {

// Check all of the methods in the class for name matches and overriding.
for (ExecutableElement elt : ElementFilter.methodsIn(clazzElt.getEnclosedElements())) {
if (elt.getSimpleName().contentEquals(method) && elements.overrides(e, elt, clazzElt)) {
if (InternalUtils.sameName(elt.getSimpleName(), method)
&& elements.overrides(e, elt, clazzElt)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypeSystemError;
import org.plumelib.util.CollectionsPlume;
Expand Down Expand Up @@ -753,7 +754,7 @@ private void translateJcipAndJavaxAnnotations(Element element, AnnotatedTypeMirr
Object value = null;
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
valmap.entrySet()) {
if (entry.getKey().getSimpleName().contentEquals("value")) {
if (InternalUtils.isValueName(entry.getKey().getSimpleName())) {
value = entry.getValue().getValue();
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.checkerframework.javacutil.AnnotationMirrorSet;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TreeUtilsAfterJava11;
Expand Down Expand Up @@ -238,7 +239,7 @@ protected boolean commonAssignmentCheck(
// Note that this method should return non-null only for fields of this class, not
// fields of any other class, including outer classes.
if (!(receiver instanceof IdentifierTree)
|| !((IdentifierTree) receiver).getName().contentEquals("this")) {
|| !InternalUtils.isThisName(((IdentifierTree) receiver).getName())) {
return null;
}
// fallthrough
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,9 @@ private boolean areSame(JavaExpression target, @Nullable JavaExpression enclosin
return false;
}
if (enclosingTarget instanceof ThisReference && target instanceof ThisReference) {
return enclosingTarget.getType().toString().equals(target.getType().toString());
return checker.getProcessingEnvironment()
.getTypeUtils()
.isSameType(enclosingTarget.getType(), target.getType());
} else {
return enclosingTarget.equals(target);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import org.checkerframework.checker.signature.qual.CanonicalName;
import org.checkerframework.dataflow.qual.Pure;
import org.checkerframework.javacutil.ElementUtils;

import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Types;
Expand Down Expand Up @@ -69,7 +70,7 @@ static SetOfTypes allSubtypes(TypeMirror t) {
@Pure
static SetOfTypes anyOfTheseNames(ImmutableSet<@CanonicalName String> names) {
return (typeUtils, u) ->
u instanceof Type && names.contains(((Type) u).tsym.getQualifiedName().toString());
u instanceof Type && names.contains(ElementUtils.getQualifiedName(((Type) u).tsym));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.checkerframework.javacutil.AnnotationBuilder;
import org.checkerframework.javacutil.AnnotationMirrorSet;
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.InternalUtils;

import java.lang.annotation.Annotation;
import java.util.Map;
Expand Down Expand Up @@ -155,7 +156,7 @@ private static boolean hasNoPrefix(AnnotationValue annotationValue) {

for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
elementValues.entrySet()) {
if (entry.getKey().getSimpleName().contentEquals("value")) {
if (InternalUtils.isValueName(entry.getKey().getSimpleName())) {
return entry.getValue();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
import org.checkerframework.javacutil.AnnotationUtils;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.SystemUtil;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
Expand Down Expand Up @@ -3438,7 +3439,7 @@ public Node visitIdentifier(IdentifierTree tree, Void p) {
switch (element.getKind()) {
case FIELD:
// Note that "this"/"super" is a field, but not a field access.
if (element.getSimpleName().contentEquals("this")) {
if (InternalUtils.isThisName(element.getSimpleName())) {
node = new ExplicitThisNode(tree);
} else {
node = new SuperNode(tree);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.sun.source.tree.IdentifierTree;

import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreeUtils;

/**
Expand All @@ -13,11 +14,17 @@
*/
public class ExplicitThisNode extends ThisNode {

/** The identifier tree for "this". */
protected final IdentifierTree tree;

/**
* Creates a node for the given "this" identifier.
*
* @param t the identifier tree for "this"
*/
public ExplicitThisNode(IdentifierTree t) {
super(TreeUtils.typeOf(t));
assert t.getName().contentEquals("this");
assert InternalUtils.isThisName(t.getName());
tree = t;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.dataflow.qual.SideEffectFree;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreeUtils;

import java.util.Collection;
Expand All @@ -21,11 +22,17 @@
*/
public class SuperNode extends Node {

/** The identifier tree for "super". */
protected final IdentifierTree tree;

/**
* Creates a node for the given "super" identifier.
*
* @param t the identifier tree for "super"
*/
public SuperNode(IdentifierTree t) {
super(TreeUtils.typeOf(t));
assert t.getName().contentEquals("super");
assert InternalUtils.isSuperName(t.getName());
tree = t;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.checkerframework.javacutil.AnnotationProvider;
import org.checkerframework.javacutil.BugInCF;
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.InternalUtils;
import org.checkerframework.javacutil.TreePathUtil;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypesUtils;
Expand Down Expand Up @@ -550,10 +551,10 @@ public static JavaExpression fromTree(ExpressionTree tree) {
IdentifierTree identifierTree = (IdentifierTree) tree;
TypeMirror typeOfId = TreeUtils.typeOf(identifierTree);
Name identifierName = identifierTree.getName();
if (identifierName.contentEquals("this")) {
if (InternalUtils.isThisName(identifierName)) {
result = new ThisReference(typeOfId);
break;
} else if (identifierName.contentEquals("super")) {
} else if (InternalUtils.isSuperName(identifierName)) {
result = new SuperReference(typeOfId);
break;
}
Expand Down
16 changes: 16 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,22 @@ list's iterator; the read-only iterator now walks the backing list by index. Thi
single largest remaining source of `Iterator` allocation in type checking. No user-visible
behavior change.

Performance: `InternalUtils` has new helpers (`isInitName`, `isThisName`, `isSuperName`,
`isValueName`, `isJavaLangObjectName`, `isJavaLangEnumName`) that compare a javac `Name`
against the table's pre-interned name by identity instead of `Name.contentEquals`, which
decodes the name's UTF-8 bytes into a fresh `String` on every call on byte-backed name
tables (javac's default before JDK 23, and what Gradle's `-XDuseUnsharedTable` forces on
all JDK versions). All call sites that compared a `Name` against these fixed literals
(`TreeUtils.isConstructor`, `TreeUtils.isEnumSuperCall`, identifier `this`/`super` checks
in dataflow and the checkers, annotation-element `value` checks) now use them. For
comparisons against dynamic-but-bounded strings (annotation element names, method names a
checker matches against), the new `InternalUtils.sameName(Name, CharSequence)` interns the
target into the name's own table through a table-validated cache and compares by identity
(~6x faster, allocation-free, on byte-backed tables); `sameName(Name, Name)` compares
same-table names by identity. `AnnotationUtils.getElementValue` and
`AnnotationBuilder.findElement` — the hottest `Name` comparisons in the Called Methods,
Must Call, and Resource Leak checkers — now use it. No user-visible behavior change.

Performance: the `AnnotatedTypeFactory` tree-type caches (`classAndMethodTreeCache`,
`fromExpressionTreeCache`, `fromMemberTreeCache`, `fromTypeTreeCache`, and `elementToTreeCache`) are
now unbounded `IdentityHashMap`s cleared per compilation unit, rather than LRU caches capped at 2048
Expand Down
Loading
Loading