Skip to content

Commit

Permalink
Fix #570 [clean branch] (#589)
Browse files Browse the repository at this point in the history
* Ignoring leading/trailing whitespaces before/after comment markers

* Fix: Checkstyle errors

* Update RSyntaxTextAreaEditorKit.java

Try to amend CodeQL error
  • Loading branch information
sesquialtera87 authored Dec 21, 2024
1 parent b0f9bed commit f0d8326
Show file tree
Hide file tree
Showing 2 changed files with 160 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2213,91 +2213,139 @@ public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {
return;
}

RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument();
RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument();
Element map = doc.getDefaultRootElement();
Caret c = textArea.getCaret();
int dot = c.getDot();
int mark = c.getMark();
int line1 = map.getElementIndex(dot);
int line2 = map.getElementIndex(mark);
int start = Math.min(line1, line2);
int end = Math.max(line1, line2);
int end = Math.max(line1, line2);

Token t = doc.getTokenListForLine(start);
int languageIndex = t!=null ? t.getLanguageIndex() : 0;
int languageIndex = t != null ? t.getLanguageIndex() : 0;
String[] startEnd = doc.getLineCommentStartAndEnd(languageIndex);

if (startEnd==null) {
if (startEnd == null) {
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
return;
}

// Don't toggle comment on last line if there is no
// text selected on it.
if (start!=end) {
if (start != end) {
Element elem = map.getElement(end);
if (Math.max(dot, mark)==elem.getStartOffset()) {
if (Math.max(dot, mark) == elem.getStartOffset()) {
end--;
}
}

textArea.beginAtomicEdit();
try {
boolean add = getDoAdd(doc,map, start,end, startEnd);
for (line1=start; line1<=end; line1++) {
for (line1 = end; line1 >= start; line1--) {
Element elem = map.getElement(line1);
handleToggleComment(elem, doc, startEnd, add);
String lineText = doc.getText(elem.getStartOffset(),
elem.getEndOffset() - elem.getStartOffset() - 1);
int[] pos = searchMarkers(lineText, startEnd);
handleToggleComment(elem, doc, lineText, startEnd, pos);
}
} catch (BadLocationException ble) {
ble.printStackTrace();
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
} finally {
textArea.endAtomicEdit();
}

}

private boolean getDoAdd(Document doc, Element map, int startLine,
int endLine, String[] startEnd)
throws BadLocationException {
boolean doAdd = false;
for (int i=startLine; i<=endLine; i++) {
Element elem = map.getElement(i);
int start = elem.getStartOffset();
String t = doc.getText(start, elem.getEndOffset()-start-1);
if (!t.startsWith(startEnd[0]) ||
(startEnd[1]!=null && !t.endsWith(startEnd[1]))) {
doAdd = true;
/**
* Search the end-comment mark, skipping trailing whitespaces.
*
* @param text The line text.
* @param startEnd The start/end comment marks.
* @return The index of the mark if present, otherwise -1.
*/
int endMatch(String text, String[] startEnd) {
if (startEnd[1] == null) {
return -1;
}

char c;
int i = text.length() - 1;

while (i >= 0) {
c = text.charAt(i);

if (!Character.isWhitespace(c)) {
break;
}

i--;
}

i = i - startEnd[1].length() + 1;

if (text.lastIndexOf(startEnd[1]) == i) {
return i;
} else {
return -1;
}
return doAdd;
}

private void handleToggleComment(Element elem, Document doc,
String[] startEnd, boolean add) throws BadLocationException {
int start = elem.getStartOffset();
int end = elem.getEndOffset() - 1;
if (add) {
if (startEnd[1]!=null) {
doc.insertString(end, startEnd[1], null);
}
doc.insertString(start, startEnd[0], null);
/**
* Search the start-comment mark, skipping leading whitespaces.
*
* @param text The line text.
* @param startEnd The start/end comment marks.
* @return The index of the mark if present, otherwise -1.
*/
int startMatch(String text, String[] startEnd) {
String ws = RSyntaxUtilities.getLeadingWhitespace(text);

if (text.indexOf(startEnd[0]) == ws.length()) {
return ws.length();
} else {
return -1;
}
else {
if (startEnd[1]!=null) {
int temp = startEnd[1].length();
doc.remove(end-temp, temp);
}

private int[] searchMarkers(String line, String[] startEnd) {
int startOffset = startMatch(line, startEnd);
int endOffset = endMatch(line, startEnd);

return new int[]{startOffset, endOffset};
}

private void handleToggleComment(Element elem, Document doc, String line, String[] startEnd, int[] pos)
throws BadLocationException {

int startOffset = elem.getStartOffset();

if (pos[0] >= 0 && ((pos[1] >= 0 && startEnd[1] != null) || (pos[1] < 0 && startEnd[1] == null))) {
// start-mark found (and also the end-mark for two-mark comments)
if (startEnd[1] != null && pos[1] >= 0) {
doc.remove(startOffset + pos[1], startEnd[1].length());
}
doc.remove(start, startEnd[0].length());

if (pos[0] >= 0) {
doc.remove(startOffset + pos[0], startEnd[0].length());
}
} else {
if (startEnd[1] != null) {
// add the mark after the last char of the line
doc.insertString(elem.getEndOffset() - 1, startEnd[1], null);
}

// insert the mark right before the first non-ws char
int n = RSyntaxUtilities.getLeadingWhitespace(line).length();
doc.insertString(startOffset + n, startEnd[0], null);
}
}

@Override
public final String getMacroID() {
return rstaToggleCommentAction;
}

}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import java.awt.event.ActionEvent;


/**
* Unit tests for the {@link RSyntaxTextAreaEditorKit.ToggleCommentAction} class.
Expand Down Expand Up @@ -144,4 +146,76 @@ void testGetMacroID() {
Assertions.assertEquals(RSyntaxTextAreaEditorKit.rstaToggleCommentAction,
new RSyntaxTextAreaEditorKit.ToggleCommentAction().getMacroID());
}
}

@Test
void testLeadingTrailingWhitespaces() {
RSyntaxTextAreaEditorKit.ToggleCommentAction commentAction = new RSyntaxTextAreaEditorKit.ToggleCommentAction();
RSyntaxTextArea textArea = createTextArea(SyntaxConstants.SYNTAX_STYLE_C, "");
ActionEvent e = new ActionEvent(textArea, 0, "command");

// multiline with leading WS
textArea.setText(" //line 1\n//line 2\nline 3");
textArea.setCaretPosition(2);
textArea.moveCaretPosition(15);

commentAction.actionPerformedImpl(e, textArea);

String expectedText = " line 1\nline 2\nline 3";
Assertions.assertEquals(expectedText, textArea.getText());

// start/end marks and leading and trailing WS
textArea.setText(" <!-- xml --> ");
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
textArea.setCaretPosition(0);
textArea.moveCaretPosition(0);

commentAction.actionPerformedImpl(e, textArea);

expectedText = " xml ";
Assertions.assertEquals(expectedText, textArea.getText());

// comment
textArea.setText(" int a = 2; ");
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
textArea.setCaretPosition(0);
textArea.moveCaretPosition(5);

commentAction.actionPerformedImpl(e, textArea);

expectedText = " //int a = 2; ";
Assertions.assertEquals(expectedText, textArea.getText());

// multiline with leading and trailing WS and start/end marks
textArea.setText(" <!-- line 1 -->\n<!--line 2 --> ");
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
textArea.setCaretPosition(0);
textArea.moveCaretPosition(textArea.getDocument().getLength());

commentAction.actionPerformedImpl(e, textArea);

expectedText = " line 1 \nline 2 ";
Assertions.assertEquals(expectedText, textArea.getText());
}

/**
* Test for {@link org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit.ToggleCommentAction#startMatch(String, String[])}
* and {@link org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit.ToggleCommentAction#endMatch(String, String[])}
*/
@Test
void startEndSearch() {
String[] markers = {"<!--", "-->"};
RSyntaxTextAreaEditorKit.ToggleCommentAction action = new RSyntaxTextAreaEditorKit.ToggleCommentAction();

Assertions.assertEquals(0, action.startMatch("<!-- text -->", markers));
Assertions.assertEquals(2, action.startMatch(" <!-- text -->", markers));
Assertions.assertEquals(-1, action.startMatch("// text", markers));
Assertions.assertEquals(-1, action.startMatch(" // text", markers));
Assertions.assertEquals(-1, action.startMatch("", markers));

Assertions.assertEquals(10, action.endMatch("<!-- text -->", markers));
Assertions.assertEquals(12, action.endMatch(" <!-- text -->", markers));
Assertions.assertEquals(-1, action.endMatch("// text", markers));
Assertions.assertEquals(-1, action.endMatch(" // text", markers));
Assertions.assertEquals(-1, action.endMatch("", markers));
}
}

0 comments on commit f0d8326

Please sign in to comment.