Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue with nested quotes in strings when using passAnnotations #1507

Open
harrismirza opened this issue Mar 21, 2024 · 0 comments
Open

Issue with nested quotes in strings when using passAnnotations #1507

harrismirza opened this issue Mar 21, 2024 · 0 comments

Comments

@harrismirza
Copy link

Hi all,

I noticed a bug when you have for example an annotation on your interface and inside a string property you have nested quotes containing something that looks like: . inside the nested quotes.

This leads immutables to believe what is inside the nested quotes is a Java Class that needs to be imported, but if this does not exist it causes compilation errors.

This only seems to happen if inside the quotes there is a string with a '.' and the first character after the '.' is an upper case letter.

A minimal example is as follows:

import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import org.immutables.value.Value;

@Value.Immutable
@Value.Style(passAnnotations = {JsonPropertyDescription.class})
public interface MinimalImmutablesTest {

    @JsonPropertyDescription(value = "This is a string with nested quotes \"a.B\"")
    int value();
}

Which generates the following class file (note the import at the top):

import a.B;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.immutables.value.Generated;

/**
 * Immutable implementation of {@link MinimalImmutablesTest}.
 * <p>
 * Use the builder to create immutable instances:
 * {@code ImmutableMinimalImmutablesTest.builder()}.
 */
@Generated(from = "MinimalImmutablesTest", generator = "Immutables")
@SuppressWarnings({"all"})
@javax.annotation.Generated("org.immutables.processor.ProxyProcessor")
public final class ImmutableMinimalImmutablesTest implements MinimalImmutablesTest {
  private final int value;

  private ImmutableMinimalImmutablesTest(int value) {
    this.value = value;
  }

  /**
   * @return The value of the {@code value} attribute
   */
  @JsonPropertyDescription("This is a string with nested quotes \"B\"")
  @Override
  public int value() {
    return value;
  }

  /**
   * Copy the current immutable object by setting a value for the {@link MinimalImmutablesTest#value() value} attribute.
   * A value equality check is used to prevent copying of the same value by returning {@code this}.
   * @param value A new value for value
   * @return A modified copy of the {@code this} object
   */
  public final ImmutableMinimalImmutablesTest withValue(int value) {
    if (this.value == value) return this;
    return new ImmutableMinimalImmutablesTest(value);
  }

  /**
   * This instance is equal to all instances of {@code ImmutableMinimalImmutablesTest} that have equal attribute values.
   * @return {@code true} if {@code this} is equal to {@code another} instance
   */
  @Override
  public boolean equals(Object another) {
    if (this == another) return true;
    return another instanceof ImmutableMinimalImmutablesTest
        && equalTo(0, (ImmutableMinimalImmutablesTest) another);
  }

  private boolean equalTo(int synthetic, ImmutableMinimalImmutablesTest another) {
    return value == another.value;
  }

  /**
   * Computes a hash code from attributes: {@code value}.
   * @return hashCode value
   */
  @Override
  public int hashCode() {
    int h = 5381;
    h += (h << 5) + value;
    return h;
  }

  /**
   * Prints the immutable value {@code MinimalImmutablesTest} with attribute values.
   * @return A string representation of the value
   */
  @Override
  public String toString() {
    return "MinimalImmutablesTest{"
        + "value=" + value
        + "}";
  }

  /**
   * Creates an immutable copy of a {@link MinimalImmutablesTest} value.
   * Uses accessors to get values to initialize the new immutable instance.
   * If an instance is already immutable, it is returned as is.
   * @param instance The instance to copy
   * @return A copied immutable MinimalImmutablesTest instance
   */
  public static ImmutableMinimalImmutablesTest copyOf(MinimalImmutablesTest instance) {
    if (instance instanceof ImmutableMinimalImmutablesTest) {
      return (ImmutableMinimalImmutablesTest) instance;
    }
    return ImmutableMinimalImmutablesTest.builder()
        .from(instance)
        .build();
  }

  /**
   * Creates a builder for {@link ImmutableMinimalImmutablesTest ImmutableMinimalImmutablesTest}.
   * <pre>
   * ImmutableMinimalImmutablesTest.builder()
   *    .value(int) // required {@link MinimalImmutablesTest#value() value}
   *    .build();
   * </pre>
   * @return A new ImmutableMinimalImmutablesTest builder
   */
  public static ImmutableMinimalImmutablesTest.Builder builder() {
    return new ImmutableMinimalImmutablesTest.Builder();
  }

  /**
   * Builds instances of type {@link ImmutableMinimalImmutablesTest ImmutableMinimalImmutablesTest}.
   * Initialize attributes and then invoke the {@link #build()} method to create an
   * immutable instance.
   * <p><em>{@code Builder} is not thread-safe and generally should not be stored in a field or collection,
   * but instead used immediately to create instances.</em>
   */
  @Generated(from = "MinimalImmutablesTest", generator = "Immutables")
  public static final class Builder {
    private static final long INIT_BIT_VALUE = 0x1L;
    private long initBits = 0x1L;

    private int value;

    private Builder() {
    }

    /**
     * Fill a builder with attribute values from the provided {@code MinimalImmutablesTest} instance.
     * Regular attribute values will be replaced with those from the given instance.
     * Absent optional values will not replace present values.
     * @param instance The instance from which to copy values
     * @return {@code this} builder for use in a chained invocation
     */
    public final Builder from(MinimalImmutablesTest instance) {
      Objects.requireNonNull(instance, "instance");
      this.value(instance.value());
      return this;
    }

    /**
     * Initializes the value for the {@link MinimalImmutablesTest#value() value} attribute.
     * @param value The value for value 
     * @return {@code this} builder for use in a chained invocation
     */
    public final Builder value(int value) {
      this.value = value;
      initBits &= ~INIT_BIT_VALUE;
      return this;
    }

    /**
     * Builds a new {@link ImmutableMinimalImmutablesTest ImmutableMinimalImmutablesTest}.
     * @return An immutable instance of MinimalImmutablesTest
     * @throws java.lang.IllegalStateException if any required attributes are missing
     */
    public ImmutableMinimalImmutablesTest build() {
      if (initBits != 0) {
        throw new IllegalStateException(formatRequiredAttributesMessage());
      }
      return new ImmutableMinimalImmutablesTest(value);
    }

    private String formatRequiredAttributesMessage() {
      List<String> attributes = new ArrayList<>();
      if ((initBits & INIT_BIT_VALUE) != 0) attributes.add("value");
      return "Cannot build MinimalImmutablesTest, some of required attributes are not set " + attributes;
    }
  }
}
@harrismirza harrismirza changed the title Issue with nested quotes in strings when using passAnnotation Issue with nested quotes in strings when using passAnnotations Mar 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant