Repository: jenkinsci/jenkins
File: core/src/main/java/hudson/model/Result.java (Java)

Code before:
    }

    public boolean isBetterOrEqualTo(@NonNull Result that) {
        return this.ordinal <= that.ordinal;
    }

    /**
     * Is this a complete build - i.e. did it run to the end (not aborted)?
     * @since 1.526
     */
    public boolean isCompleteBuild() {
        return this.completeBuild;
    }

    @Override
    public @NonNull String toString() {
        return name;
    }

    @Override
    public @NonNull String toExportedObject() {
        return name;
    }

    public static @NonNull Result fromString(String s) {
         if (s == null) return FAILURE;
        for (Result r : all)
            if (s.equalsIgnoreCase(r.name))
                return r;
        return FAILURE;
    }

    private static @NonNull List<String> getNames() {
        List<String> l = new ArrayList<>();
        for (Result r : all)
            l.add(r.name);
        return l;
    }

    // Maintain each Result as a singleton deserialized (like build result from an agent node)
    private Object readResolve() {
        for (Result r : all)
            if (ordinal == r.ordinal)
                return r;
        return FAILURE;
    }

    private static final long serialVersionUID = 1L;

    private static final Result[] all = new Result[] {SUCCESS, UNSTABLE, FAILURE, NOT_BUILT, ABORTED};


Review comment (bug):
The removal of the `@NonNull` annotation from the parameter contradicts the method's return annotation which is still `@NonNull`. This creates an ambiguous API contract where the method accepts null but was previously documented as not accepting it.

Additionally, silently returning `FAILURE` for null input may hide bugs in calling code. The `OptionHandlerImpl.parseArguments` method (lines 221-224) assumes that `fromString` only returns `FAILURE` when given an invalid status string, and uses this to generate helpful error messages. With this change, a null input would be incorrectly treated as an invalid status string rather than a programming error.

Consider one of these approaches instead:
1. Keep the `@NonNull` annotation and throw an `IllegalArgumentException` for null inputs
2. If null must be supported, document this behavior with a JavaDoc comment explaining that null returns `FAILURE` and update `OptionHandlerImpl` to handle this case separately
```suggestion
    public static @NonNull Result fromString(@NonNull String s) {
        if (s == null) {
            throw new IllegalArgumentException("Input string for Result.fromString must not be null");
        }
```

Code after:
    }

    public boolean isBetterOrEqualTo(@NonNull Result that) {
        return this.ordinal <= that.ordinal;
    }

    /**
     * Is this a complete build - i.e. did it run to the end (not aborted)?
     * @since 1.526
     */
    public boolean isCompleteBuild() {
        return this.completeBuild;
    }

    @Override
    public @NonNull String toString() {
        return name;
    }

    @Override
    public @NonNull String toExportedObject() {
        return name;
    }

    public static @NonNull Result fromString(@NonNull String s) {
        for (Result r : all)
            if (s.equalsIgnoreCase(r.name))
                return r;
        return FAILURE;
    }

    private static @NonNull List<String> getNames() {
        List<String> l = new ArrayList<>();
        for (Result r : all)
            l.add(r.name);
        return l;
    }

    // Maintain each Result as a singleton deserialized (like build result from an agent node)
    private Object readResolve() {
        for (Result r : all)
            if (ordinal == r.ordinal)
                return r;
        return FAILURE;
    }

    private static final long serialVersionUID = 1L;

    private static final Result[] all = new Result[] {SUCCESS, UNSTABLE, FAILURE, NOT_BUILT, ABORTED};

    public static final SingleValueConverter conv = new AbstractSingleValueConverter() {