Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

test - jdk/amber/string tapas #28

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
12 changes: 12 additions & 0 deletions ide/editor.indent/apichanges.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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"/>
Expand Down
2 changes: 1 addition & 1 deletion ide/editor.indent/manifest.mf
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ OpenIDE-Module-Layer: org/netbeans/modules/editor/indent/resources/layer.xml
AutoUpdate-Show-In-Client: false
OpenIDE-Module-Recommends: org.netbeans.modules.editor.indent.spi.CodeStylePreferences.Provider
OpenIDE-Module-Provides: org.netbeans.templates.IndentEngine
OpenIDE-Module-Specification-Version: 1.48
OpenIDE-Module-Specification-Version: 1.49
Original file line number Diff line number Diff line change
Expand Up @@ -170,23 +170,43 @@ public void modifyIndent(int lineStartOffset, int newIndent) throws BadLocationE
}

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);
}
}
}
Expand Down
51 changes: 37 additions & 14 deletions ide/editor.lib/src/org/netbeans/editor/BaseKit.java
Original file line number Diff line number Diff line change
Expand Up @@ -1374,25 +1374,48 @@ private void performTextInsertion(JTextComponent target, int insertionOffset, St
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ public enum ColoringAttributes {

KEYWORD,

JAVADOC_IDENTIFIER;
JAVADOC_IDENTIFIER,

UNINDENTED_TEXT_BLOCK;

public static Coloring empty() {
return new Coloring();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@
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;
Expand All @@ -81,6 +83,8 @@
import org.netbeans.modules.parsing.spi.SchedulerEvent;
import org.netbeans.modules.parsing.spi.TaskIndexingMode;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jackpot:
warning: Unused Import

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jackpot:
warning: Unused Import

import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.Pair;


/**
Expand Down Expand Up @@ -249,23 +253,25 @@ protected boolean process(CompilationInfo info, final Document doc, ErrorDescrip

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));
}
}

Expand Down Expand Up @@ -320,7 +326,7 @@ protected boolean process(CompilationInfo info, final Document doc, ErrorDescrip
return true;

if (computeUnusedImports) {
setter.setHighlights(doc, imports, v.preText);
setter.setHighlights(doc, extraColoring, v.preText);
}

setter.setColorings(doc, newColoring);
Expand Down Expand Up @@ -407,6 +413,7 @@ private static class DetectorVisitor extends CancellableTreePathScanner<Void, Vo
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;
Expand All @@ -421,6 +428,7 @@ private DetectorVisitor(org.netbeans.api.java.source.CompilationInfo info, final
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);
Expand Down Expand Up @@ -1063,8 +1071,36 @@ public Void visitMemberReference(MemberReferenceTree node, Void p) {
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) {
Expand All @@ -1085,11 +1121,24 @@ public Void visitLiteral(LiteralTree node, Void p) {
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,30 @@ public void run() {
});
}

public Token currentToken() {
Token[] res = new Token[1];
doc.render(new Runnable() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jackpot:
warning: This anonymous inner class creation can be turned into a lambda expression.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Jackpot:
warning: This anonymous inner class creation can be turned into a lambda expression.

@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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;
Expand Down Expand Up @@ -445,6 +446,35 @@ public void testIncDecReading230408() throws Exception {
performTest("IncDecReading230408");
}

public void testRawStringLiteral() throws Exception {
try {
SourceVersion.valueOf("RELEASE_11");
} catch (IllegalArgumentException iae) {
//OK, presumably no support for raw string literals
}
setSourceLevel("11");
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) {
Expand All @@ -471,6 +501,19 @@ protected boolean process(CompilationInfo info, Document doc) {
}, 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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ private String coloringsToString() {
ColoringAttributes.DECLARATION,

ColoringAttributes.MARK_OCCURRENCES,
ColoringAttributes.UNINDENTED_TEXT_BLOCK,
});

public static HighlightImpl parse(StyledDocument doc, String line) throws ParseException, BadLocationException {
Expand Down
Loading