Issue #3432: Added DetailNode support for CodeSelector, gui code selection and tests

This commit is contained in:
kazachka 2016-11-12 19:42:09 +03:00 committed by rnveach
parent 23202260b2
commit 62d4bfe0dd
5 changed files with 189 additions and 11 deletions

View File

@ -1434,7 +1434,7 @@
<exclude>com/puppycrawl/tools/checkstyle/grammars/javadoc/*.class</exclude>
<!-- Swing related classes -->
<exclude>com/puppycrawl/tools/checkstyle/gui/BaseCellEditor*.class</exclude>
<exclude>com/puppycrawl/tools/checkstyle/gui/CodeSelector*.class</exclude>
<exclude>com/puppycrawl/tools/checkstyle/gui/CodeSelector.class</exclude>
<exclude>com/puppycrawl/tools/checkstyle/gui/JTreeTable*.class</exclude>
<exclude>com/puppycrawl/tools/checkstyle/gui/ListToTreeSelectionModelWrapper*.class</exclude>
<exclude>com/puppycrawl/tools/checkstyle/gui/Main*.class</exclude>
@ -1443,7 +1443,6 @@
<exclude>com/puppycrawl/tools/checkstyle/gui/TreeTableCellRenderer*.class</exclude>
<exclude>com/puppycrawl/tools/checkstyle/gui/TreeTableModelAdapter*.class</exclude>
<!-- GUI model classes without tests -->
<exclude>com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModel*.class</exclude>
<exclude>com/puppycrawl/tools/checkstyle/gui/MainFrameModel*.class</exclude>
<!-- deprecated classes -->
<exclude>com/puppycrawl/tools/checkstyle/checks/AbstractFormatCheck.class</exclude>

View File

@ -25,6 +25,7 @@ import java.util.List;
import javax.swing.JTextArea;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.DetailNode;
/**
* Helper class to select a code.
@ -38,14 +39,19 @@ public class CodeSelector {
/**
* Constructor.
* @param ast ast node.
* @param node ast node.
* @param editor text area editor.
* @param lines2position list to map lines.
*/
public CodeSelector(final DetailAST ast, final JTextArea editor,
public CodeSelector(final Object node, final JTextArea editor,
final List<Integer> lines2position) {
this.editor = editor;
pModel = new CodeSelectorPModel(ast, lines2position);
if (node instanceof DetailAST) {
pModel = new CodeSelectorPModel((DetailAST) node, lines2position);
}
else {
pModel = new CodeSelectorPModel((DetailNode) node, lines2position);
}
}
/**

View File

@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.List;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.DetailNode;
import com.puppycrawl.tools.checkstyle.utils.TokenUtils;
/**
@ -31,8 +32,8 @@ import com.puppycrawl.tools.checkstyle.utils.TokenUtils;
* @author unknown
*/
public class CodeSelectorPModel {
/** DetailAST node. */
private final DetailAST ast;
/** DetailAST or DetailNode node. */
private final Object node;
/** Mapping. */
private final List<Integer> lines2position;
/** Selection start position. */
@ -46,7 +47,18 @@ public class CodeSelectorPModel {
* @param lines2position list to map lines.
*/
public CodeSelectorPModel(DetailAST ast, List<Integer> lines2position) {
this.ast = ast;
node = ast;
final List<Integer> copy = new ArrayList<>(lines2position);
this.lines2position = Collections.unmodifiableList(copy);
}
/**
* Constructor.
* @param node DetailNode node.
* @param lines2position list to map lines.
*/
public CodeSelectorPModel(DetailNode node, List<Integer> lines2position) {
this.node = node;
final List<Integer> copy = new ArrayList<>(lines2position);
this.lines2position = Collections.unmodifiableList(copy);
}
@ -69,6 +81,19 @@ public class CodeSelectorPModel {
* Find start and end selection positions from AST line and Column.
*/
public void findSelectionPositions() {
if (node instanceof DetailAST) {
findSelectionPositions((DetailAST) node);
}
else {
findSelectionPositions((DetailNode) node);
}
}
/**
* Find start and end selection positions from AST line and Column.
* @param ast DetailAST node for which selection finds
*/
private void findSelectionPositions(DetailAST ast) {
selectionStart = lines2position.get(ast.getLineNo()) + ast.getColumnNo();
if (ast.getChildCount() == 0
@ -80,6 +105,17 @@ public class CodeSelectorPModel {
}
}
/**
* Find start and end selection positions from DetailNode line and Column.
* @param detailNode DetailNode node for which selection finds
*/
private void findSelectionPositions(DetailNode detailNode) {
selectionStart = lines2position.get(detailNode.getLineNumber())
+ detailNode.getColumnNumber();
selectionEnd = findLastPosition(detailNode);
}
/**
* Finds the last position of node without children.
* @param astNode DetailAST node.
@ -94,4 +130,23 @@ public class CodeSelectorPModel {
return findLastPosition(astNode.getLastChild());
}
}
/**
* Finds the last position of node without children.
* @param detailNode DetailNode node.
* @return Last position of node without children.
*/
private int findLastPosition(final DetailNode detailNode) {
final int lastPosition;
if (detailNode.getChildren().length == 0) {
lastPosition = lines2position.get(detailNode.getLineNumber())
+ detailNode.getColumnNumber() + detailNode.getText().length();
}
else {
final DetailNode lastChild =
detailNode.getChildren()[detailNode.getChildren().length - 1];
lastPosition = findLastPosition(lastChild);
}
return lastPosition;
}
}

View File

@ -142,9 +142,7 @@ public class JTreeTable extends JTable {
* Make selection of code in a text area.
*/
private void makeCodeSelection() {
// temporary disabled. Have to deal with Javadoc nodes as well
// see https://github.com/checkstyle/checkstyle/issues/3432
new CodeSelector(null, editor, linePositionMap);
new CodeSelector(tree.getLastSelectedPathComponent(), editor, linePositionMap).select();
}
/**

View File

@ -0,0 +1,120 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2016 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle.gui;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.DetailNode;
import com.puppycrawl.tools.checkstyle.gui.MainFrameModel.ParseMode;
public class CodeSelectorPModelTest {
private MainFrameModel model;
private DetailAST tree;
private List<Integer> linesToPosition;
@Before
public void loadFile() throws CheckstyleException {
model = new MainFrameModel();
model.setParseMode(ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS);
model.openFile(new File(getPath("InputJavadocAttributesAndMethods.java")));
tree = ((DetailAST) model.getParseTreeTableModel().getRoot()).getFirstChild();
linesToPosition = convertLinesToPosition(model.getLinesToPosition());
}
private static String getPath(String filename) {
return "src/test/resources/com/puppycrawl/tools/checkstyle/gui/" + filename;
}
/** Converts lineToPosition from multicharacter to one character line separator
* needs to support crossplatform line separators
* @param systemLinesToPosition lines to position mapping for current system
* @return lines to position mapping with one character line separator
*/
private static List<Integer> convertLinesToPosition(List<Integer> systemLinesToPosition) {
final List<Integer> convertedLinesToPosition = new ArrayList<>();
final int lineSeparationCorrection = System.lineSeparator().length() - 1;
convertedLinesToPosition.add(0, systemLinesToPosition.get(0));
for (int i = 1; i < systemLinesToPosition.size(); i++) {
convertedLinesToPosition.add(i,
systemLinesToPosition.get(i) - lineSeparationCorrection * (i - 1));
}
return convertedLinesToPosition;
}
@Test
public void testDetailASTSelection() {
final CodeSelectorPModel selector = new CodeSelectorPModel(tree, linesToPosition);
selector.findSelectionPositions();
Assert.assertEquals(23, selector.getSelectionStart());
Assert.assertEquals(212, selector.getSelectionEnd());
}
@Test
public void testDetailASTLeafSelection() {
final DetailAST leaf = tree.getLastChild().getFirstChild();
final CodeSelectorPModel selector = new CodeSelectorPModel(leaf, linesToPosition);
selector.findSelectionPositions();
Assert.assertEquals(62, selector.getSelectionStart());
Assert.assertEquals(63, selector.getSelectionEnd());
}
@Test
public void testDetailASTNoSelection() {
final DetailAST leaf = tree.getFirstChild();
final CodeSelectorPModel selector = new CodeSelectorPModel(leaf, linesToPosition);
selector.findSelectionPositions();
Assert.assertEquals(23, selector.getSelectionStart());
Assert.assertEquals(23, selector.getSelectionEnd());
}
@Test
public void testDetailNodeSelection() {
final DetailNode javadoc = (DetailNode) model.getParseTreeTableModel()
.getChild(tree.getFirstChild().getNextSibling().getFirstChild(), 0);
final CodeSelectorPModel selector = new CodeSelectorPModel(javadoc, linesToPosition);
selector.findSelectionPositions();
Assert.assertEquals(0, selector.getSelectionStart());
Assert.assertEquals(25, selector.getSelectionEnd());
}
@Test
public void testDetailNodeLeafSelection() {
final DetailNode javadocLeaf = ((DetailNode) model.getParseTreeTableModel()
.getChild(tree.getFirstChild().getNextSibling().getFirstChild(), 0))
.getChildren()[2].getChildren()[0];
final CodeSelectorPModel selector = new CodeSelectorPModel(javadocLeaf, linesToPosition);
selector.findSelectionPositions();
Assert.assertEquals(5, selector.getSelectionStart());
Assert.assertEquals(6, selector.getSelectionEnd());
}
}