javaintellij-ideajava-text-blocks

Can IntelliJ convert my old string concatenation to new Text Block feature previewed in Java 14?


I have existing code such as this:

String sql = "CREATE TABLE " + tableName + " (\n" +
        "  id_ UUID DEFAULT random_uuid() PRIMARY KEY ,\n" +
        "  when_ TIMESTAMP WITHOUT TIME ZONE NOT NULL\n" +
        "  duration_ STRING NOT NULL\n" +
        ");";

…in a project in IntelliJ 2020.1.1 (preview) Ultimate edition where the JDK settings are configured for language level 14 (Preview) - Records, patters, text blocks.

So I expected IntelliJ to offer a conversion to text blocks among the items display when I click on the yellow light bulb that appears next to this line of code. But I see no such offer.

screen shot of pop-up menu displayed by clicking on yellow light bulb next to this line of code

I am surprised to not find such an offer, as the JetBrains company claims to support JEP 368: Text Blocks (Second Preview) in their 2020.1 version of IntelliJ, as discussed here and here.

➥ Does IntelliJ offer some way to convert old string concatenation to text blocks?


Solution

  • Disclosure: IntelliJ IDEA developer is here.


    Currently, IntelliJ IDEA only suggests converting the complete literal concatenation into the text block. Here, however, you have a concatenation that involves the tableName variable. This prevents inspection from starting. You can work-around this adding bogus parentheses:

    String sql = "CREATE TABLE " + tableName + (" (\n" +
                 "  id_ UUID DEFAULT random_uuid() PRIMARY KEY ,\n" +
                 "  when_ TIMESTAMP WITHOUT TIME ZONE NOT NULL\n" +
                 "  duration_ STRING NOT NULL\n" +
                 ");");
    

    After that, the conversion is suggested on the first \n character:

    IntelliJ IDEA screenshot

    The result after removing parentheses looks like this:

    String sql = "CREATE TABLE " + tableName + """
             (
              id_ UUID DEFAULT random_uuid() PRIMARY KEY ,
              when_ TIMESTAMP WITHOUT TIME ZONE NOT NULL
              duration_ STRING NOT NULL
            );""";
    

    I filed an issue to suggest the conversion if only a part of concatenation can be converted to the text block.

    An alternative solution, which actually is promoted by JDK, is to use string formatting. First, use intention action "Replace '+' with 'String.format()'" (it's available via Alt+Enter everywhere inside the concatenation). The result looks like this:

    String sql = String
        .format("CREATE TABLE %s (\n  id_ UUID DEFAULT random_uuid() PRIMARY KEY ,\n  when_ TIMESTAMP WITHOUT TIME " +
                "ZONE NOT NULL\n  duration_ STRING NOT NULL\n);", tableName);
    

    Now it's immediately suggested to use text block, and the result looks like this:

    String sql = String.format("""
            CREATE TABLE %s (
              id_ UUID DEFAULT random_uuid() PRIMARY KEY ,
              when_ TIMESTAMP WITHOUT TIME ZONE NOT NULL
              duration_ STRING NOT NULL
            );""", tableName);
    

    Unfortunately, a new instance method .formatted() is not suggested (filed another issue), so it will require some manual work to convert it:

    String sql = """
            CREATE TABLE %s (
              id_ UUID DEFAULT random_uuid() PRIMARY KEY ,
              when_ TIMESTAMP WITHOUT TIME ZONE NOT NULL
              duration_ STRING NOT NULL
            );""".formatted(tableName);