Skip to content

Commit

Permalink
HHH-16515 - Add @nullable annotations to org.hibernate.spi
Browse files Browse the repository at this point in the history
Signed-off-by: Jan Schatteman <jschatte@redhat.com>

Correction to gradle/java-module.gradle for the checkerframework
Co-authored-by: Christian Beikov <christian.beikov@gmail.com>

Add @nullable annotations to org.hibernate.spi
  • Loading branch information
jrenaat committed Apr 26, 2023
1 parent 3543186 commit d8b44d0
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 35 deletions.
2 changes: 1 addition & 1 deletion gradle/java-module.gradle
Expand Up @@ -524,7 +524,7 @@ checkerFramework {
extraJavacArgs = [
'-AsuppressWarnings=initialization',
"-Astubs=${project.rootDir}/checkerstubs",
'-AonlyDefs=^org\\.hibernate\\.jpamodelgen\\.'
'-AonlyDefs=^org\\.hibernate\\.(jpamodelgen|spi)\\.'
]
}

Expand Down
Expand Up @@ -20,6 +20,8 @@
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.loader.internal.AliasConstantsHelper;

import org.checkerframework.checker.nullness.qual.Nullable;

public final class StringHelper {

private static final int ALIAS_TRUNCATE_LENGTH = 10;
Expand Down Expand Up @@ -825,7 +827,7 @@ public static String[] unquote(final String[] names, final Dialect dialect) {
}
}

public static String nullIfEmpty(String value) {
public static String nullIfEmpty(@Nullable String value) {
return isEmpty( value ) ? null : value;
}

Expand Down
Expand Up @@ -9,7 +9,9 @@
import java.util.ArrayList;
import java.util.List;

import org.hibernate.metamodel.mapping.SelectablePath;
import org.hibernate.internal.util.NullnessUtil;

import org.checkerframework.checker.nullness.qual.Nullable;

/**
* A compound name.
Expand All @@ -26,7 +28,7 @@ public interface DotIdentifierSequence {
* Given the sequence {@code a.b.c}, returns the sequence
* {@code a.b}.
*/
DotIdentifierSequence getParent();
@Nullable DotIdentifierSequence getParent();

/**
* The name of this leaf sequence part.
Expand Down Expand Up @@ -64,8 +66,9 @@ default DotIdentifierSequence[] getParts() {
}

private void parts(List<DotIdentifierSequence> list) {
if ( getParent() != null ) {
getParent().parts( list );
DotIdentifierSequence parent = getParent();
if ( parent != null ) {
parent.parts( list );
}
list.add( this );
}
Expand Down
56 changes: 31 additions & 25 deletions hibernate-core/src/main/java/org/hibernate/spi/NavigablePath.java
Expand Up @@ -12,6 +12,10 @@
import org.hibernate.Incubating;
import org.hibernate.internal.util.StringHelper;

import org.checkerframework.checker.nullness.qual.Nullable;

import static org.hibernate.internal.util.NullnessUtil.castNonNull;

/**
* A compound name where the root path element is an entity name or a collection role
* and each the path sub-path from the root references a domain or mapping model part
Expand All @@ -23,9 +27,9 @@
public class NavigablePath implements DotIdentifierSequence, Serializable {
public static final String IDENTIFIER_MAPPER_PROPERTY = "_identifierMapper";

private final NavigablePath parent;
private final @Nullable NavigablePath parent;
private final String localName;
private final String alias;
private final @Nullable String alias;
private final String identifierForTableGroup;
private final FullPathCalculator fullPathCalculator;
private final int hashCode;
Expand All @@ -34,7 +38,7 @@ public NavigablePath(String localName) {
this( localName, null );
}

public NavigablePath(String rootName, String alias) {
public NavigablePath(String rootName, @Nullable String alias) {
this.parent = null;
this.alias = alias = StringHelper.nullIfEmpty( alias );
this.localName = rootName;
Expand All @@ -49,7 +53,7 @@ public NavigablePath(NavigablePath parent, String navigableName) {
this( parent, navigableName, null );
}

public NavigablePath(NavigablePath parent, String localName, String alias) {
public NavigablePath(NavigablePath parent, String localName, @Nullable String alias) {
assert parent != null;

this.parent = parent;
Expand Down Expand Up @@ -79,9 +83,9 @@ public NavigablePath(NavigablePath parent, String localName, String alias) {
}

public NavigablePath(
NavigablePath parent,
@Nullable NavigablePath parent,
String localName,
String alias,
@Nullable String alias,
String identifierForTableGroup,
FullPathCalculator fullPathCalculator,
int hashCode) {
Expand All @@ -94,7 +98,7 @@ public NavigablePath(
}

@Override
public NavigablePath getParent() {
public @Nullable NavigablePath getParent() {
return parent instanceof TreatedNavigablePath ? parent.getParent() : parent;
}

Expand All @@ -103,7 +107,7 @@ public String getLocalName() {
return localName;
}

public String getAlias() {
public @Nullable String getAlias() {
return alias;
}

Expand All @@ -121,7 +125,7 @@ public int hashCode() {
}

@Override
public boolean equals(Object other) {
public boolean equals(@Nullable Object other) {
if ( this == other ) {
return true;
}
Expand Down Expand Up @@ -175,14 +179,14 @@ public NavigablePath treatAs(String entityName, String alias) {
return new TreatedNavigablePath( this, entityName, alias );
}

public NavigablePath getRealParent() {
public @Nullable NavigablePath getRealParent() {
return parent;
}

/**
* Determine whether this path is part of the given path's parent
*/
public boolean isParent(NavigablePath navigablePath) {
public boolean isParent(@Nullable NavigablePath navigablePath) {
while ( navigablePath != null ) {
if ( this.equals( navigablePath.getParent() ) ) {
return true;
Expand All @@ -195,14 +199,15 @@ public boolean isParent(NavigablePath navigablePath) {
/**
* Determine whether the given path is a suffix of this path
*/
public boolean isSuffix(DotIdentifierSequence dotIdentifierSequence) {
public boolean isSuffix(@Nullable DotIdentifierSequence dotIdentifierSequence) {
if ( dotIdentifierSequence == null ) {
return true;
}
if ( !localNamesMatch( dotIdentifierSequence ) ) {
return false;
}
return getParent() != null && getParent().isSuffix( dotIdentifierSequence.getParent() );
NavigablePath parent = getParent();
return parent != null && parent.isSuffix( dotIdentifierSequence.getParent() );
}

/**
Expand All @@ -216,23 +221,24 @@ public boolean isSuffix(DotIdentifierSequence dotIdentifierSequence) {
* or null if the NavigablePath does not contain the suffix.
*
*/
public NavigablePath trimSuffix(DotIdentifierSequence suffix) {
public @Nullable NavigablePath trimSuffix(@Nullable DotIdentifierSequence suffix) {
if ( suffix == null ) {
return this;
}
if ( !getLocalName().equals( suffix.getLocalName() ) ) {
return null;
}
if ( getParent() != null ) {
return getParent().trimSuffix( suffix.getParent() );
NavigablePath parent = getParent();
if ( parent != null ) {
return parent.trimSuffix( suffix.getParent() );
}
return null;
}

/**
* Determine whether this path is part of the given path's parent
*/
public boolean isParentOrEqual(NavigablePath navigablePath) {
public boolean isParentOrEqual(@Nullable NavigablePath navigablePath) {
while ( navigablePath != null ) {
if ( this.equals( navigablePath ) ) {
return true;
Expand All @@ -242,15 +248,15 @@ public boolean isParentOrEqual(NavigablePath navigablePath) {
return false;
}

public boolean pathsMatch(NavigablePath p) {
public boolean pathsMatch(@Nullable NavigablePath p) {
return this == p || p != null && localName.equals( p.localName )
&& ( parent == null ? p.parent == null && Objects.equals( alias, p.alias ) : parent.pathsMatch( p.parent ) );
}

/**
* Ignores aliases in the resulting String
*/
public String relativize(NavigablePath base) {
public @Nullable String relativize(NavigablePath base) {
// e.g.
// - base = Root.sub
// - this = Root.sub.stuff
Expand Down Expand Up @@ -284,7 +290,7 @@ public void collectPath(String path) {
buffer.append( path );
}

public String resolve() {
public @Nullable String resolve() {
if ( buffer == null ) {
// Return an empty string instead of null in case the two navigable paths are equal
return matchedBase ? "" : null;
Expand Down Expand Up @@ -323,24 +329,24 @@ public String toString() {
*/
@FunctionalInterface
protected interface FullPathCalculator extends Serializable {
String calculateFullPath(NavigablePath parent, String localName, String alias);
String calculateFullPath(@Nullable NavigablePath parent, String localName, @Nullable String alias);
}

/**
* The pattern used for root NavigablePaths
*/
protected static String calculateRootFullPath(NavigablePath parent, String rootName, String alias) {
protected static String calculateRootFullPath(@Nullable NavigablePath parent, String rootName, @Nullable String alias) {
assert parent == null;
return alias == null ? rootName : rootName + "(" + alias + ")";
}

/**
* The normal pattern used for the "full path"
*/
private static String calculateNormalFullPath(NavigablePath parent, String localName, String alias) {
private static String calculateNormalFullPath(@Nullable NavigablePath parent, String localName, @Nullable String alias) {
assert parent != null;

final String parentFullPath = parent.getFullPath();
final String parentFullPath = castNonNull( parent ).getFullPath();
final String baseFullPath = StringHelper.isEmpty( parentFullPath )
? localName
: parentFullPath + "." + localName;
Expand All @@ -350,7 +356,7 @@ private static String calculateNormalFullPath(NavigablePath parent, String local
/**
* Pattern used for `_identifierMapper`
*/
protected static String calculateIdMapperFullPath(NavigablePath parent, String localName, String alias) {
protected static String calculateIdMapperFullPath(@Nullable NavigablePath parent, String localName, @Nullable String alias) {
return parent != null ? parent.getFullPath() : "";
}
}
Expand Up @@ -8,6 +8,10 @@

import org.hibernate.Incubating;

import org.checkerframework.checker.nullness.qual.Nullable;

import static org.hibernate.internal.util.NullnessUtil.castNonNull;

/**
* An implementation of {@link NavigablePath} with special handling for treated paths.
*
Expand All @@ -20,7 +24,7 @@ public TreatedNavigablePath(NavigablePath parent, String entityTypeName) {
this( parent, entityTypeName, null );
}

public TreatedNavigablePath(NavigablePath parent, String entityTypeName, String alias) {
public TreatedNavigablePath(NavigablePath parent, String entityTypeName, @Nullable String alias) {
super(
parent,
"#" + entityTypeName,
Expand All @@ -32,20 +36,20 @@ public TreatedNavigablePath(NavigablePath parent, String entityTypeName, String
assert !( parent instanceof TreatedNavigablePath );
}

protected static String calculateTreatedFullPath(NavigablePath parent, String localName, String alias) {
protected static String calculateTreatedFullPath(@Nullable NavigablePath parent, String localName, @Nullable String alias) {
return alias == null
? "treat(" + parent + " as " + localName + ")"
: "treat(" + parent + " as " + localName + ")(" + alias + ")";
}

@Override
public NavigablePath treatAs(String entityName) {
return new TreatedNavigablePath( getRealParent(), entityName );
return new TreatedNavigablePath( castNonNull( getRealParent() ), entityName );
}

@Override
public NavigablePath treatAs(String entityName, String alias) {
return new TreatedNavigablePath( getRealParent(), entityName, alias );
return new TreatedNavigablePath( castNonNull( getRealParent() ), entityName, alias );
}

// @Override
Expand Down

0 comments on commit d8b44d0

Please sign in to comment.