From 62d4bfe0dd5635d41cc97e8fa8ccabd89ea376e9 Mon Sep 17 00:00:00 2001 From: kazachka Date: Sat, 12 Nov 2016 19:42:09 +0300 Subject: [PATCH] Issue #3432: Added DetailNode support for CodeSelector, gui code selection and tests --- pom.xml | 3 +- .../tools/checkstyle/gui/CodeSelector.java | 12 +- .../checkstyle/gui/CodeSelectorPModel.java | 61 ++++++++- .../tools/checkstyle/gui/JTreeTable.java | 4 +- .../gui/CodeSelectorPModelTest.java | 120 ++++++++++++++++++ 5 files changed, 189 insertions(+), 11 deletions(-) create mode 100644 src/test/java/com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModelTest.java diff --git a/pom.xml b/pom.xml index 23379b30a..79db2afdb 100644 --- a/pom.xml +++ b/pom.xml @@ -1434,7 +1434,7 @@ com/puppycrawl/tools/checkstyle/grammars/javadoc/*.class com/puppycrawl/tools/checkstyle/gui/BaseCellEditor*.class - com/puppycrawl/tools/checkstyle/gui/CodeSelector*.class + com/puppycrawl/tools/checkstyle/gui/CodeSelector.class com/puppycrawl/tools/checkstyle/gui/JTreeTable*.class com/puppycrawl/tools/checkstyle/gui/ListToTreeSelectionModelWrapper*.class com/puppycrawl/tools/checkstyle/gui/Main*.class @@ -1443,7 +1443,6 @@ com/puppycrawl/tools/checkstyle/gui/TreeTableCellRenderer*.class com/puppycrawl/tools/checkstyle/gui/TreeTableModelAdapter*.class - com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModel*.class com/puppycrawl/tools/checkstyle/gui/MainFrameModel*.class com/puppycrawl/tools/checkstyle/checks/AbstractFormatCheck.class diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/gui/CodeSelector.java b/src/main/java/com/puppycrawl/tools/checkstyle/gui/CodeSelector.java index f336da633..359b4c5d2 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/gui/CodeSelector.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/gui/CodeSelector.java @@ -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 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); + } } /** diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModel.java b/src/main/java/com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModel.java index c5a942449..c4b161fd0 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModel.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModel.java @@ -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 lines2position; /** Selection start position. */ @@ -46,7 +47,18 @@ public class CodeSelectorPModel { * @param lines2position list to map lines. */ public CodeSelectorPModel(DetailAST ast, List lines2position) { - this.ast = ast; + node = ast; + final List 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 lines2position) { + this.node = node; final List 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; + } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/gui/JTreeTable.java b/src/main/java/com/puppycrawl/tools/checkstyle/gui/JTreeTable.java index 0e81fed0b..7bf064a62 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/gui/JTreeTable.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/gui/JTreeTable.java @@ -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(); } /** diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModelTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModelTest.java new file mode 100644 index 000000000..db86f0d9e --- /dev/null +++ b/src/test/java/com/puppycrawl/tools/checkstyle/gui/CodeSelectorPModelTest.java @@ -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 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 convertLinesToPosition(List systemLinesToPosition) { + final List 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()); + } + +}