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

Formatter fails when complex case is part of switch expression #922

Closed
wk-tw opened this issue Mar 16, 2023 · 6 comments
Closed

Formatter fails when complex case is part of switch expression #922

wk-tw opened this issue Mar 16, 2023 · 6 comments
Labels

Comments

@wk-tw
Copy link

wk-tw commented Mar 16, 2023

Environment :

  • Java 17 Preview
  • Gradle 7.6
  • SpotLess plugin version : id("com.diffplug.spotless") version "6.15.0"

SpotLess configuration :

   spotless {
        java {
            googleJavaFormat("1.15.0")
        }
    }

Issue with complex case :

case ReachableByEmail c && (c instanceof ReachableByPhone)

public class PurchaseService {

  String postPurchaseOperation(Customer customer) {
    return switch (customer) {
      case ReachableByEmail c && (c instanceof ReachableByPhone) ->
          String.format("Send message on both email %s and phone number %s",
              c.getEmail(),
              ((ReachableByPhone) c).getPhoneNumber());
      case ReachableByEmail customerWithEmail -> "Send message to his address email : "
          + customerWithEmail.getEmail();
      case ReachableByPhone customerWithPhone -> "Send message to his phone number : "
          + customerWithPhone.getPhoneNumber();
      default -> "Not reachable";
    };
  }
}

Thrown errors

Caused by: com.google.googlejavaformat.java.FormatterException: 8:13: error: expected token: '&'; generated ( instead and java.lang.reflect.InvocationTargetException

@duncanmak
Copy link

I'm using https://github.com/spotify/fmt-maven-plugin which imports google-java-format 1.17.0 and it's failing to format guard clauses in switch expressions.

The error:

com.google.googlejavaformat.java.FormatterException: 69:13: error: expected token: 'when'; generated - instead

The code:

KiwiNode readTail(boolean dotOK) throws IOException {
    var token = nextToken();

    return switch (token) {
      case String s when s.equals(EOF) -> throw new RuntimeException("EOF during read");
      case String s when s.equals(")") -> ListNode.of();
      case String s when s.equals(".") -> {
          var result = read();
          token = nextToken();
          if (token != ")") warn("Where's the ')'? Got " + token + " after .");
          yield result;
        }
      default -> {
        isPushedToken = true;
        pushedToken = token;
        yield ListNode.cons(read(), readTail(true));
      }
    };
  }

@benzen
Copy link

benzen commented Nov 21, 2023

I'm using 1.18.1 via prettier, this issue is still not resolved.

@TheCK
Copy link
Contributor

TheCK commented Nov 21, 2023

@benzen I have a fix for this in Java 21 but nobody seems to be looking at pull requests 🤷‍♂️

See: #988

@benzen
Copy link

benzen commented Nov 21, 2023

I've seen afterward, but I have no competence for judging it.

I've noticed that your PR was not processed forward because of the CLA agreement that you didn't signed.

Have you signed it since ?

@TheCK
Copy link
Contributor

TheCK commented Nov 21, 2023

@benzen yeah I did. The check is green now. I think it needs some manual intervention though.

@cushon cushon added the Java 21 label Dec 7, 2023
@cushon
Copy link
Collaborator

cushon commented Dec 8, 2023

After the changes in 430ba3b and b86c508, the formatter handles examples like #922 (comment):

class T {
  KiwiNode readTail(boolean dotOK) throws IOException {
    var token = nextToken();

    return switch (token) {
      case String s when s.equals(EOF) -> throw new RuntimeException("EOF during read");
      case String s when s.equals(")") -> ListNode.of();
      case String s when s.equals(".") -> {
        var result = read();
        token = nextToken();
        if (token != ")") warn("Where's the ')'? Got " + token + " after .");
        yield result;
      }
      default -> {
        isPushedToken = true;
        pushedToken = token;
        yield ListNode.cons(read(), readTail(true));
      }
    };
  }
}

@cushon cushon closed this as completed Dec 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants