selenium icon indicating copy to clipboard operation
selenium copied to clipboard

[java] JSpecify annotations for immutable models and enums

Open mk868 opened this issue 1 year ago • 2 comments

User description

Description

In this PR I'm adding nullness annotations for classes

  • Dimension
  • Keys
  • Point
  • Rectangle
  • UsernameAndPassword

Dimension

  • equals accepts null argument -> marked with @Nullable

Keys

  • getKeyFromUnicode can return null value -> return type marked with @Nullable

Point

  • equals accepts null argument -> marked with @Nullable

Rectangle

  • equals accepts null argument -> marked with @Nullable

UsernameAndPassword

No null values

Motivation and Context

The JSpecify nullness annotations will give developers better exposure to potential problems with their code to avoid NullPointerExceptions. Related issue: https://github.com/SeleniumHQ/selenium/issues/14291

Types of changes

  • [ ] Bug fix (non-breaking change which fixes an issue)
  • [x] New feature (non-breaking change which adds functionality)
  • [ ] Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • [x] I have read the contributing document.
  • [ ] My change requires a change to the documentation.
  • [ ] I have updated the documentation accordingly.
  • [ ] I have added tests to cover my changes.
  • [ ] All new and existing tests passed.

PR Type

enhancement


Description

  • Added @NullMarked annotations to several classes and enums to improve nullness handling.
  • Updated equals methods in Dimension, Point, and Rectangle classes to accept @Nullable parameters.
  • Modified getKeyFromUnicode method in Keys enum to return @Nullable.
  • These changes aim to enhance code safety by preventing potential NullPointerExceptions.

Changes walkthrough 📝

Relevant files
Enhancement
Dimension.java
Add nullness annotations to Dimension class                           

java/src/org/openqa/selenium/Dimension.java

  • Added @NullMarked annotation to the Dimension class.
  • Updated equals method to accept @Nullable parameter.
  • +4/-1     
    Keys.java
    Add nullness annotations to Keys enum                                       

    java/src/org/openqa/selenium/Keys.java

  • Added @NullMarked annotation to the Keys enum.
  • Updated getKeyFromUnicode method to return @Nullable.
  • +4/-1     
    Point.java
    Add nullness annotations to Point class                                   

    java/src/org/openqa/selenium/Point.java

  • Added @NullMarked annotation to the Point class.
  • Updated equals method to accept @Nullable parameter.
  • +4/-1     
    Rectangle.java
    Add nullness annotations to Rectangle class                           

    java/src/org/openqa/selenium/Rectangle.java

  • Added @NullMarked annotation to the Rectangle class.
  • Updated equals method to accept @Nullable parameter.
  • +4/-1     
    UsernameAndPassword.java
    Add nullness annotations to UsernameAndPassword class       

    java/src/org/openqa/selenium/UsernameAndPassword.java

    • Added @NullMarked annotation to the UsernameAndPassword class.
    +2/-0     

    💡 PR-Agent usage: Comment /help on the PR to get a list of all available PR-Agent tools and their descriptions

    mk868 avatar Aug 14 '24 20:08 mk868

    PR Reviewer Guide 🔍

    ⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Key issues to review

    Possible Inconsistency
    The getKeyFromUnicode method is marked as returning @Nullable Keys, but the method implementation doesn't explicitly return null. It might be worth adding an explicit null return at the end of the method to match the annotation.

    qodo-code-review[bot] avatar Aug 14 '24 20:08 qodo-code-review[bot]

    PR Code Suggestions ✨

    CategorySuggestion                                                                                                                                    Score
    Performance
    Improve performance of key lookup by using a Map instead of iterating through all values

    Consider using a more efficient data structure, such as a Map, to store and lookup
    Keys by their Unicode values.

    java/src/org/openqa/selenium/Keys.java [186-190]

    +private static final Map<Character, Keys> unicodeToKeyMap = new HashMap<>();
    +
    +static {
    +  for (Keys key : values()) {
    +    unicodeToKeyMap.put(key.charAt(0), key);
    +  }
    +}
    +
     public static @Nullable Keys getKeyFromUnicode(char key) {
    -  for (Keys unicodeKey : values()) {
    -    if (unicodeKey.charAt(0) == key) {
    -      return unicodeKey;
    -    }
    +  return unicodeToKeyMap.get(key);
     
    
    • [ ] Apply this suggestion <!-- /improve --apply_suggestion=0 -->
    Suggestion importance[1-10]: 9

    Why: The suggestion improves performance by replacing iteration with a Map for constant-time lookups, which is a significant enhancement for efficiency.

    9
    Enhancement
    Simplify the equals method using instanceof pattern matching

    Consider using instanceof pattern matching to simplify the equals method and avoid
    explicit casting.

    java/src/org/openqa/selenium/Dimension.java [44-47]

     @Override
     public boolean equals(@Nullable Object o) {
    -  if (!(o instanceof Dimension)) {
    -    return false;
    +  if (o instanceof Dimension other) {
    +    return width == other.width && height == other.height;
       }
    +  return false;
     
    
    • [ ] Apply this suggestion <!-- /improve --apply_suggestion=1 -->
    Suggestion importance[1-10]: 8

    Why: The suggestion correctly simplifies the equals method by using instanceof pattern matching, which improves code readability and eliminates the need for explicit casting.

    8
    Convert the class to a record for a more concise and immutable representation

    Consider using a record instead of a class for Rectangle, as it's an immutable data
    class with public final fields.

    java/src/org/openqa/selenium/Rectangle.java [25-30]

     @NullMarked
    -public class Rectangle {
    +public record Rectangle(int x, int y, int width, int height) {
     
    -  public final int x;
    -  public final int y;
    -
    
    • [ ] Apply this suggestion <!-- /improve --apply_suggestion=2 -->
    Suggestion importance[1-10]: 8

    Why: Converting the class to a record provides a more concise and immutable representation, aligning with modern Java practices for data classes.

    8
    Best practice
    Make fields final to ensure immutability of the class

    Consider making the x and y fields final to ensure immutability of the Point class.

    java/src/org/openqa/selenium/Point.java [26-28]

     public class Point {
    -  public int x;
    -  public int y;
    +  public final int x;
    +  public final int y;
     
    
    • [ ] Apply this suggestion <!-- /improve --apply_suggestion=3 -->
    Suggestion importance[1-10]: 7

    Why: Making fields final enhances the immutability of the class, which is a good practice for ensuring thread safety and reducing potential bugs.

    7

    qodo-code-review[bot] avatar Aug 14 '24 20:08 qodo-code-review[bot]