This is an automated email from the ASF dual-hosted git repository.

jlahoda pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new cb50c2f  JDK13 text block support
cb50c2f is described below

commit cb50c2fede0387535900727e1abdcd4718ab02fd
Author: Reema Taneja <32299405+rtane...@users.noreply.github.com>
AuthorDate: Sun Aug 25 14:14:54 2019 +0530

    JDK13 text block support
---
 ide/editor.indent/apichanges.xml                   |  12 ++
 .../modules/editor/indent/spi/Context.java         |  32 ++++-
 .../src/org/netbeans/editor/BaseKit.java           |  51 +++++--
 .../editor/base/semantic/ColoringAttributes.java   |   4 +-
 .../base/semantic/SemanticHighlighterBase.java     |  59 +++++++-
 .../java/editor/base/semantic/TokenList.java       |  24 ++++
 .../java/editor/base/semantic/DetectorTest.java    |  43 ++++++
 .../java/editor/base/semantic/HighlightImpl.java   |   1 +
 .../java/editor/base/semantic/MarkOccDetTest.java  |  17 ++-
 .../java/editor/base/semantic/TestBase.java        |  80 ++++++++++-
 .../modules/editor/java/TypingCompletion.java      |  53 +++++--
 .../java/editor/imports/ClipboardHandler.java      | 128 ++++++++++++-----
 .../modules/java/editor/resources/fontsColors.xml  |   1 +
 .../java/editor/semantic/ColoringManager.java      |   1 +
 .../java/editor/semantic/SemanticHighlighter.java  |   8 +-
 .../editor/java/TypingCompletionUnitTest.java      |  63 ++++++++-
 .../java/editor/imports/ClipboardHandlerTest.java  |  15 ++
 .../modules/java/hints/jdk/ConvertToTextBlock.java | 109 +++++++++++++++
 .../modules/java/hints/resources/jdk13.properties  |  17 +++
 .../modules/java/hints/resources/layer.xml         |  16 +++
 .../java/hints/jdk/ConvertToTextBlockTest.java     | 155 +++++++++++++++++++++
 java/java.lexer/apichanges.xml                     |  12 ++
 .../org/netbeans/api/java/lexer/JavaTokenId.java   |   2 +
 .../src/org/netbeans/lib/java/lexer/JavaLexer.java |  24 +++-
 .../lib/java/lexer/JavaLexerBatchTest.java         |  35 ++++-
 .../org/netbeans/api/java/source/SourceUtils.java  |  26 +++-
 .../modules/java/source/builder/TreeFactory.java   |   2 +
 .../modules/java/source/pretty/CharBuffer.java     |  16 ++-
 .../modules/java/source/pretty/VeryPretty.java     |  34 ++++-
 .../modules/java/source/save/Reindenter.java       |  34 ++++-
 .../netbeans/api/java/source/gen/LiteralTest.java  |  88 ++++++++++++
 .../modules/java/source/save/ReindenterTest.java   |  35 ++++-
 32 files changed, 1104 insertions(+), 93 deletions(-)

diff --git a/ide/editor.indent/apichanges.xml b/ide/editor.indent/apichanges.xml
index 932020a..255737d 100644
--- a/ide/editor.indent/apichanges.xml
+++ b/ide/editor.indent/apichanges.xml
@@ -83,6 +83,18 @@ is the proper place.
     <!-- ACTUAL CHANGES BEGIN HERE: -->
 
     <changes>
+        <change id="indent.given.indent">
+            <summary>Indent can be given as a string</summary>
+            <version major="1" minor="49"/>
+            <date day="16" month="6" year="2019"/>
+            <author login="jlahoda"/>
+            <compatibility source="compatible" binary="compatible"/>
+            <description>
+                Added method 
org.netbeans.modules.editor.indent.spi.Context.modifyIndent(int, int, String),
+                which allows to set indent by specifying particular indent 
string.
+            </description>
+            <class package="org.netbeans.modules.editor.indent.spi" 
name="Context"/>
+        </change>
         <change id="indent.support">
             <summary>Indentation Support module created</summary>
             <version major="1" minor="39"/>
diff --git 
a/ide/editor.indent/src/org/netbeans/modules/editor/indent/spi/Context.java 
b/ide/editor.indent/src/org/netbeans/modules/editor/indent/spi/Context.java
index a9d1108..0ed70ad 100644
--- a/ide/editor.indent/src/org/netbeans/modules/editor/indent/spi/Context.java
+++ b/ide/editor.indent/src/org/netbeans/modules/editor/indent/spi/Context.java
@@ -170,23 +170,43 @@ public final class Context {
         }
 
         String newIndentString = IndentUtils.createIndentString(doc, 
newIndent);
+
+        modifyIndent(lineStartOffset, oldIndentEndOffset - lineStartOffset, 
newIndentString);
+    }
+
+    /**
+     * Modify indent of the line at the offset passed as the parameter, by 
stripping the given
+     * number of input characters and inserting the given indent.
+     *
+     * @param lineStartOffset start offset of a line where the indent is being 
modified.
+     * @param oldIndentCharCount number of characters to remove.
+     * @param newIndent new indent.
+     * @throws javax.swing.text.BadLocationException if the given 
lineStartOffset is not within
+     *  corresponding document's bounds.
+     * @since 1.49
+     */
+    public void modifyIndent(int lineStartOffset, int oldIndentCharCount, 
String newIndent) throws BadLocationException {
+        Document doc = document();
+        IndentImpl.checkOffsetInDocument(doc, lineStartOffset);
+        CharSequence docText = DocumentUtilities.getText(doc);
+        int oldIndentEndOffset = lineStartOffset + oldIndentCharCount;
         // Attempt to match the begining characters
         int offset = lineStartOffset;
-        for (int i = 0; i < newIndentString.length() && lineStartOffset + i < 
oldIndentEndOffset; i++) {
-            if (newIndentString.charAt(i) != docText.charAt(lineStartOffset + 
i)) {
+        for (int i = 0; i < newIndent.length() && lineStartOffset + i < 
oldIndentEndOffset; i++) {
+            if (newIndent.charAt(i) != docText.charAt(lineStartOffset + i)) {
                 offset = lineStartOffset + i;
-                newIndentString = newIndentString.substring(i);
+                newIndent = newIndent.substring(i);
                 break;
             }
         }
         
         // Replace the old indent
-        if (!doc.getText(offset, oldIndentEndOffset - 
offset).equals(newIndentString)) {
+        if (!doc.getText(offset, oldIndentEndOffset - 
offset).equals(newIndent)) {
             if (offset < oldIndentEndOffset) {
                 doc.remove(offset, oldIndentEndOffset - offset);
             }
-            if (newIndentString.length() > 0) {
-                doc.insertString(offset, newIndentString, null);
+            if (newIndent.length() > 0) {
+                doc.insertString(offset, newIndent, null);
             }
         }
     }
diff --git a/ide/editor.lib/src/org/netbeans/editor/BaseKit.java 
b/ide/editor.lib/src/org/netbeans/editor/BaseKit.java
index b36c6c9..0add683 100644
--- a/ide/editor.lib/src/org/netbeans/editor/BaseKit.java
+++ b/ide/editor.lib/src/org/netbeans/editor/BaseKit.java
@@ -1374,25 +1374,48 @@ public class BaseKit extends DefaultEditorKit {
                 editorUI.getWordMatch().clear(); // reset word matching
                 Boolean overwriteMode = 
(Boolean)editorUI.getProperty(EditorUI.OVERWRITE_MODE_PROPERTY);
                 boolean ovr = (overwriteMode != null && 
overwriteMode.booleanValue());
-                if (Utilities.isSelectionShowing(caret)) { // valid selection
-                    try {
-                        doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, true);
-                        replaceSelection(target, insertionOffset, caret, 
insertionText, ovr);
-                    } finally {
-                        doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, null);
+                int currentInsertOffset = insertionOffset;
+                int targetCaretOffset = caretPosition;
+                for (int i = 0; i < insertionText.length();) {
+                    int end = insertionText.indexOf('\n', i);
+                    if (end == (-1)) end = insertionText.length();
+                    String currentLine = insertionText.substring(i, end);
+                    if (i == 0) {
+                        if (Utilities.isSelectionShowing(caret)) { // valid 
selection
+                            try {
+                                
doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, true);
+                                replaceSelection(target, currentInsertOffset, 
caret, currentLine, ovr);
+                            } finally {
+                                
doc.putProperty(DOC_REPLACE_SELECTION_PROPERTY, null);
+                            }
+                        } else { // no selection
+                            if (ovr && currentInsertOffset < doc.getLength() 
&& doc.getChars(currentInsertOffset, 1)[0] != '\n') { //NOI18N
+                                // overwrite current char
+                                insertString(doc, currentInsertOffset, caret, 
currentLine, true);
+                            } else { // insert mode
+                                insertString(doc, currentInsertOffset, caret, 
currentLine, false);
+                            }
+                        }
+                    } else {
+                        Indent indent = Indent.get(doc);
+                        indent.lock();
+                        try {
+                            currentInsertOffset = 
indent.indentNewLine(currentInsertOffset);
+                        } finally {
+                            indent.unlock();
+                        }
+                        insertString(doc, currentInsertOffset, caret, 
currentLine, false);
                     }
-                } else { // no selection
-                    if (ovr && insertionOffset < doc.getLength() && 
doc.getChars(insertionOffset, 1)[0] != '\n') { //NOI18N
-                        // overwrite current char
-                        insertString(doc, insertionOffset, caret, 
insertionText, true);
-                    } else { // insert mode
-                        insertString(doc, insertionOffset, caret, 
insertionText, false);
+                    if (caretPosition >= i && caretPosition <= end) {
+                        targetCaretOffset = currentInsertOffset - 
insertionOffset + caretPosition - i;
                     }
+                    currentInsertOffset += currentLine.length();
+                    i = end + 1;
                 }
 
-                if (caretPosition != -1) {
+                if (targetCaretOffset != -1) {
                     assert caretPosition >= 0 && (caretPosition <= 
insertionText.length());
-                    caret.setDot(insertionOffset + caretPosition);
+                    caret.setDot(insertionOffset + targetCaretOffset);
                 }
             } finally {
                 DocumentUtilities.setTypingModification(doc, false);
diff --git 
a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/ColoringAttributes.java
 
b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/ColoringAttributes.java
index b9796f7..9f09f17 100644
--- 
a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/ColoringAttributes.java
+++ 
b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/ColoringAttributes.java
@@ -62,7 +62,9 @@ public enum ColoringAttributes {
     
     KEYWORD,
     
-    JAVADOC_IDENTIFIER;
+    JAVADOC_IDENTIFIER,
+
+    UNINDENTED_TEXT_BLOCK;
     
     public static Coloring empty() {
         return new Coloring();
diff --git 
a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
 
b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
index 58c7a05..5d6d51c 100644
--- 
a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
+++ 
b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/SemanticHighlighterBase.java
@@ -65,12 +65,14 @@ import javax.lang.model.element.Modifier;
 import javax.lang.model.type.TypeKind;
 import javax.lang.model.type.TypeMirror;
 import javax.swing.text.Document;
+import org.netbeans.api.java.lexer.JavaTokenId;
 import org.netbeans.api.java.source.CompilationInfo;
 import org.netbeans.api.java.source.ElementHandle;
 import org.netbeans.api.java.source.JavaParserResultTask;
 import org.netbeans.api.java.source.JavaSource.Phase;
 import org.netbeans.api.java.source.TreeUtilities;
 import org.netbeans.api.java.source.support.CancellableTreePathScanner;
+import org.netbeans.api.lexer.PartType;
 import org.netbeans.api.lexer.Token;
 import org.netbeans.api.lexer.TokenHierarchy;
 //import org.netbeans.modules.editor.NbEditorUtilities;
@@ -81,6 +83,8 @@ import org.netbeans.modules.parsing.spi.Scheduler;
 import org.netbeans.modules.parsing.spi.SchedulerEvent;
 import org.netbeans.modules.parsing.spi.TaskIndexingMode;
 import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
+import org.openide.util.Pair;
 
 
 /**
@@ -249,23 +253,25 @@ public abstract class SemanticHighlighterBase extends 
JavaParserResultTask {
         
         boolean computeUnusedImports = 
"text/x-java".equals(FileUtil.getMIMEType(info.getFileObject()));
         
-        List<int[]> imports = computeUnusedImports ? new ArrayList<int[]>() : 
null;
+        List<Pair<int[], Coloring>> extraColoring = computeUnusedImports ? new 
ArrayList<>(v.extraColoring) : v.extraColoring;
 
         if (computeUnusedImports) {
             Collection<TreePath> unusedImports = UnusedImports.process(info, 
cancel);
 
             if (unusedImports == null) return true;
             
+            Coloring unused = 
collection2Coloring(Arrays.asList(ColoringAttributes.UNUSED));
+
             for (TreePath tree : unusedImports) {
                 if (cancel.get()) {
                     return true;
                 }
 
                 //XXX: finish
-                imports.add(new int[] {
+                extraColoring.add(Pair.of(new int[] {
                     (int) 
info.getTrees().getSourcePositions().getStartPosition(cu, tree.getLeaf()),
                     (int) 
info.getTrees().getSourcePositions().getEndPosition(cu, tree.getLeaf())
-                });
+                }, unused));
             }
         }
         
@@ -320,7 +326,7 @@ public abstract class SemanticHighlighterBase extends 
JavaParserResultTask {
             return true;
         
         if (computeUnusedImports) {
-            setter.setHighlights(doc, imports, v.preText);
+            setter.setHighlights(doc, extraColoring, v.preText);
         }
 
         setter.setColorings(doc, newColoring);
@@ -407,6 +413,7 @@ public abstract class SemanticHighlighterBase extends 
JavaParserResultTask {
         private Map<Element, List<Use>> type2Uses;        
         private Map<Tree, List<Token>> tree2Tokens;
         private List<Token> contextKeywords;
+        private List<Pair<int[], Coloring>> extraColoring;
         private Map<int[], String> preText;
         private TokenList tl;
         private long memberSelectBypass = -1;        
@@ -421,6 +428,7 @@ public abstract class SemanticHighlighterBase extends 
JavaParserResultTask {
             type2Uses = new HashMap<Element, List<Use>>();
             tree2Tokens = new IdentityHashMap<Tree, List<Token>>();
             contextKeywords = new ArrayList<>();
+            extraColoring = new ArrayList<>();
             preText = new HashMap<>();
 
             tl = new TokenList(info, doc, cancel);
@@ -1063,8 +1071,36 @@ public abstract class SemanticHighlighterBase extends 
JavaParserResultTask {
             return null;
         }
 
+        private static final Coloring UNINDENTED_TEXT_BLOCK =
+                ColoringAttributes.add(ColoringAttributes.empty(), 
ColoringAttributes.UNINDENTED_TEXT_BLOCK);
+
         @Override
         public Void visitLiteral(LiteralTree node, Void p) {
+            int startPos = (int) 
info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(),
 node);
+            tl.moveToOffset(startPos);
+            Token t = tl.currentToken();
+            if (t != null && t.id() == JavaTokenId.MULTILINE_STRING_LITERAL && 
t.partType() == PartType.COMPLETE) {
+                String tokenText = t.text().toString();
+                String[] lines = tokenText.split("\n");
+                int indent = Arrays.stream(lines, 1, lines.length)
+                                   .mapToInt(this::leadingIndent)
+                                   .min()
+                                   .orElse(0);
+                int pos = startPos + lines[0].length() + 1;
+                for (int i = 1; i < lines.length; i++) {
+                    String line = lines[i];
+                    if (i == lines.length - 1) {
+                        line = line.substring(0, line.length() - 3);
+                    }
+                    String strippendLine = line.replaceAll("[\t ]+$", "");
+                    int indentedStart = pos + indent;
+                    int indentedEnd = pos + strippendLine.length();
+                    if (indentedEnd > indentedStart)
+                        extraColoring.add(Pair.of(new int[] {indentedStart, 
indentedEnd}, UNINDENTED_TEXT_BLOCK));
+                    pos += line.length() + 1;
+                }
+            }
+
             TreePath pp = getCurrentPath().getParentPath();
             if (pp.getLeaf() != null &&
                 pp.getLeaf().getKind() == Kind.METHOD_INVOCATION) {
@@ -1085,11 +1121,24 @@ public abstract class SemanticHighlighterBase extends 
JavaParserResultTask {
             return super.visitLiteral(node, p);
         }
 
+        private int leadingIndent(String line) {
+            int indent = 0;
+
+            for (int i = 0; i < line.length(); i++) { //TODO: code points
+                if (Character.isWhitespace(line.charAt(i)))
+                    indent++;
+                else
+                    break;
+            }
+
+            return indent;
+        }
+
     }
 
     public static interface ErrorDescriptionSetter {
         
-        public void setHighlights(Document doc, Collection<int[]> highlights, 
Map<int[], String> preText);
+        public void setHighlights(Document doc, Collection<Pair<int[], 
Coloring>> highlights, Map<int[], String> preText);
         public void setColorings(Document doc, Map<Token, Coloring> colorings);
     }    
 }
diff --git 
a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/TokenList.java
 
b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/TokenList.java
index 1bab7c3..cadc339 100644
--- 
a/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/TokenList.java
+++ 
b/java/java.editor.base/src/org/netbeans/modules/java/editor/base/semantic/TokenList.java
@@ -240,6 +240,30 @@ public class TokenList {
         });
     }
     
+    public Token currentToken() {
+        Token[] res = new Token[1];
+        doc.render(new Runnable() {
+            @Override
+            public void run() {
+                if (cancel.get()) {
+                    return ;
+                }
+
+                if (ts != null && !ts.isValid()) {
+                    cancel.set(true);
+                    return ;
+                }
+
+                if (ts == null) {
+                    return ;
+                }
+
+                res[0] = ts.token();
+            }
+        });
+        return res[0];
+    }
+
     public void moduleNameHere(final ExpressionTree tree, final Map<Tree, 
List<Token>> tree2Tokens) {
         doc.render(new Runnable() {
             @Override
diff --git 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
index 1f25ff4..4dcece3 100644
--- 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
+++ 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/DetectorTest.java
@@ -21,6 +21,7 @@ package org.netbeans.modules.java.editor.base.semantic;
 import java.util.logging.Handler;
 import java.util.logging.LogRecord;
 import java.util.logging.Logger;
+import javax.lang.model.SourceVersion;
 import javax.swing.text.BadLocationException;
 import javax.swing.text.Document;
 import org.netbeans.api.java.source.CompilationController;
@@ -445,6 +446,35 @@ public class DetectorTest extends TestBase {
         performTest("IncDecReading230408");
     }
 
+    public void testRawStringLiteral() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException iae) {
+            //OK, presumably no support for raw string literals
+        }
+        setSourceLevel("13");
+        performTest("RawStringLiteral",
+                    "public class RawStringLiteral {\n" +
+                    "    String s1 = \"\"\"\n" +
+                    "                int i1 = 1;    \n" +
+                    "                  int i2 = 2;\n" +
+                    "             \"\"\";\n" +
+                    "    String s2 = \"\"\"\n" +
+                    "                int i1 = 1;    \n" +
+                    "                  int i2 = 2;\n" +
+                    "                      \"\"\";\n" +
+                    "}\n",
+                    "[PUBLIC, CLASS, DECLARATION], 0:13-0:29",
+                    "[PUBLIC, CLASS], 1:4-1:10",
+                    "[PACKAGE_PRIVATE, FIELD, DECLARATION], 1:11-1:13",
+                    "[UNINDENTED_TEXT_BLOCK], 2:13-2:27",
+                    "[UNINDENTED_TEXT_BLOCK], 3:13-3:29",
+                    "[PUBLIC, CLASS], 5:4-5:10",
+                    "[PACKAGE_PRIVATE, FIELD, DECLARATION], 5:11-5:13",
+                    "[UNINDENTED_TEXT_BLOCK], 6:16-6:27",
+                    "[UNINDENTED_TEXT_BLOCK], 7:16-7:29");
+    }
+
     private void performTest(String fileName) throws Exception {
         performTest(fileName, new Performer() {
             public void compute(CompilationController parameter, Document doc, 
final ErrorDescriptionSetter setter) {
@@ -471,6 +501,19 @@ public class DetectorTest extends TestBase {
         }, false, expected);
     }
 
+    private void performTest(String fileName, String code, String... expected) 
throws Exception {
+        performTest(fileName, code, new Performer() {
+            public void compute(CompilationController parameter, Document doc, 
final ErrorDescriptionSetter setter) {
+                new SemanticHighlighterBase() {
+                    @Override
+                    protected boolean process(CompilationInfo info, Document 
doc) {
+                        return process(info, doc, setter);
+                    }
+                }.process(parameter, doc);
+            }
+        }, expected);
+    }
+
     private FileObject testSourceFO;
     
     static {
diff --git 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/HighlightImpl.java
 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/HighlightImpl.java
index dffd3e5..6ee1410 100644
--- 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/HighlightImpl.java
+++ 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/HighlightImpl.java
@@ -142,6 +142,7 @@ public final class HighlightImpl {
         ColoringAttributes.DECLARATION,
         
         ColoringAttributes.MARK_OCCURRENCES,
+        ColoringAttributes.UNINDENTED_TEXT_BLOCK,
     });
  
     public static HighlightImpl parse(StyledDocument doc, String line) throws 
ParseException, BadLocationException {
diff --git 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
index cd07ba6..63f5b27 100644
--- 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
+++ 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/MarkOccDetTest.java
@@ -20,6 +20,7 @@ package org.netbeans.modules.java.editor.base.semantic;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 import javax.swing.text.Document;
 import javax.swing.text.StyledDocument;
 import junit.framework.Test;
@@ -27,10 +28,12 @@ import junit.framework.TestSuite;
 import org.netbeans.api.java.source.CompilationController;
 import org.netbeans.api.java.source.CompilationInfo;
 import org.netbeans.api.java.source.test.support.MemoryValidator;
+import 
org.netbeans.modules.java.editor.base.semantic.ColoringAttributes.Coloring;
 import org.netbeans.modules.java.editor.options.MarkOccurencesSettings;
 import org.netbeans.modules.java.editor.base.semantic.TestBase.Performer;
 import org.netbeans.modules.parsing.spi.SchedulerEvent;
 import org.openide.text.NbDocument;
+import org.openide.util.Pair;
 
 /**XXX: constructors throwing an exception are not marked as exit points
  *
@@ -343,6 +346,9 @@ public class MarkOccDetTest extends TestBase {
         performTest(name, line, column, false);
     }
     
+    private static final Coloring MARK_OCCURRENCES =
+            ColoringAttributes.add(ColoringAttributes.empty(), 
ColoringAttributes.MARK_OCCURRENCES);
+
     private void performTest(String name, final int line, final int column, 
boolean doCompileRecursively) throws Exception {
         performTest(name,new Performer() {
             public void compute(CompilationController info, Document doc, 
SemanticHighlighterBase.ErrorDescriptionSetter setter) {
@@ -350,19 +356,18 @@ public class MarkOccDetTest extends TestBase {
                 List<int[]> spans = new MarkOccurrencesHighlighterBase() {
                     @Override
                     protected void process(CompilationInfo info, Document doc, 
SchedulerEvent event) {
-                        throw new UnsupportedOperationException("Not supported 
yet."); //To change body of generated methods, choose Tools | Templates.
+                        throw new UnsupportedOperationException("Not supported 
yet.");
                     }
                 }.processImpl(info, MarkOccurencesSettings.getCurrentNode(), 
doc, offset);
                 
                 if (spans != null) {
-                    setter.setHighlights(doc, spans, Collections.<int[], 
String>emptyMap());
+                    setter.setHighlights(doc, spans.stream()
+                                                   .map(span -> Pair.of(span, 
MARK_OCCURRENCES))
+                                                   
.collect(Collectors.toList()),
+                                         Collections.<int[], 
String>emptyMap());
                 }
             }
         }, doCompileRecursively);
     }
     
-    protected ColoringAttributes getColoringAttribute() {
-        return ColoringAttributes.MARK_OCCURRENCES;
-    }
-    
 }
diff --git 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
index 7b2aca5..9d681b6 100644
--- 
a/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
+++ 
b/java/java.editor.base/test/unit/src/org/netbeans/modules/java/editor/base/semantic/TestBase.java
@@ -31,6 +31,7 @@ import java.io.StringWriter;
 import java.io.Writer;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.EnumSet;
@@ -40,6 +41,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
 import javax.swing.text.Document;
 import org.netbeans.api.java.lexer.JavaTokenId;
 import org.netbeans.api.java.source.Task;
@@ -47,6 +49,7 @@ import org.netbeans.api.java.source.CompilationController;
 import org.netbeans.api.java.source.JavaSource;
 import org.netbeans.api.java.source.JavaSource.Phase;
 import org.netbeans.api.java.source.SourceUtilsTestUtil;
+import org.netbeans.api.java.source.TestUtilities;
 import org.netbeans.api.java.source.TreePathHandle;
 import org.netbeans.api.lexer.Language;
 import org.netbeans.api.lexer.Token;
@@ -57,6 +60,7 @@ import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileUtil;
 import org.openide.filesystems.MIMEResolver;
 import org.openide.loaders.DataObject;
+import org.openide.util.Pair;
 
 /**
  *
@@ -230,8 +234,74 @@ public abstract class TestBase extends NbTestCase {
         validator.validate(out.toString());
     }
     
-    protected ColoringAttributes getColoringAttribute() {
-        return ColoringAttributes.UNUSED;
+    protected void performTest(String fileName, String code, Performer 
performer, String... expected) throws Exception {
+        performTest(fileName, code, performer, false, expected);
+    }
+
+    protected void performTest(String fileName, String code, Performer 
performer, boolean doCompileRecursively, String... expected) throws Exception {
+        SourceUtilsTestUtil.prepareTest(new String[] 
{"org/netbeans/modules/java/editor/resources/layer.xml"}, new Object[] {new 
MIMEResolverImpl()});
+
+       FileObject scratch = SourceUtilsTestUtil.makeScratchDir(this);
+       FileObject cache   = scratch.createFolder("cache");
+
+        File wd         = getWorkDir();
+        File testSource = new File(wd, "test/" + fileName + ".java");
+
+        testSource.getParentFile().mkdirs();
+        TestUtilities.copyStringToFile(testSource, code);
+
+        testSourceFO = FileUtil.toFileObject(testSource);
+
+        assertNotNull(testSourceFO);
+
+        if (sourceLevel != null) {
+            SourceUtilsTestUtil.setSourceLevel(testSourceFO, sourceLevel);
+        }
+
+        File testBuildTo = new File(wd, "test-build");
+
+        testBuildTo.mkdirs();
+
+        FileObject srcRoot = FileUtil.toFileObject(testSource.getParentFile());
+        
SourceUtilsTestUtil.prepareTest(srcRoot,FileUtil.toFileObject(testBuildTo), 
cache);
+
+        if (doCompileRecursively) {
+            SourceUtilsTestUtil.compileRecursively(srcRoot);
+        }
+
+        final Document doc = getDocument(testSourceFO);
+        final List<HighlightImpl> highlights = new ArrayList<HighlightImpl>();
+
+        JavaSource source = JavaSource.forFileObject(testSourceFO);
+
+        assertNotNull(source);
+
+       final CountDownLatch l = new CountDownLatch(1);
+
+        source.runUserActionTask(new Task<CompilationController>() {
+            public void run(CompilationController parameter) {
+                try {
+                    parameter.toPhase(Phase.UP_TO_DATE);
+
+                    ErrorDescriptionSetterImpl setter = new 
ErrorDescriptionSetterImpl();
+
+                    performer.compute(parameter, doc, setter);
+
+                    highlights.addAll(setter.highlights);
+                } catch (IOException e) {
+                    e.printStackTrace();
+                } finally {
+                   l.countDown();
+               }
+            }
+        }, true);
+
+        l.await();
+
+        assertEquals(Arrays.asList(expected),
+                     highlights.stream()
+                               .map(h -> h.getHighlightTestData())
+                               .collect(Collectors.toList()));
     }
     
     public static Collection<HighlightImpl> toHighlights(Document doc, 
Map<Token, Coloring> colors) {
@@ -290,9 +360,9 @@ public abstract class TestBase extends NbTestCase {
         }
     
         @Override
-        public void setHighlights(Document doc, Collection<int[]> highlights, 
Map<int[], String> preText) {
-            for (int[] h : highlights) {
-                this.highlights.add(new HighlightImpl(doc, h[0], h[1], 
EnumSet.of(getColoringAttribute())));
+        public void setHighlights(Document doc, Collection<Pair<int[], 
Coloring>> highlights, Map<int[], String> preText) {
+            for (Pair<int[], Coloring> h : highlights) {
+                this.highlights.add(new HighlightImpl(doc, h.first()[0], 
h.first()[1], h.second()));
             }
             if (showPrependedText) {
                 for (Entry<int[], String> e : preText.entrySet()) {
diff --git 
a/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java 
b/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java
index be2f82b..1641a25 100644
--- 
a/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java
+++ 
b/java/java.editor/src/org/netbeans/modules/editor/java/TypingCompletion.java
@@ -22,18 +22,24 @@ import java.util.EnumSet;
 import java.util.List;
 import java.util.Set;
 import java.util.prefs.Preferences;
+import javax.lang.model.SourceVersion;
 import javax.swing.text.BadLocationException;
 import javax.swing.text.Document;
 import org.netbeans.api.editor.mimelookup.MimeLookup;
 import org.netbeans.api.editor.settings.SimpleValueNames;
 import org.netbeans.api.java.lexer.JavaTokenId;
+import static org.netbeans.api.java.source.SourceUtils.isTextBlockSupported;
 import org.netbeans.api.lexer.PartType;
 import org.netbeans.api.lexer.TokenHierarchy;
 import org.netbeans.api.lexer.TokenSequence;
 import org.netbeans.editor.BaseDocument;
+import org.netbeans.modules.editor.NbEditorUtilities;
+import org.netbeans.modules.editor.indent.api.Indent;
 import org.netbeans.spi.editor.typinghooks.DeletedTextInterceptor;
 import org.netbeans.spi.editor.typinghooks.TypedBreakInterceptor;
 import org.netbeans.spi.editor.typinghooks.TypedTextInterceptor;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
 
 /**
  * This static class groups the whole aspect of bracket completion. It is
@@ -138,9 +144,16 @@ class TypingCompletion {
         
         
         char chr = context.getDocument().getText(context.getOffset(), 
1).charAt(0);
-        if (chr == ')' || chr == ',' || chr == '\"' || chr == '\'' || chr == ' 
' || chr == ']' || chr == '}' || chr == '\n' || chr == '\t' || chr == ';') {
+        if (chr == ')' || chr == ',' || chr == '\'' || chr == ' ' || chr == 
']' || chr == '}' || chr == '\n' || chr == '\t' || chr == ';') {
             char insChr = context.getText().charAt(0);
-            context.setText("" + insChr + matching(insChr) , 1);  // NOI18N
+            context.setText("" + insChr + matching(insChr), 1);  // NOI18N
+        } else if (chr == '\"') {
+            if ((context.getOffset() > 2 && 
context.getDocument().getText(context.getOffset() - 2, 3).equals("\"\"\"")) &&
+                    isTextBlockSupported(getFileObject((BaseDocument) 
context.getDocument()))) {
+                context.setText("\"\n\"\"\"", 2);  // NOI18N
+            } else {
+                context.setText("\"\"", 1);  // NOI18N
+            }
         }
     }
 
@@ -202,7 +215,6 @@ class TypingCompletion {
         TokenSequence<JavaTokenId> javaTS = javaTokenSequence(context, true);
         JavaTokenId id = (javaTS != null) ? javaTS.token().id() : null;
 
-
         // If caret within comment return false
         boolean caretInsideToken = (id != null)
                 && (javaTS.offset() + javaTS.token().length() > 
context.getOffset()
@@ -214,7 +226,8 @@ class TypingCompletion {
         boolean completablePosition = isQuoteCompletablePosition(context);
         boolean insideString = caretInsideToken
                 && (id == JavaTokenId.STRING_LITERAL
-                || id == JavaTokenId.CHAR_LITERAL);
+                || id == JavaTokenId.CHAR_LITERAL
+                || id == JavaTokenId.MULTILINE_STRING_LITERAL);
 
         int lastNonWhite = 
org.netbeans.editor.Utilities.getRowLastNonWhite((BaseDocument) 
context.getDocument(), context.getOffset());
         // eol - true if the caret is at the end of line (ignoring whitespaces)
@@ -231,7 +244,7 @@ class TypingCompletion {
                         javaTS.move(context.getOffset() - 1);
                         if (javaTS.moveNext()) {
                             id = javaTS.token().id();
-                            if (id == JavaTokenId.STRING_LITERAL || id == 
JavaTokenId.CHAR_LITERAL) {
+                            if (id == JavaTokenId.STRING_LITERAL || id == 
JavaTokenId.CHAR_LITERAL || id == JavaTokenId.MULTILINE_STRING_LITERAL) {
                                 context.setText("", 0); // NOI18N
                                 return context.getOffset() + 1;
                             }
@@ -242,7 +255,26 @@ class TypingCompletion {
         }
 
         if ((completablePosition && !insideString) || eol) {
-            context.setText(context.getText() + context.getText(), 1);
+            if (context.getText().equals("\"") && context.getOffset() >= 2 &&
+                    context.getDocument().getText(context.getOffset() - 2, 
2).equals("\"\"") &&
+                    isTextBlockSupported(getFileObject((BaseDocument) 
context.getDocument()))) {
+                context.setText("\"\n\"\"\"", 2);  // NOI18N
+                Thread.dumpStack();
+            } else {
+                context.setText(context.getText() + context.getText(), 1);
+            }
+        } else if (context.getText().equals("\"") &&
+                isTextBlockSupported(getFileObject((BaseDocument) 
context.getDocument()))) {
+            if ((javaTS != null) && javaTS.moveNext()) {
+                id = javaTS.token().id();
+                if ((id == JavaTokenId.STRING_LITERAL) && 
(javaTS.token().text().toString().equals("\"\""))) {
+                    if (context.getDocument().getText(context.getOffset(), 
2).equals("\"\"")) {
+                        context.setText("\"\"\"\n\"", 4);
+                    }
+                }
+                javaTS.movePrevious();
+                id = javaTS.token().id();
+            }
         }
         return -1;
     }
@@ -812,8 +844,13 @@ class TypingCompletion {
         }
         return null;
     }
-    
-    private static Set<JavaTokenId> STRING_AND_COMMENT_TOKENS = 
EnumSet.of(JavaTokenId.STRING_LITERAL, JavaTokenId.LINE_COMMENT, 
JavaTokenId.JAVADOC_COMMENT, JavaTokenId.BLOCK_COMMENT, 
JavaTokenId.CHAR_LITERAL);
+
+    private static FileObject getFileObject(BaseDocument doc) {
+        DataObject dob = NbEditorUtilities.getDataObject(doc);
+        return dob.getPrimaryFile();
+    }
+
+    private static Set<JavaTokenId> STRING_AND_COMMENT_TOKENS = 
EnumSet.of(JavaTokenId.STRING_LITERAL, JavaTokenId.LINE_COMMENT, 
JavaTokenId.JAVADOC_COMMENT, JavaTokenId.BLOCK_COMMENT, 
JavaTokenId.CHAR_LITERAL, JavaTokenId.MULTILINE_STRING_LITERAL);
 
     private static boolean isStringOrComment(JavaTokenId javaTokenId) {
         return STRING_AND_COMMENT_TOKENS.contains(javaTokenId);
diff --git 
a/java/java.editor/src/org/netbeans/modules/java/editor/imports/ClipboardHandler.java
 
b/java/java.editor/src/org/netbeans/modules/java/editor/imports/ClipboardHandler.java
index 14adc77..0620499 100644
--- 
a/java/java.editor/src/org/netbeans/modules/java/editor/imports/ClipboardHandler.java
+++ 
b/java/java.editor/src/org/netbeans/modules/java/editor/imports/ClipboardHandler.java
@@ -89,6 +89,7 @@ import org.netbeans.api.java.source.GeneratorUtilities;
 import org.netbeans.api.java.source.JavaSource;
 import org.netbeans.api.java.source.ModificationResult;
 import org.netbeans.api.java.source.SourceUtils;
+import static org.netbeans.api.java.source.SourceUtils.isTextBlockSupported;
 import org.netbeans.api.java.source.Task;
 import org.netbeans.api.java.source.WorkingCopy;
 import org.netbeans.api.lexer.TokenHierarchy;
@@ -98,6 +99,7 @@ import org.netbeans.editor.BaseKit;
 import org.netbeans.editor.BaseKit.CutAction;
 import org.netbeans.lib.editor.util.swing.DocumentUtilities;
 import org.netbeans.modules.editor.NbEditorUtilities;
+import org.netbeans.modules.editor.indent.api.IndentUtils;
 import org.openide.DialogDescriptor;
 import org.openide.DialogDisplayer;
 import org.openide.filesystems.FileObject;
@@ -621,46 +623,102 @@ public class ClipboardHandler {
         
         private boolean delegatedImportData(final TransferSupport support) {
             JComponent comp = (JComponent) support.getComponent();
-            if (comp instanceof JTextComponent && 
!support.isDataFlavorSupported(COPY_FROM_STRING_FLAVOR) && 
insideToken((JTextComponent) comp, JavaTokenId.STRING_LITERAL)) {
-                final Transferable t = support.getTransferable();
-                return delegate.importData(comp, new Transferable() {
-                    @Override
-                    public DataFlavor[] getTransferDataFlavors() {
-                        return t.getTransferDataFlavors();
-                    }
+            if (comp instanceof JTextComponent && 
!support.isDataFlavorSupported(COPY_FROM_STRING_FLAVOR) ) {
+                if (insideToken((JTextComponent) comp, 
JavaTokenId.STRING_LITERAL)) {
+                    final Transferable t = support.getTransferable();
+                    return delegate.importData(comp, new Transferable() {
+                        @Override
+                        public DataFlavor[] getTransferDataFlavors() {
+                            return t.getTransferDataFlavors();
+                        }
 
-                    @Override
-                    public boolean isDataFlavorSupported(DataFlavor flavor) {
-                        return t.isDataFlavorSupported(flavor);
-                    }
+                        @Override
+                        public boolean isDataFlavorSupported(DataFlavor 
flavor) {
+                            return t.isDataFlavorSupported(flavor);
+                        }
 
-                    @Override
-                    public Object getTransferData(DataFlavor flavor) throws 
UnsupportedFlavorException, IOException {
-                        Object data = t.getTransferData(flavor);
-                        if (data instanceof String) {
-                            String s = (String) data;
-                            s = s.replace("\\","\\\\"); //NOI18N
-                            s = s.replace("\"","\\\""); //NOI18N
-                            s = s.replace("\r\n","\n"); //NOI18N
-                            s = s.replace("\n","\\n\" +\n\""); //NOI18N
-                            data = s;
-                        } else if (data instanceof Reader) {
-                            BufferedReader br = new 
BufferedReader((Reader)data);
-                            StringBuilder sb = new StringBuilder();
-                            String line;
-                            while ((line = br.readLine()) != null) {
-                                line = line.replace("\\","\\\\"); //NOI18N
-                                line = line.replace("\"","\\\""); //NOI18N
-                                if (sb.length() > 0) {
-                                    sb.append("\\n\" +\n\""); //NOI18N
+                        @Override
+                        public Object getTransferData(DataFlavor flavor) 
throws UnsupportedFlavorException, IOException {
+                            Object data = t.getTransferData(flavor);
+                            if (data instanceof String) {
+                                String s = (String) data;
+                                s = s.replace("\\","\\\\"); //NOI18N
+                                s = s.replace("\"","\\\""); //NOI18N
+                                s = s.replace("\r\n","\n"); //NOI18N
+                                s = s.replace("\n","\\n\" +\n\""); //NOI18N
+                                data = s;
+                            } else if (data instanceof Reader) {
+                                BufferedReader br = new 
BufferedReader((Reader)data);
+                                StringBuilder sb = new StringBuilder();
+                                String line;
+                                while ((line = br.readLine()) != null) {
+                                    line = line.replace("\\","\\\\"); //NOI18N
+                                    line = line.replace("\"","\\\""); //NOI18N
+                                    if (sb.length() > 0) {
+                                        sb.append("\\n\" +\n\""); //NOI18N
+                                    }
+                                    sb.append(line);
                                 }
-                                sb.append(line);
+                                data = new StringReader(sb.toString());
                             }
-                            data = new StringReader(sb.toString());
+                            return data;
                         }
-                        return data;
-                    }
-                });
+                    });
+                } else if 
((isTextBlockSupported(NbEditorUtilities.getFileObject(((JTextComponent)comp).getDocument())))
 && insideToken((JTextComponent) comp, JavaTokenId.MULTILINE_STRING_LITERAL)) {
+                    final Transferable t = support.getTransferable();
+                    return delegate.importData(comp, new Transferable() {
+                        @Override
+                        public DataFlavor[] getTransferDataFlavors() {
+                            return t.getTransferDataFlavors();
+                        }
+
+                        @Override
+                        public boolean isDataFlavorSupported(DataFlavor 
flavor) {
+                            return t.isDataFlavorSupported(flavor);
+                        }
+
+                        @Override
+                        public Object getTransferData(DataFlavor flavor) 
throws UnsupportedFlavorException, IOException {
+                            Object data = t.getTransferData(flavor);
+                            JTextComponent c = (JTextComponent) comp;
+                            int indent = 0;
+                            try {
+                                indent = 
IndentUtils.lineIndent(c.getDocument(), 
IndentUtils.lineStartOffset(c.getDocument(), c.getCaretPosition()));
+                            } catch (BadLocationException ex) {
+                                Exceptions.printStackTrace(ex);
+                            }
+                            if (data instanceof String) {
+                                String s = (String) data;
+                                s = s.replace("\"\"\"","\\\"\"\""); //NOI18N
+                                StringBuilder sb = new StringBuilder("");
+                                for (int i = 0; i < indent; i++) {
+                                     sb.append(" "); //NOI18N
+                                }
+                                String emptySpaces = sb.toString();
+                                s = s.replace("\r\n","\n"); //NOI18N
+                                s = s.replace("\n",System.lineSeparator() + 
emptySpaces); //NOI18N
+                                data = s;
+                            } else if (data instanceof Reader) {
+                                BufferedReader br = new 
BufferedReader((Reader)data);
+                                StringBuilder sb = new StringBuilder();
+                                String line;
+
+                                while ((line = br.readLine()) != null) {
+                                    line = line.replace("\"\"\"", "\\\"\"\""); 
//NOI18N
+                                    if (sb.length() > 0) {
+                                        sb.append(System.lineSeparator()); 
//NOI18N
+                                        for (int i = 0; i < indent; i++) {
+                                            sb.append(" "); //NOI18N
+                                        }
+                                    }
+                                    sb.append(line);
+                                }
+                                data = new StringReader(sb.toString());
+                            }
+                            return data;
+                        }
+                    });
+                }
             }
             return delegate.importData(support);
         }
diff --git 
a/java/java.editor/src/org/netbeans/modules/java/editor/resources/fontsColors.xml
 
b/java/java.editor/src/org/netbeans/modules/java/editor/resources/fontsColors.xml
index 33a873f..668ecb7 100644
--- 
a/java/java.editor/src/org/netbeans/modules/java/editor/resources/fontsColors.xml
+++ 
b/java/java.editor/src/org/netbeans/modules/java/editor/resources/fontsColors.xml
@@ -87,6 +87,7 @@
     <fontcolor name="mod-protected" />
     <fontcolor name="mod-public" />
     <fontcolor name="mod-keyword" default="keyword" />
+    <fontcolor name="mod-unindented-text-block" bgColor="EEDDDD" />
     
     <!--currently not used:-->
 <!--    <fontcolor name="mod-type-parameter-declaration" bgColor="lightGray"/>
diff --git 
a/java/java.editor/src/org/netbeans/modules/java/editor/semantic/ColoringManager.java
 
b/java/java.editor/src/org/netbeans/modules/java/editor/semantic/ColoringManager.java
index 5ffe5de..d5ec0cf 100644
--- 
a/java/java.editor/src/org/netbeans/modules/java/editor/semantic/ColoringManager.java
+++ 
b/java/java.editor/src/org/netbeans/modules/java/editor/semantic/ColoringManager.java
@@ -85,6 +85,7 @@ public final class ColoringManager {
         put("mod-unused", UNUSED);
         put("mod-keyword", KEYWORD);
         put("javadoc-identifier", JAVADOC_IDENTIFIER);
+        put("mod-unindented-text-block", UNINDENTED_TEXT_BLOCK);
     }
     
     private static void put(String coloring, ColoringAttributes... attributes) 
{
diff --git 
a/java/java.editor/src/org/netbeans/modules/java/editor/semantic/SemanticHighlighter.java
 
b/java/java.editor/src/org/netbeans/modules/java/editor/semantic/SemanticHighlighter.java
index 065d8f8..c143fc9 100644
--- 
a/java/java.editor/src/org/netbeans/modules/java/editor/semantic/SemanticHighlighter.java
+++ 
b/java/java.editor/src/org/netbeans/modules/java/editor/semantic/SemanticHighlighter.java
@@ -43,6 +43,7 @@ import 
org.netbeans.modules.java.editor.base.semantic.SemanticHighlighterBase.Er
 import org.netbeans.spi.editor.highlighting.support.OffsetsBag;
 import org.netbeans.spi.editor.hints.ErrorDescription;
 import org.openide.loaders.DataObject;
+import org.openide.util.Pair;
 
 /**
  *
@@ -62,13 +63,12 @@ public class SemanticHighlighter extends 
SemanticHighlighterBase {
         
         public void setErrors(Document doc, List<ErrorDescription> errors, 
List<TreePathHandle> allUnusedImports) {}
         
-        public void setHighlights(final Document doc, final Collection<int[]> 
highlights, Map<int[], String> preText) {
+        public void setHighlights(final Document doc, final 
Collection<Pair<int[], Coloring>> highlights, Map<int[], String> preText) {
             SwingUtilities.invokeLater(new Runnable() {
                 public void run() {
                     OffsetsBag bag = new OffsetsBag(doc);
-                    Coloring unused = 
ColoringAttributes.add(ColoringAttributes.empty(), ColoringAttributes.UNUSED);
-                    for (int[] highlight : highlights) {
-                        bag.addHighlight(highlight[0], highlight[1], 
ColoringManager.getColoringImpl(unused));
+                    for (Pair<int[], Coloring> highlight : highlights) {
+                        bag.addHighlight(highlight.first()[0], 
highlight.first()[1], ColoringManager.getColoringImpl(highlight.second()));
                     }
                     getImportHighlightsBag(doc).setHighlights(bag);
                     
diff --git 
a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java
 
b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java
index 8345f5c..db4d1ff 100644
--- 
a/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java
+++ 
b/java/java.editor/test/unit/src/org/netbeans/modules/editor/java/TypingCompletionUnitTest.java
@@ -23,6 +23,7 @@ import java.awt.EventQueue;
 import java.awt.event.KeyEvent;
 import java.util.prefs.Preferences;
 import java.util.regex.Pattern;
+import javax.lang.model.SourceVersion;
 import javax.swing.JEditorPane;
 import javax.swing.SwingUtilities;
 import javax.swing.text.BadLocationException;
@@ -1239,7 +1240,67 @@ public class TypingCompletionUnitTest extends NbTestCase 
{
         ctx.typeChar(')');
         ctx.assertDocumentTextEquals("//()|)");
     }
-     
+
+    public void testTextBlock1() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        Context ctx = new Context(new JavaKit(), "\"\"|");
+        ctx.typeChar('\"');
+        ctx.assertDocumentTextEquals("\"\"\"\n|\"\"\"");
+    }
+
+    public void testTextBlock2() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        Context ctx = new Context(new JavaKit(), "\"\"\"\n|\"\"\"");
+        ctx.typeChar('\"');
+        ctx.assertDocumentTextEquals("\"\"\"\n\"|\"\"");
+    }
+
+    public void testTextBlock3() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        Context ctx = new Context(new JavaKit(), "\"\"\"\n\"|\"\"");
+        ctx.typeChar('\"');
+        ctx.assertDocumentTextEquals("\"\"\"\n\"\"|\"");
+    }
+
+    public void testTextBlock4() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        Context ctx = new Context(new JavaKit(), "\"\"\"\n\"\"|\"");
+        ctx.typeChar('\"');
+        ctx.assertDocumentTextEquals("\"\"\"\n\"\"\"|");
+    }
+    
+    public void testTextBlock5() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test:
+            return ;
+        }
+        Context ctx = new Context(new JavaKit(), "t(|\"\")");
+        ctx.typeChar('\"');
+        ctx.assertDocumentTextEquals("t(\"\"\"\n  |\"\"\")");
+    } 
+    
     public void testCorrectHandlingOfStringEscapes184059() throws Exception {
         assertTrue(isInsideString("foo\n\"bar|\""));
         assertTrue(isInsideString("foo\n\"bar\\\"|\""));
diff --git 
a/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/imports/ClipboardHandlerTest.java
 
b/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/imports/ClipboardHandlerTest.java
index cab88de..3c43513 100644
--- 
a/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/imports/ClipboardHandlerTest.java
+++ 
b/java/java.editor/test/unit/src/org/netbeans/modules/java/editor/imports/ClipboardHandlerTest.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import java.util.concurrent.Exchanger;
 import java.util.concurrent.TimeUnit;
 import java.util.regex.Pattern;
+import javax.lang.model.SourceVersion;
 import javax.swing.JEditorPane;
 import javax.swing.SwingUtilities;
 import org.netbeans.api.java.lexer.JavaTokenId;
@@ -90,6 +91,20 @@ public class ClipboardHandlerTest extends NbTestCase {
     public void testAnonymousClass() throws Exception {
         copyAndPaste("package test;\nimport java.util.ArrayList;\npublic class 
Test { void t() { |new ArrayList<String>() {};| } }\n", "package test;\npublic 
class Target {\nvoid t() { ^ }\n}", "package test;\n\nimport 
java.util.ArrayList;\n\npublic class Target {\nvoid t() { new 
ArrayList<String>() {}; }\n}");
     }
+    
+    public void testCopyIntoTextBlock() throws Exception {
+        copyAndPaste("|List l1;\nList l2;\nList l3;\n\n| ", "package 
test;\npublic class Target {\nString s = \"\"\"\n^\"\"\"\n}", "package 
test;\npublic class Target {\nString s = \"\"\"\nList l1;\nList l2;\nList 
l3;\n\n\"\"\"\n}");
+    }
+    
+    public void testCopyTextBlockIntoTextBlock() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        copyAndPaste("|\"\"\"\nList l1;\"\"\"| ", "package test;\npublic class 
Target {\nString s = \"\"\"\ntest^ block\n\"\"\"\n}", "package test;\npublic 
class Target {\nString s = \"\"\"\ntest\\\"\"\"\nList l1;\\\"\"\" 
block\n\"\"\"\n}");
+    }
 
     private void copyAndPaste(String from, final String to, String golden) 
throws Exception {
         final int pastePos = to.indexOf('^');
diff --git 
a/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToTextBlock.java
 
b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToTextBlock.java
new file mode 100644
index 0000000..35f0917
--- /dev/null
+++ 
b/java/java.hints/src/org/netbeans/modules/java/hints/jdk/ConvertToTextBlock.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.java.hints.jdk;
+
+import com.sun.source.tree.BinaryTree;
+import com.sun.source.tree.LiteralTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.Tree.Kind;
+import com.sun.source.util.TreePath;
+import java.util.List;
+import org.netbeans.api.java.queries.CompilerOptionsQuery;
+import org.netbeans.api.java.source.CompilationInfo;
+import org.netbeans.spi.editor.hints.ErrorDescription;
+import org.netbeans.spi.editor.hints.Fix;
+import org.netbeans.spi.java.hints.ConstraintVariableType;
+import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
+import org.netbeans.spi.java.hints.Hint;
+import org.netbeans.spi.java.hints.HintContext;
+import org.netbeans.spi.java.hints.JavaFix;
+import org.netbeans.spi.java.hints.TriggerPattern;
+import org.netbeans.spi.java.hints.TriggerTreeKind;
+import org.openide.util.NbBundle.Messages;
+
+@Hint(displayName = "#DN_ConvertToTextBlock", description = 
"#DESC_ConvertToTextBlock", category="rules15",
+      minSourceVersion = "13")
+@Messages({
+    "DN_ConvertToTextBlock=Convert to Text Block",
+    "DESC_ConvertToTextBlock=Convert to Text Block"
+})
+public class ConvertToTextBlock {
+
+    @TriggerTreeKind(Kind.PLUS)
+    @Messages("ERR_ConvertToTextBlock=Can be converted to text block")
+    public static ErrorDescription computeWarning(HintContext ctx) {
+        if 
(!CompilerOptionsQuery.getOptions(ctx.getInfo().getFileObject()).getArguments().contains("--enable-preview"))
+            return null;
+        if (ctx.getPath().getParentPath() != null && 
getTextOrNull(ctx.getPath().getParentPath()) != null) {
+            return null;
+        }
+        String text = getTextOrNull(ctx.getPath());
+        if (text == null) {
+            return null;
+        }
+        Fix fix = new FixImpl(ctx.getInfo(), ctx.getPath(), 
text).toEditorFix();
+        return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), 
Bundle.ERR_ConvertToTextBlock(), fix);
+    }
+
+    private static String getTextOrNull(TreePath tp) {
+        StringBuilder text = new StringBuilder();
+        Tree current = tp.getLeaf();
+        while (current.getKind() == Kind.PLUS) {
+            BinaryTree bt = (BinaryTree) current;
+            if (bt.getRightOperand().getKind() == Kind.STRING_LITERAL) {
+                text.insert(0, ((LiteralTree) 
bt.getRightOperand()).getValue());
+            } else {
+                return null;
+            }
+            current = bt.getLeftOperand();
+        }
+        if (current.getKind() == Kind.STRING_LITERAL) {
+            text.insert(0, ((LiteralTree) current).getValue());
+        } else {
+            return null;
+        }
+        String textString = text.toString();
+        if (!textString.contains("\n")) {
+            return null;
+        }
+        return textString;
+    }
+
+    private static final class FixImpl extends JavaFix {
+
+        private final String text;
+
+        public FixImpl(CompilationInfo info, TreePath tp, String text) {
+            super(info, tp);
+            this.text = text;
+        }
+
+        @Override
+        @Messages("FIX_ConvertToTextBlock=Convert to text block")
+        protected String getText() {
+            return Bundle.FIX_ConvertToTextBlock();
+        }
+
+        @Override
+        protected void performRewrite(TransformationContext ctx) {
+            ctx.getWorkingCopy().rewrite(ctx.getPath().getLeaf(), 
ctx.getWorkingCopy().getTreeMaker().Literal(text.split("\n", -1)));
+            //perform the required transformation
+        }
+    }
+}
diff --git 
a/java/java.hints/src/org/netbeans/modules/java/hints/resources/jdk13.properties
 
b/java/java.hints/src/org/netbeans/modules/java/hints/resources/jdk13.properties
new file mode 100644
index 0000000..532a56d
--- /dev/null
+++ 
b/java/java.hints/src/org/netbeans/modules/java/hints/resources/jdk13.properties
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+display.name=Migrate to JDK 13
diff --git 
a/java/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml 
b/java/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml
index 689379e..8e70d6a 100644
--- a/java/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml
+++ b/java/java.hints/src/org/netbeans/modules/java/hints/resources/layer.xml
@@ -398,11 +398,27 @@
                 <file 
name="org.netbeans.modules.java.hints.jdk.ConvertToVarHint.properties" 
url="enabled.properties"/>
                 <file 
name="org.netbeans.modules.java.hints.jdk.ConvertSwitchToRuleSwitch.properties" 
url="enabled.properties"/>
             </folder>
+            <folder name="rule_config_jdk13">
+                <file name="Javac_canUseDiamond.properties" 
url="enabled.properties"/>
+                <file name="Javac_canUseLambda.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.IteratorToFor.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.UnnecessaryUnboxing.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.ConvertToARM.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.JoinCatches.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.Tiny.containsForIndexOf.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.StaticImport.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.ConvertToStringSwitch.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.UnnecessaryBoxing.run.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.ConvertToVarHint.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.ConvertSwitchToRuleSwitch.properties" 
url="enabled.properties"/>
+                <file 
name="org.netbeans.modules.java.hints.jdk.ConvertToTextBlock.properties" 
url="enabled.properties"/>
+            </folder>
             <folder name="ui">
                 <file name="rule_config_default.properties" 
url="nbresloc:/org/netbeans/modules/java/hints/resources/default.properties"/>
                 <file name="rule_config_jdk8.properties" 
url="nbresloc:/org/netbeans/modules/java/hints/resources/jdk8.properties"/>
                 <file name="rule_config_jdk11.properties" 
url="nbresloc:/org/netbeans/modules/java/hints/resources/jdk11.properties"/>
                 <file name="rule_config_jdk12.properties" 
url="nbresloc:/org/netbeans/modules/java/hints/resources/jdk12.properties"/>
+                <file name="rule_config_jdk13.properties" 
url="nbresloc:/org/netbeans/modules/java/hints/resources/jdk13.properties"/>
             </folder>
         </folder></folder></folder></folder></folder>
     </folder>
diff --git 
a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertToTextBlockTest.java
 
b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertToTextBlockTest.java
new file mode 100644
index 0000000..91749bd
--- /dev/null
+++ 
b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/jdk/ConvertToTextBlockTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.java.hints.jdk;
+
+import javax.lang.model.SourceVersion;
+import org.junit.Test;
+import org.netbeans.modules.java.hints.test.api.HintTest;
+
+public class ConvertToTextBlockTest {
+
+    @Test
+    public void testFixWorking() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        HintTest.create()
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    public static void main(String[] args) {\n" +
+                       "        assert args[0].equals(\"{\\n\" +\n" +
+                       "                              \"    int i = 0;\\n\" 
+\n" +
+                       "                              \"}\");\n" +
+                       "    }\n" +
+                       "}\n")
+                .sourceLevel(SourceVersion.latest().name())
+                .options("--enable-preview")
+                .run(ConvertToTextBlock.class)
+                .findWarning("3:30-3:37:verifier:" + 
Bundle.ERR_ConvertToTextBlock())
+                .applyFix()
+                .assertCompilable()
+                //TODO: change to match expected output
+                .assertOutput("package test;\n" +
+                        "public class Test {\n" +
+                        "    public static void main(String[] args) {\n" +
+                        "        assert args[0].equals(\"\"\"\n" +
+                        "                              {\n" +
+                        "                                  int i = 0;\n" +
+                        "                              }\"\"\");\n" +
+                        "    }\n" +
+                        "}\n");
+    }
+
+    @Test
+    public void testNewLineAtEnd() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        HintTest.create()
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    public static void main(String[] args) {\n" +
+                       "        assert args[0].equals(\"{\\n\" +\n" +
+                       "                              \"    int i = 0;\\n\" 
+\n" +
+                       "                              \"}\\n\");\n" +
+                       "    }\n" +
+                       "}\n")
+                .sourceLevel(SourceVersion.latest().name())
+                .options("--enable-preview")
+                .run(ConvertToTextBlock.class)
+                .findWarning("3:30-3:37:verifier:" + 
Bundle.ERR_ConvertToTextBlock())
+                .applyFix()
+                .assertCompilable()
+                //TODO: change to match expected output
+                .assertOutput("package test;\n" +
+                        "public class Test {\n" +
+                        "    public static void main(String[] args) {\n" +
+                        "        assert args[0].equals(\"\"\"\n" +
+                        "                              {\n" +
+                        "                                  int i = 0;\n" +
+                        "                              }\n" +
+                        "                              \"\"\");\n" +
+                        "    }\n" +
+                        "}\n");
+    }
+
+    @Test
+    public void testNewLinesAtEnd() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        HintTest.create()
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    public static void main(String[] args) {\n" +
+                       "        assert args[0].equals(\"{\\n\" +\n" +
+                       "                              \"    int i = 0;\\n\" 
+\n" +
+                       "                              \"}\\n\\n\");\n" +
+                       "    }\n" +
+                       "}\n")
+                .sourceLevel(SourceVersion.latest().name())
+                .options("--enable-preview")
+                .run(ConvertToTextBlock.class)
+                .findWarning("3:30-3:37:verifier:" + 
Bundle.ERR_ConvertToTextBlock())
+                .applyFix()
+                .assertCompilable()
+                .assertOutput("package test;\n" +
+                        "public class Test {\n" +
+                        "    public static void main(String[] args) {\n" +
+                        "        assert args[0].equals(\"\"\"\n" +
+                        "                              {\n" +
+                        "                                  int i = 0;\n" +
+                        "                              }\n" +
+                        "                              \n"  +
+                        "                              \"\"\");\n" +
+                        "    }\n" +
+                        "}\n");
+    }
+
+    @Test
+    public void testOnlyLiterals() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test
+            return ;
+        }
+        HintTest.create()
+                .input("package test;\n" +
+                       "public class Test {\n" +
+                       "    public int test() {\n" +
+                       "        return c() + c();\n" +
+                       "    }\n" +
+                       "    private int c() { return 0; }\n" +
+                       "}\n")
+                .sourceLevel(SourceVersion.latest().name())
+                .options("--enable-preview")
+                .run(ConvertToTextBlock.class)
+                .assertWarnings();
+    }
+}
diff --git a/java/java.lexer/apichanges.xml b/java/java.lexer/apichanges.xml
index 77a4f2a..c8ceebf 100644
--- a/java/java.lexer/apichanges.xml
+++ b/java/java.lexer/apichanges.xml
@@ -83,6 +83,18 @@ is the proper place.
 
     <!-- ACTUAL CHANGES BEGIN HERE: -->
     <changes>
+        <change id="RawStringLiteral">
+             <api name="general"/>
+             <summary>Added RAW_STRING_LITERAL JavaTokenKind</summary>
+             <version major="1" minor="41"/>
+             <date day="22" month="4" year="2018"/>
+             <author login="jlahoda"/>
+            <compatibility addition="yes" binary="compatible" deletion="no" 
deprecation="no" modification="no" semantic="compatible" source="compatible"/>
+             <description>
+                 Added JavaTokenId.RAW_STRING_LITERAL.
+             </description>
+             <class package="org.netbeans.api.java.lexer" name="JavaTokenId"/>
+        </change>
         <change id="Modules">
              <api name="general"/>
              <summary>Added tokens used in module-info.java files</summary>
diff --git a/java/java.lexer/src/org/netbeans/api/java/lexer/JavaTokenId.java 
b/java/java.lexer/src/org/netbeans/api/java/lexer/JavaTokenId.java
index 7cf0fbb..17602a5 100644
--- a/java/java.lexer/src/org/netbeans/api/java/lexer/JavaTokenId.java
+++ b/java/java.lexer/src/org/netbeans/api/java/lexer/JavaTokenId.java
@@ -127,6 +127,8 @@ public enum JavaTokenId implements TokenId {
     DOUBLE_LITERAL(null, "number"),
     CHAR_LITERAL(null, "character"),
     STRING_LITERAL(null, "string"),
+    /**@since 1.41*/
+    MULTILINE_STRING_LITERAL(null, "string"),
     
     TRUE("true", "literal"),
     FALSE("false", "literal"),
diff --git a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java 
b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java
index d0a598d..8a2b651 100644
--- a/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java
+++ b/java/java.lexer/src/org/netbeans/lib/java/lexer/JavaLexer.java
@@ -170,19 +170,41 @@ public class JavaLexer implements Lexer<JavaTokenId> {
                     return token(JavaTokenId.ERROR);
                 case '"': // string literal
                     if (lookupId == null) lookupId = 
JavaTokenId.STRING_LITERAL;
-                    while (true)
+                    while (true) {
                         switch (nextChar()) {
                             case '"': // NOI18N
+                                if (this.version >= 13) {
+                                    String text = input.readText().toString();
+                                    if (text.length() == 2) {
+                                        if (nextChar() != '"') {
+                                            input.backup(1); //TODO: EOF???
+                                            return token(lookupId);
+                                        }
+                                        lookupId = 
JavaTokenId.MULTILINE_STRING_LITERAL;
+                                    }
+                                    if (lookupId == 
JavaTokenId.MULTILINE_STRING_LITERAL) {
+                                        if (text.endsWith("\"\"\"") && 
!text.endsWith("\\\"\"\"") && text.length() > 6) {
+                                            return token(lookupId);
+                                        } else {
+                                            break;
+                                        }
+                                    }
+                                }
+                                
                                 return token(lookupId);
                             case '\\':
                                 nextChar();
                                 break;
                             case '\r': consumeNewline();
                             case '\n':
+                                if (lookupId == 
JavaTokenId.MULTILINE_STRING_LITERAL && this.version >= 13) {
+                                    break;
+                                }
                             case EOF:
                                 return tokenFactory.createToken(lookupId, 
//XXX: \n handling for exotic identifiers?
                                         input.readLength(), PartType.START);
                         }
+                    }
 
                 case '\'': // char literal
                     while (true)
diff --git 
a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java
 
b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java
index b87cbdd..757ae28 100644
--- 
a/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java
+++ 
b/java/java.lexer/test/unit/src/org/netbeans/lib/java/lexer/JavaLexerBatchTest.java
@@ -106,12 +106,13 @@ public class JavaLexerBatchTest extends TestCase {
     }
     
     public void testStringLiterals() {
-        String text = "\"\" \"a\"\"\" \"\\\"\" \"\\\\\" \"\\\\\\\"\" \"\\n\" 
\"a";
+        String text = "\"\" \"a\" \"\" \"\\\"\" \"\\\\\" \"\\\\\\\"\" \"\\n\" 
\"a";
         TokenHierarchy<?> hi = TokenHierarchy.create(text, 
JavaTokenId.language());
         TokenSequence<?> ts = hi.tokenSequence();
         LexerTestUtilities.assertNextTokenEquals(ts, 
JavaTokenId.STRING_LITERAL, "\"\"");
         LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " 
");
         LexerTestUtilities.assertNextTokenEquals(ts, 
JavaTokenId.STRING_LITERAL, "\"a\"");
+        LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " 
");
         LexerTestUtilities.assertNextTokenEquals(ts, 
JavaTokenId.STRING_LITERAL, "\"\"");
         LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " 
");
         LexerTestUtilities.assertNextTokenEquals(ts, 
JavaTokenId.STRING_LITERAL, "\"\\\"\"");
@@ -697,4 +698,36 @@ public class JavaLexerBatchTest extends TestCase {
         LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " 
");
     }
 
+    private void enableRawStringLiterals(InputAttributes attr) {
+        attr.setValue(JavaTokenId.language(), "version", (Supplier<String>) () 
-> {
+            return "13";
+        }, true);
+    }
+
+    public void testMultilineLiteral() {
+        String text = "\"\"\"\n2\"3\n4\\\"\"\"5\"\"\\\"6\n7\"\"\" 
\"\"\"wrong\"\"\" \"\"\"\nbla\n";
+        InputAttributes attr = new InputAttributes();
+        enableRawStringLiterals(attr);
+        TokenHierarchy<?> hi = TokenHierarchy.create(text, false, 
JavaTokenId.language(), EnumSet.noneOf(JavaTokenId.class), attr);
+        TokenSequence<?> ts = hi.tokenSequence();
+
+        LexerTestUtilities.assertNextTokenEquals(ts, 
JavaTokenId.MULTILINE_STRING_LITERAL, 
"\"\"\"\n2\"3\n4\\\"\"\"5\"\"\\\"6\n7\"\"\"");
+        LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " 
");
+        LexerTestUtilities.assertNextTokenEquals(ts, 
JavaTokenId.MULTILINE_STRING_LITERAL, "\"\"\"wrong\"\"\"");
+        LexerTestUtilities.assertNextTokenEquals(ts, JavaTokenId.WHITESPACE, " 
");
+        LexerTestUtilities.assertNextTokenEquals(ts, 
JavaTokenId.MULTILINE_STRING_LITERAL, "\"\"\"\nbla\n");
+        assertFalse(ts.moveNext());
+    }
+
+    public void testTrailing() {
+        String text = "\"\"";
+        InputAttributes attr = new InputAttributes();
+        enableRawStringLiterals(attr);
+        TokenHierarchy<?> hi = TokenHierarchy.create(text, false, 
JavaTokenId.language(), EnumSet.noneOf(JavaTokenId.class), attr);
+        TokenSequence<?> ts = hi.tokenSequence();
+
+        LexerTestUtilities.assertNextTokenEquals(ts, 
JavaTokenId.STRING_LITERAL, "\"\"");
+        assertFalse(ts.moveNext());
+    }
+
 }
diff --git 
a/java/java.source.base/src/org/netbeans/api/java/source/SourceUtils.java 
b/java/java.source.base/src/org/netbeans/api/java/source/SourceUtils.java
index 8e136e2..fa7bbb4 100644
--- a/java/java.source.base/src/org/netbeans/api/java/source/SourceUtils.java
+++ b/java/java.source.base/src/org/netbeans/api/java/source/SourceUtils.java
@@ -80,13 +80,16 @@ import javax.tools.JavaFileObject;
 
 import org.netbeans.api.annotations.common.CheckForNull;
 import org.netbeans.api.annotations.common.NonNull;
+import org.netbeans.api.annotations.common.NullAllowed;
 import org.netbeans.api.editor.mimelookup.MimeLookup;
 import org.netbeans.api.editor.mimelookup.MimePath;
 import org.netbeans.api.java.classpath.ClassPath;
 import org.netbeans.api.java.classpath.JavaClassPathConstants;
 import org.netbeans.api.java.lexer.JavaTokenId;
+import org.netbeans.api.java.queries.CompilerOptionsQuery;
 import org.netbeans.api.java.queries.JavadocForBinaryQuery;
 import org.netbeans.api.java.queries.SourceForBinaryQuery;
+import org.netbeans.api.java.queries.SourceLevelQuery;
 import org.netbeans.api.java.source.ClasspathInfo.PathKind;
 import org.netbeans.api.java.source.JavaSource.Phase;
 import org.netbeans.api.java.source.matching.Matcher;
@@ -120,6 +123,7 @@ import 
org.netbeans.spi.java.classpath.support.ClassPathSupport;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileUtil;
 import org.openide.filesystems.URLMapper;
+import org.openide.modules.SpecificationVersion;
 import org.openide.util.Exceptions;
 import org.openide.util.Lookup;
 import org.openide.util.Pair;
@@ -563,7 +567,27 @@ public class SourceUtils {
         }
         return null;        
     }
-    
+
+    /**
+     * @since 13.0
+     */
+    public static boolean isTextBlockSupported(
+            @NullAllowed FileObject fileObject) {
+        SpecificationVersion supportedVer = new SpecificationVersion("13"); 
//NOI18N
+
+        SpecificationVersion runtimeVer = new 
SpecificationVersion(System.getProperty("java.specification.version")); //NOI18N
+        if (runtimeVer.compareTo(supportedVer) >= 0) {
+            if (fileObject != null) {
+                SpecificationVersion sourceVer = new 
SpecificationVersion(SourceLevelQuery.getSourceLevel(fileObject));
+                if (sourceVer.compareTo(supportedVer) < 0) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
     private static FileObject findSourceForBinary(FileObject binaryRoot, 
FileObject binary, String signature, String pkgName, String className, boolean 
isPkg) throws IOException {
         FileObject[] sourceRoots = 
SourceForBinaryQuery.findSourceRoots(binaryRoot.toURL()).getRoots();            
            
         ClassPath sourcePath = ClassPathSupport.createClassPath(sourceRoots);
diff --git 
a/java/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java
 
b/java/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java
index 0ee4288..1e89e99 100644
--- 
a/java/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java
+++ 
b/java/java.source.base/src/org/netbeans/modules/java/source/builder/TreeFactory.java
@@ -507,6 +507,8 @@ public class TreeFactory {
                 return make.at(NOPOS).Literal(TypeTag.INT, ((Byte) 
value).intValue());
             if (value instanceof Short)
                 return make.at(NOPOS).Literal(TypeTag.INT, ((Short) 
value).intValue());
+            if (value instanceof String[])
+                return make.at(NOPOS).Literal(TypeTag.CLASS, value);
             // workaround for making NULL_LITERAL kind.
             if (value == null) {
                 return make.at(NOPOS).Literal(TypeTag.BOT, value);
diff --git 
a/java/java.source.base/src/org/netbeans/modules/java/source/pretty/CharBuffer.java
 
b/java/java.source.base/src/org/netbeans/modules/java/source/pretty/CharBuffer.java
index 0f9a739..14eff95 100644
--- 
a/java/java.source.base/src/org/netbeans/modules/java/source/pretty/CharBuffer.java
+++ 
b/java/java.source.base/src/org/netbeans/modules/java/source/pretty/CharBuffer.java
@@ -235,17 +235,29 @@ public final class CharBuffer {
     public void addTrimObserver(TrimBufferObserver o) {
         trimObservers.add(o);
     }
+
     public void nlTerm() {
+       nlTerm(true);
+    }
+
+    public void nlTerm(boolean trim) {
        if(hasMargin())
            needSpace();
        else {
            int t = used;
            if (t <= 0) return;
-           while (t > 0 && chars[t-1] <= ' ') t--; // NOI18N
-            trimTo(t);
+            if (trim) {
+                while (t > 0 && chars[t-1] <= ' ') t--; // NOI18N
+                trimTo(t);
+            }
            append('\n'); // NOI18N
        }
     }
+
+    public void nlTermNoTrim() {
+       nlTerm(false);
+    }
+
     public void toLineStart() {
        if(hasMargin())
            needSpace();
diff --git 
a/java/java.source.base/src/org/netbeans/modules/java/source/pretty/VeryPretty.java
 
b/java/java.source.base/src/org/netbeans/modules/java/source/pretty/VeryPretty.java
index 5231dbc..66c0043 100644
--- 
a/java/java.source.base/src/org/netbeans/modules/java/source/pretty/VeryPretty.java
+++ 
b/java/java.source.base/src/org/netbeans/modules/java/source/pretty/VeryPretty.java
@@ -102,6 +102,7 @@ import org.netbeans.api.java.source.CodeStyle;
 import org.netbeans.api.java.source.CodeStyle.*;
 import org.netbeans.api.java.source.Comment;
 import org.netbeans.api.java.source.Comment.Style;
+import static org.netbeans.api.java.source.SourceUtils.isTextBlockSupported;
 import org.netbeans.api.lexer.TokenHierarchy;
 import org.netbeans.api.lexer.TokenSequence;
 import org.netbeans.modules.java.source.TreeShims;
@@ -240,6 +241,10 @@ public final class VeryPretty extends JCTree.Visitor 
implements DocTreeVisitor<V
        out.nlTerm();
     }
 
+    private void newLineNoTrim() {
+        out.nlTermNoTrim();
+    }
+
     public void blankline() {
         out.blanklines(1);
     }
@@ -1873,7 +1878,34 @@ public final class VeryPretty extends JCTree.Visitor 
implements DocTreeVisitor<V
                  "\'");
            break;
           case CLASS:
-           print("\"" + quote((String) tree.value, '\'') + "\"");
+             if (tree.value instanceof String) {
+                 print("\"" + quote((String) tree.value, '\'') + "\"");
+             } else if (isTextBlockSupported(null) && tree.value instanceof 
String[]) {
+                 int indent = out.col;
+                 print("\"\"\"");
+                 newline();
+                 String[] lines = (String[]) tree.value;
+                 for (int i = 0; i < lines.length; i++) {
+                     out.toCol(indent);
+                     String line = lines[i];
+                     for (int c = 0; c < line.length(); c++) {
+                         if (line.startsWith("\"\"\"", c)) {
+                             print('\\');
+                             print('"');
+                         } else if (line.charAt(c) != '\'' && line.charAt(c) 
!= '"') {
+                             print(Convert.quote(line.charAt(c)));
+                         } else {
+                             print(line.charAt(c));
+                         }
+                     }
+                     if (i + 1 < lines.length) {
+                         newLineNoTrim();
+                     }
+                 }
+                 print("\"\"\"");
+             } else {
+                 throw new IllegalStateException("Incorrect literal value.");
+             }
            break;
           case BOOLEAN:
             print(tree.getValue().toString());
diff --git 
a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reindenter.java
 
b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reindenter.java
index 597c093..092df1c 100644
--- 
a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reindenter.java
+++ 
b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reindenter.java
@@ -68,10 +68,12 @@ import javax.tools.JavaFileObject;
 import com.sun.tools.javac.parser.ParserFactory;
 import com.sun.tools.javac.util.Log;
 import java.util.ArrayList;
+import java.util.Arrays;
 import org.netbeans.api.java.lexer.JavaTokenId;
 import org.netbeans.api.java.source.CodeStyle;
 import org.netbeans.api.lexer.TokenHierarchy;
 import org.netbeans.api.lexer.TokenSequence;
+import org.netbeans.modules.editor.indent.api.IndentUtils;
 import org.netbeans.modules.editor.indent.spi.Context;
 import org.netbeans.modules.editor.indent.spi.Context.Region;
 import org.netbeans.modules.editor.indent.spi.ExtraLock;
@@ -116,6 +118,7 @@ public class Reindenter implements IndentTask {
         for (Region region : context.indentRegions()) {
             if (initRegionData(region)) {
                 HashSet<Integer> linesToAddStar = new HashSet<Integer>();
+                Map<Integer, Integer> oldIndents = new HashMap<>();
                 LinkedList<Integer> startOffsets = getStartOffsets(region);
                 for (ListIterator<Integer> it = startOffsets.listIterator(); 
it.hasNext();) {
                     int startOffset = it.next();
@@ -151,6 +154,17 @@ public class Reindenter implements IndentTask {
                             if (!blockCommentLine.startsWith("*")) { //NOI18N
                                 linesToAddStar.add(startOffset);
                             }
+                        } else if (ts.token().id() == 
JavaTokenId.MULTILINE_STRING_LITERAL) {
+                            String tokenText = ts.token().text().toString();
+                            String[] lines = tokenText.split("\n");
+                            int indent = Arrays.stream(lines, 1, lines.length)
+                                               .mapToInt(this::leadingIndent)
+                                               .min()
+                                               .orElse(0);
+                            int initialLineStartOffset = 
context.lineStartOffset(ts.offset());
+                            int indentUpdate = 
newIndents.getOrDefault(initialLineStartOffset, 0);
+                            oldIndents.put(startOffset, indent);
+                            newIndents.put(startOffset, ts.offset() - 
initialLineStartOffset + indentUpdate);
                         } else {
                             if (delta == 0 && ts.moveNext() && ts.token().id() 
== JavaTokenId.LINE_COMMENT) {
                                 newIndents.put(startOffset, 0);
@@ -168,7 +182,12 @@ public class Reindenter implements IndentTask {
                         context.document().insertString(startOffset, "* ", 
null); //NOI18N
                     }
                     if (newIndent != null) {
-                        context.modifyIndent(startOffset, newIndent);
+                        Integer oldIndent = oldIndents.get(startOffset);
+                        if (oldIndent != null) {
+                            context.modifyIndent(startOffset, oldIndent, 
IndentUtils.createIndentString(newIndent, true, -1));
+                        } else {
+                            context.modifyIndent(startOffset, newIndent);
+                        }
                     }
                     if (!startOffsets.isEmpty()) {
                         char c;
@@ -185,6 +204,19 @@ public class Reindenter implements IndentTask {
         }
     }
 
+    private int leadingIndent(String line) {
+        int indent = 0;
+
+        for (int i = 0; i < line.length(); i++) { //TODO: code points
+            if (Character.isWhitespace(line.charAt(i)))
+                indent++;
+            else
+                break;
+        }
+
+        return indent;
+    }
+
     @Override
     public ExtraLock indentLock() {
         return null;
diff --git 
a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/LiteralTest.java
 
b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/LiteralTest.java
index 4f07d54..6feed6a 100644
--- 
a/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/LiteralTest.java
+++ 
b/java/java.source.base/test/unit/src/org/netbeans/api/java/source/gen/LiteralTest.java
@@ -25,6 +25,7 @@ import com.sun.source.tree.MethodInvocationTree;
 import com.sun.source.tree.MethodTree;
 import com.sun.source.tree.VariableTree;
 import java.io.File;
+import javax.lang.model.SourceVersion;
 import org.netbeans.api.java.source.Task;
 import org.netbeans.api.java.source.JavaSource;
 import org.netbeans.api.java.source.JavaSource.Phase;
@@ -168,6 +169,93 @@ public class LiteralTest extends GeneratorTestMDRCompat {
         assertEquals(golden, res);
     }
 
+    public void testTextBlocksNew() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test:
+            return ;
+        }
+        testFile = new File(getWorkDir(), "Test.java");
+        TestUtilities.copyStringToFile(testFile,
+            "package hierbas.del.litoral;\n" +
+            "\n" +
+            "public class Test {\n" +
+            "    public static final String C;\n" +
+            "}\n"
+            );
+        String golden =
+            "package hierbas.del.litoral;\n" +
+            "\n" +
+            "public class Test {\n" +
+            "    public static final String C = \"\"\"\n" +
+            "                                   line \"1\n" +
+            "                                   line\\\"\\\"\\\"\"\"2\"\n" +
+            "                                   line\\n3\"\"\";\n" +
+            "}\n";
+        JavaSource testSource = 
JavaSource.forFileObject(FileUtil.toFileObject(testFile));
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws 
java.io.IOException {
+                workingCopy.toPhase(Phase.RESOLVED);
+                TreeMaker make = workingCopy.getTreeMaker();
+
+                ClassTree clazz = (ClassTree) 
workingCopy.getCompilationUnit().getTypeDecls().get(0);
+                VariableTree var = (VariableTree) clazz.getMembers().get(1);
+                LiteralTree val = make.Literal(new String[] {"line \"1",
+                                                             
"line\"\"\"\"\"2\"",
+                                                             "line\n3"});
+                VariableTree nue = make.setInitialValue(var, val);
+                workingCopy.rewrite(var, nue);
+            }
+
+        };
+        testSource.runModificationTask(task).commit();
+        String res = TestUtilities.copyFileToString(testFile);
+        System.err.println(res);
+        assertEquals(golden, res);
+    }
+
+    public void testTextBlocksReplace() throws Exception {
+        testFile = new File(getWorkDir(), "Test.java");
+        TestUtilities.copyStringToFile(testFile,
+            "package hierbas.del.litoral;\n" +
+            "\n" +
+            "public class Test {\n" +
+            "    public static final String C = \"\"\"\n" +
+            "                                   old\"\"\";\n" +
+            "}\n"
+            );
+        String golden =
+            "package hierbas.del.litoral;\n" +
+            "\n" +
+            "public class Test {\n" +
+            "    public static final String C = \"\"\"\n" +
+            "                                   new\n" +
+            "                                   \"\"\";\n" +
+            "}\n";
+        JavaSource testSource = 
JavaSource.forFileObject(FileUtil.toFileObject(testFile));
+        Task<WorkingCopy> task = new Task<WorkingCopy>() {
+
+            public void run(WorkingCopy workingCopy) throws 
java.io.IOException {
+                workingCopy.toPhase(Phase.RESOLVED);
+                TreeMaker make = workingCopy.getTreeMaker();
+
+                ClassTree clazz = (ClassTree) 
workingCopy.getCompilationUnit().getTypeDecls().get(0);
+                VariableTree var = (VariableTree) clazz.getMembers().get(1);
+                LiteralTree val = make.Literal(new String[] {"new",
+                                                             ""});
+                VariableTree nue = make.setInitialValue(var, val);
+                workingCopy.rewrite(var, nue);
+            }
+
+        };
+        testSource.runModificationTask(task).commit();
+        String res = TestUtilities.copyFileToString(testFile);
+        System.err.println(res);
+        assertEquals(golden, res);
+    }
+
     String getGoldenPckg() {
         return "";
     }
diff --git 
a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/ReindenterTest.java
 
b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/ReindenterTest.java
index 4c49ae7..3848fb4 100644
--- 
a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/ReindenterTest.java
+++ 
b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/ReindenterTest.java
@@ -20,6 +20,7 @@ package org.netbeans.modules.java.source.save;
 
 import java.util.prefs.Preferences;
 import java.util.regex.Pattern;
+import javax.lang.model.SourceVersion;
 import javax.swing.text.Document;
 import javax.swing.text.PlainDocument;
 import org.netbeans.api.editor.mimelookup.MimeLookup;
@@ -1943,7 +1944,39 @@ public class ReindenterTest extends NbTestCase {
                 "package t;\npublic class T {\n    public void op() {\n        
int a = switch(get())\n        {\n        }\n    }\n}\n");
     }
 
-    
+    public void testNewLineIndentationTextBlock1() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test:
+            return ;
+        }
+        performNewLineIndentationTest("package t;\npublic class T {\n    
private final String s = \"\"\"|\n}\n",
+                "package t;\npublic class T {\n    private final String s = 
\"\"\"\n                             \n}\n");
+    }
+
+    public void testSpanIndentationTextBlock1() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test:
+            return ;
+        }
+        performSpanIndentationTest("package t;\npublic class T {\n|private 
final String s = \"\"\"\n\"\"\";|\n}\n",
+                "package t;\npublic class T {\n    private final String s = 
\"\"\"\n                             \"\"\";\n}\n");
+    }
+
+    public void testSpanIndentationTextBlock2() throws Exception {
+        try {
+            SourceVersion.valueOf("RELEASE_13");
+        } catch (IllegalArgumentException ex) {
+            //OK, skip test:
+            return ;
+        }
+        performSpanIndentationTest("package t;\npublic class T {\n|private 
final String s = \"\"\"\n1\n  2\n 3\n\"\"\";|\n}\n",
+                "package t;\npublic class T {\n    private final String s = 
\"\"\"\n                             1\n                               2\n      
                        3\n                             \"\"\";\n}\n");
+    }
+
     private void performNewLineIndentationTest(String code, String golden) 
throws Exception {
         int pos = code.indexOf('|');
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@netbeans.apache.org
For additional commands, e-mail: commits-h...@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists

Reply via email to