Repository: checkstyle/checkstyle

Problem statement:
GUI can not find node by simple xpath
```
$ cat Test.java 
public class Test {
    int i; // warn
    int[] arr = {
      40, // ok magic reason
      47, // ok magic reason
    };
}

$ java -jar checkstyle-8.36.2-all.jar -b "/CLASS_DEF" Test.java 
CLASS_DEF -> CLASS_DEF [1:0]
```

`java -cp checkstyle-8.36.2-all.jar com.puppycrawl.tools.checkstyle.gui.Main Test.java`
Xpath is reported as `^ wrong xpath query`

![image](https://user-images.githubusercontent.com/812984/99819544-73f17680-2b04-11eb-9a30-b74e9624a064.png)



Hints:
@romani 
I got the problem. The CLASS_DEF AST Node is supported by IDENT[@text='Test']. We cannot mention CLASS_DEF simply as there can be multiple class definitions in a java file. So, we need to also mention IDEN[@text='Test']. So, the correct XPATH Query will be `/CLASS_DEF[./IDENT[@text='Test']]`. We can see this when we click on CLASS_DEF node and generate the xpath query. The result is as shown below.

![image](https://user-images.githubusercontent.com/53093601/99880977-da79b000-2c3c-11eb-86a3-6cdd8cb78724.png)

So, simple CLASS_DEF doesn't work.
whole idea of Xpath to has non-exact queries.

Can select first matching node instead printing error ?
or at least find node and print "^ several results found" to let user be aware of this.
https://github.com/checkstyle/checkstyle/blob/3f045f19d40ed017fe4647d6dc2efcda73107e7e/src/main/java/com/puppycrawl/tools/checkstyle/gui/TreeTable.java#L205
Issue from line above looks like it is because we are expecting an EXACT match. Non-exact matches will fail. I expect the GUI doesn't support other non-exact matches like `//CLASS_DEF//IDENT` where classes can be nested as well as multiple.

I assume we will have to switch to something like https://github.com/checkstyle/checkstyle/blob/797642aef9585ac695686b98b7268caccd332a20/src/main/java/com/puppycrawl/tools/checkstyle/filters/XpathFilterElement.java#L238 to support gathering all matching nodes.
The idea was to Find the Node by running Xpath query and selecting particular text in the program. As far as I know Non-Exact Xpath Queries will not be able to identify particular node from the program uniquely. If we deal with Non Exact Xpath Query and give message like `several results found`, then we will get distracted from our functionality i.e `Find Node by Xpath`.

If our functionality is to just check that given xpath is correct or not, then we should go for Non Exact Xpath Queries.

A simple solution is to modify the message. We can give message like `^ wrong xpath query or not an exact xpath query`. Also we can give a sample xpath query so that user gets better idea.
> We can give message like ^ wrong xpath query or not an exact xpath query

at least this should be done.
But we should be able to apply any Xpath and select it atleast first of it in tree, as whole reason of this UI is to give user GUI tool to generate/write Xpath whicj will be used in Xpath Filters.
Example: https://github.com/checkstyle/checkstyle/pull/8711#issuecomment-731250709
can you point me where you apply query ?
it should work the same as apply of query from CLI by option "-b", with only difference is to select first matching node.  
@romani 
> https://github.com/checkstyle/checkstyle/blob/3f045f19d40ed017fe4647d6dc2efcda73107e7e/src/main/java/com/puppycrawl/tools/checkstyle/gui/TreeTable.java#L205

This is the line where are I match exact Xpath Query.
This feature was completely broken since #3095 as there is hard coded "EOF" token for the root node in the `TreeTable` class.
@nmancus1 , this is a item we completely forgot to recheck.

> @nmancus1 , this is a item we completely forgot to recheck.

Yes, it seems like the GUI is often an afterthought for us. I will send a PR soon.

Patch:
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/gui/TreeTable.java b/src/main/java/com/puppycrawl/tools/checkstyle/gui/TreeTable.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/gui/TreeTable.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/gui/TreeTable.java
@@ -30,6 +30,7 @@
 import java.util.Deque;
 import java.util.EventObject;
 import java.util.List;
+import java.util.stream.Collectors;
 
 import javax.swing.AbstractAction;
 import javax.swing.Action;
@@ -42,7 +43,11 @@
 import javax.swing.tree.TreePath;
 
 import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.utils.XpathUtil;
+import com.puppycrawl.tools.checkstyle.xpath.AbstractNode;
+import com.puppycrawl.tools.checkstyle.xpath.RootNode;
 import com.puppycrawl.tools.checkstyle.xpath.XpathQueryGenerator;
+import net.sf.saxon.trans.XPathException;
 
 /**
  * This example shows how to create a simple TreeTable component,
@@ -59,6 +64,8 @@ public final class TreeTable extends JTable {
 
     /** A unique serial version identifier. */
     private static final long serialVersionUID = -8493693409423365387L;
+    /** The newline character. */
+    private static final String NEWLINE = "\n";
     /** A subclass of JTree. */
     private final TreeTableCellRenderer tree;
     /** JTextArea editor. */
@@ -158,10 +165,7 @@ private void makeCodeSelection() {
     private void generateXpath() {
         if (tree.getLastSelectedPathComponent() instanceof DetailAST) {
             final DetailAST ast = (DetailAST) tree.getLastSelectedPathComponent();
-            final int beginPos = 4;
-            String xpath = XpathQueryGenerator.generateXpathQuery(ast);
-            final int length = xpath.length();
-            xpath = xpath.substring(beginPos, length);
+            final String xpath = XpathQueryGenerator.generateXpathQuery(ast);
             xpathEditor.setText(xpath);
         }
         else {
@@ -193,55 +197,25 @@ private void setColumnsInitialWidth() {
         getColumn("Type").setPreferredWidth(preferredTypeColumnWidth);
     }
 
-    /**
-     * Search node by Xpath.
-     *
-     * @param root {@code DetailAST} root ast element
-     * @param xpath {@code String} xpath query
-     * @param nodes {@code Deque<DetailAST>} stack of nodes in selection path
-     * @return {@code boolean} node found or not
-     */
-    private static boolean search(DetailAST root, String xpath, Deque<DetailAST> nodes) {
-        boolean result = false;
-        if (xpath.equals(XpathQueryGenerator.generateXpathQuery(root))) {
-            nodes.push(root);
-            result = true;
-        }
-        else {
-            DetailAST child = root.getFirstChild();
-            while (child != null) {
-                if (search(child, xpath, nodes)) {
-                    nodes.push(root);
-                    result = true;
-                    break;
-                }
-                child = child.getNextSibling();
-            }
-        }
-        return result;
-    }
-
     /**
      * Select Node by Xpath.
      */
     public void selectNodeByXpath() {
         final DetailAST rootAST = (DetailAST) tree.getModel().getRoot();
         if (rootAST.hasChildren()) {
-            final String xpath = "/EOF" + xpathEditor.getText();
-            final Deque<DetailAST> nodes = new ArrayDeque<>();
-            if (search(rootAST, xpath, nodes)) {
-                TreePath path = new TreePath(nodes.pop());
-                while (!nodes.isEmpty()) {
-                    path = path.pathByAddingChild(nodes.pop());
-                    if (!tree.isExpanded(path)) {
-                        tree.expandPath(path);
-                    }
-                    tree.setSelectionPath(path);
-                    makeCodeSelection();
-                }
+            final String xpath = xpathEditor.getText();
+
+            try {
+                final Deque<DetailAST> nodes =
+                        XpathUtil.getXpathItems(xpath, new RootNode(rootAST))
+                              .stream()
+                              .map(AbstractNode.class::cast)
+                              .map(AbstractNode::getUnderlyingNode)
+                              .collect(Collectors.toCollection(ArrayDeque::new));
+                updateTreeTable(xpath, nodes);
             }
-            else {
-                xpathEditor.setText(xpathEditor.getText() + "\n^ wrong xpath query");
+            catch (XPathException exception) {
+                xpathEditor.setText(xpathEditor.getText() + NEWLINE + exception.getMessage());
             }
         }
         else {
@@ -249,6 +223,55 @@ public void selectNodeByXpath() {
         }
     }
 
+    /**
+     * Updates the Treetable by expanding paths in the tree and highlighting
+     * associated code.
+     *
+     * @param xpath the XPath query to show in case of no match
+     * @param nodes the deque of DetailAST nodes to match in TreeTable and XPath editor
+     */
+    private void updateTreeTable(String xpath, Deque<DetailAST> nodes) {
+        if (nodes.isEmpty()) {
+            xpathEditor.setText("No elements matching XPath query '"
+                    + xpath + "' found.");
+        }
+        else {
+            for (DetailAST node : nodes) {
+                expandTreeTableByPath(node);
+                makeCodeSelection();
+            }
+            xpathEditor.setText(getAllMatchingXpathQueriesText(nodes));
+        }
+    }
+
+    /**
+     * Expands path in tree table to given node so that user can
+     * see the node.
+     *
+     * @param node node to expand table by
+     */
+    private void expandTreeTableByPath(DetailAST node) {
+        TreePath path = new TreePath(node);
+        path = path.pathByAddingChild(node);
+        if (!tree.isExpanded(path)) {
+            tree.expandPath(path);
+        }
+        tree.setSelectionPath(path);
+    }
+
+    /**
+     * Generates a String with all matching XPath queries separated
+     * by newlines.
+     *
+     * @param nodes deque of nodes to generate queries for
+     * @return complete text of all XPath expressions separated by newlines.
+     */
+    private static String getAllMatchingXpathQueriesText(Deque<DetailAST> nodes) {
+        return nodes.stream()
+                .map(XpathQueryGenerator::generateXpathQuery)
+                .collect(Collectors.joining(NEWLINE, "", NEWLINE));
+    }
+
     /**
      * Overridden to message super and forward the method to the tree.
      * Since the tree is not actually in the component hierarchy it will
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/utils/XpathUtil.java b/src/main/java/com/puppycrawl/tools/checkstyle/utils/XpathUtil.java
--- a/src/main/java/com/puppycrawl/tools/checkstyle/utils/XpathUtil.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/utils/XpathUtil.java
@@ -39,6 +39,7 @@
 import com.puppycrawl.tools.checkstyle.xpath.RootNode;
 import net.sf.saxon.Configuration;
 import net.sf.saxon.om.Item;
+import net.sf.saxon.om.NodeInfo;
 import net.sf.saxon.sxpath.XPathDynamicContext;
 import net.sf.saxon.sxpath.XPathEvaluator;
 import net.sf.saxon.sxpath.XPathExpression;
@@ -184,14 +185,10 @@ public static String getTextAttributeValue(DetailAST ast) {
      */
     public static String printXpathBranch(String xpath, File file) throws CheckstyleException,
             IOException {
-        final XPathEvaluator xpathEvaluator = new XPathEvaluator(Configuration.newConfiguration());
         try {
             final RootNode rootNode = new RootNode(JavaParser.parseFile(file,
                 JavaParser.Options.WITH_COMMENTS));
-            final XPathExpression xpathExpression = xpathEvaluator.createExpression(xpath);
-            final XPathDynamicContext xpathDynamicContext =
-                xpathExpression.createDynamicContext(rootNode);
-            final List<Item> matchingItems = xpathExpression.evaluate(xpathDynamicContext);
+            final List<NodeInfo> matchingItems = getXpathItems(xpath, rootNode);
             return matchingItems.stream()
                 .map(item -> ((AbstractNode) item).getUnderlyingNode())
                 .map(AstTreeStringPrinter::printBranch)
@@ -204,4 +201,23 @@ public static String printXpathBranch(String xpath, File file) throws Checkstyle
         }
     }
 
+    /**
+     * Returns list of nodes matching xpath expression given node context.
+     *
+     * @param xpath Xpath expression
+     * @param rootNode {@code NodeInfo} node context
+     * @return list of nodes matching xpath expression given node context
+     * @throws XPathException if Xpath cannot be parsed
+     */
+    public static List<NodeInfo> getXpathItems(String xpath, AbstractNode rootNode)
+            throws XPathException {
+        final XPathEvaluator xpathEvaluator = new XPathEvaluator(Configuration.newConfiguration());
+        final XPathExpression xpathExpression = xpathEvaluator.createExpression(xpath);
+        final XPathDynamicContext xpathDynamicContext = xpathExpression
+                .createDynamicContext(rootNode);
+        final List<Item> items = xpathExpression.evaluate(xpathDynamicContext);
+        return items.stream()
+                .map(NodeInfo.class::cast)
+                .collect(Collectors.toUnmodifiableList());
+    }
 }


Test patch:
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/gui/MainFrameTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/gui/MainFrameTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/gui/MainFrameTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/gui/MainFrameTest.java
@@ -183,7 +183,7 @@ public void testFindNodeButton() throws IOException {
         findNodeButton.doClick();
         assertWithMessage("Unexpected XPath text area text")
                 .that(xpathTextArea.getText())
-                .isEqualTo("Xpath\n^ wrong xpath query");
+                .isEqualTo("No elements matching XPath query 'Xpath' found.");
     }
 
 }
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/gui/TreeTableTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/gui/TreeTableTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/gui/TreeTableTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/gui/TreeTableTest.java
@@ -26,7 +26,9 @@
 import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
 import java.io.File;
+import java.io.IOException;
 
+import javax.swing.JButton;
 import javax.swing.JTextArea;
 import javax.swing.KeyStroke;
 import javax.swing.tree.TreePath;
@@ -108,4 +110,105 @@ public void testExpandOnEnterKey() {
                 .isTrue();
     }
 
+    @Test
+    public void testFindNodesAllClassDefs() throws IOException {
+        final MainFrame mainFrame = new MainFrame();
+        mainFrame.openFile(new File(getPath("InputTreeTableXpathAreaPanel.java")));
+        final JButton findNodeButton = findComponentByName(mainFrame, "findNodeButton");
+        final JTextArea xpathTextArea = findComponentByName(mainFrame, "xpathTextArea");
+        xpathTextArea.setText("//CLASS_DEF");
+        findNodeButton.doClick();
+
+        final String expected = "/COMPILATION_UNIT/CLASS_DEF[./IDENT"
+                + "[@text='InputTreeTableXpathAreaPanel']]\n"
+                + "/COMPILATION_UNIT/CLASS_DEF[./IDENT[@text='InputTreeTableXpathAreaPanel']]"
+                + "/OBJBLOCK/CLASS_DEF"
+                + "[./IDENT[@text='Inner']]\n";
+
+        assertWithMessage("Expected and actual XPath queries should match.")
+                .that(xpathTextArea.getText())
+                .isEqualTo(expected);
+    }
+
+    @Test
+    public void testFindNodesIdent() throws IOException {
+        final MainFrame mainFrame = new MainFrame();
+        mainFrame.openFile(new File(getPath("InputTreeTableXpathAreaPanel.java")));
+        final JButton findNodeButton = findComponentByName(mainFrame, "findNodeButton");
+        final JTextArea xpathTextArea = findComponentByName(mainFrame, "xpathTextArea");
+        xpathTextArea.setText("//IDENT");
+        findNodeButton.doClick();
+
+        final String expected = "/COMPILATION_UNIT/CLASS_DEF/IDENT"
+                + "[@text='InputTreeTableXpathAreaPanel']\n"
+                + "/COMPILATION_UNIT/PACKAGE_DEF/DOT/IDENT[@text='treetable']\n"
+                + "/COMPILATION_UNIT/PACKAGE_DEF/DOT[./IDENT[@text='treetable']]/DOT/IDENT"
+                + "[@text='gui']\n"
+                + "/COMPILATION_UNIT/CLASS_DEF[./IDENT[@text='InputTreeTableXpathAreaPanel']]"
+                + "/OBJBLOCK/CLASS_DEF/IDENT[@text='Inner']\n"
+                + "/COMPILATION_UNIT/PACKAGE_DEF/DOT[./IDENT[@text='treetable']]/DOT[./IDENT"
+                + "[@text='gui']]/DOT/IDENT[@text='checkstyle']\n"
+                + "/COMPILATION_UNIT/PACKAGE_DEF/DOT[./IDENT[@text='treetable']]/DOT[./IDENT"
+                + "[@text='gui']]/DOT[./IDENT[@text='checkstyle']]/DOT/IDENT[@text='tools']\n"
+                + "/COMPILATION_UNIT/PACKAGE_DEF/DOT[./IDENT[@text='treetable']]/DOT[./IDENT"
+                + "[@text='gui']]"
+                + "/DOT[./IDENT[@text='checkstyle']]/DOT[./IDENT[@text='tools']]/DOT/IDENT"
+                + "[@text='com']\n"
+                + "/COMPILATION_UNIT/PACKAGE_DEF/DOT[./IDENT[@text='treetable']]/DOT[./IDENT"
+                + "[@text='gui']]"
+                + "/DOT[./IDENT[@text='checkstyle']]/DOT[./IDENT[@text='tools']]/DOT[./IDENT"
+                + "[@text='com']]/IDENT[@text='puppycrawl']\n";
+
+        assertWithMessage("Expected and actual XPath queries should match.")
+                .that(xpathTextArea.getText())
+                .isEqualTo(expected);
+    }
+
+    @Test
+    public void testFindNodesMissingElements() throws IOException {
+        final MainFrame mainFrame = new MainFrame();
+        mainFrame.openFile(new File(getPath("InputTreeTableXpathAreaPanel.java")));
+        final JButton findNodeButton = findComponentByName(mainFrame, "findNodeButton");
+        final JTextArea xpathTextArea = findComponentByName(mainFrame, "xpathTextArea");
+        xpathTextArea.setText("//LITERAL_TRY");
+        findNodeButton.doClick();
+
+        final String expected = "No elements matching XPath query '//LITERAL_TRY' found.";
+
+        assertWithMessage("Unexpected XPath text area text")
+                .that(xpathTextArea.getText())
+                .isEqualTo(expected);
+    }
+
+    @Test
+    public void testFindNodesUnexpectedTokenAtStart() throws IOException {
+        final MainFrame mainFrame = new MainFrame();
+        mainFrame.openFile(new File(getPath("InputTreeTableXpathAreaPanel.java")));
+        final JButton findNodeButton = findComponentByName(mainFrame, "findNodeButton");
+        final JTextArea xpathTextArea = findComponentByName(mainFrame, "xpathTextArea");
+        xpathTextArea.setText("!*7^");
+        findNodeButton.doClick();
+
+        final String expected = "!*7^\nUnexpected token \"!\" at start of expression";
+
+        assertWithMessage("Unexpected XPath text area text")
+                .that(xpathTextArea.getText())
+                .isEqualTo(expected);
+    }
+
+    @Test
+    public void testFindNodesInvalidCharacterInExpression() throws IOException {
+        final MainFrame mainFrame = new MainFrame();
+        mainFrame.openFile(new File(getPath("InputTreeTableXpathAreaPanel.java")));
+        final JButton findNodeButton = findComponentByName(mainFrame, "findNodeButton");
+        final JTextArea xpathTextArea = findComponentByName(mainFrame, "xpathTextArea");
+        xpathTextArea.setText("//CLASS_DEF^");
+        findNodeButton.doClick();
+
+        final String expected = "//CLASS_DEF^\nInvalid character '^' in expression";
+
+        assertWithMessage("Unexpected XPath text area text")
+                .that(xpathTextArea.getText())
+                .isEqualTo(expected);
+    }
 }
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/internal/utils/XpathUtil.java b/src/test/java/com/puppycrawl/tools/checkstyle/internal/utils/XpathUtil.java
deleted file mode 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/internal/utils/XpathUtil.java
+++ /dev/null
@@ -1,61 +0,0 @@
-////////////////////////////////////////////////////////////////////////////////
-// checkstyle: Checks Java source code for adherence to a set of rules.
-// Copyright (C) 2001-2022 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.internal.utils;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import com.puppycrawl.tools.checkstyle.xpath.AbstractNode;
-import net.sf.saxon.Configuration;
-import net.sf.saxon.om.Item;
-import net.sf.saxon.om.NodeInfo;
-import net.sf.saxon.sxpath.XPathDynamicContext;
-import net.sf.saxon.sxpath.XPathEvaluator;
-import net.sf.saxon.sxpath.XPathExpression;
-import net.sf.saxon.trans.XPathException;
-
-/**
- * XpathUtil.
- *
- * @noinspection ClassOnlyUsedInOnePackage
- */
-public final class XpathUtil {
-
-    private XpathUtil() {
-    }
-
-    /**
-     * Returns list of nodes matching xpath expression given node context.
-     *
-     * @param xpath Xpath expression
-     * @param rootNode {@code NodeInfo} node context
-     * @return list of nodes matching xpath expression given node context
-     */
-    public static List<NodeInfo> getXpathItems(String xpath, AbstractNode rootNode)
-            throws XPathException {
-        final XPathEvaluator xpathEvaluator = new XPathEvaluator(Configuration.newConfiguration());
-        final XPathExpression xpathExpression = xpathEvaluator.createExpression(xpath);
-        final XPathDynamicContext xpathDynamicContext = xpathExpression
-                .createDynamicContext(rootNode);
-        final List<Item> items = xpathExpression.evaluate(xpathDynamicContext);
-        return items.stream().map(item -> (NodeInfo) item).collect(Collectors.toList());
-    }
-
-}
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/xpath/ElementNodeTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/xpath/ElementNodeTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/xpath/ElementNodeTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/xpath/ElementNodeTest.java
@@ -20,7 +20,7 @@
 package com.puppycrawl.tools.checkstyle.xpath;
 
 import static com.google.common.truth.Truth.assertWithMessage;
-import static com.puppycrawl.tools.checkstyle.internal.utils.XpathUtil.getXpathItems;
+import static com.puppycrawl.tools.checkstyle.utils.XpathUtil.getXpathItems;
 
 import java.io.File;
 import java.util.List;
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/xpath/RootNodeTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/xpath/RootNodeTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/xpath/RootNodeTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/xpath/RootNodeTest.java
@@ -20,7 +20,7 @@
 package com.puppycrawl.tools.checkstyle.xpath;
 
 import static com.google.common.truth.Truth.assertWithMessage;
-import static com.puppycrawl.tools.checkstyle.internal.utils.XpathUtil.getXpathItems;
+import static com.puppycrawl.tools.checkstyle.utils.XpathUtil.getXpathItems;
 
 import java.io.File;
 import java.util.List;
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/xpath/XpathMapperTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/xpath/XpathMapperTest.java
--- a/src/test/java/com/puppycrawl/tools/checkstyle/xpath/XpathMapperTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/xpath/XpathMapperTest.java
@@ -20,7 +20,7 @@
 package com.puppycrawl.tools.checkstyle.xpath;
 
 import static com.google.common.truth.Truth.assertWithMessage;
-import static com.puppycrawl.tools.checkstyle.internal.utils.XpathUtil.getXpathItems;
+import static com.puppycrawl.tools.checkstyle.utils.XpathUtil.getXpathItems;
 
 import java.io.File;
 import java.util.List;
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/gui/treetable/InputTreeTableXpathAreaPanel.java b/src/test/resources/com/puppycrawl/tools/checkstyle/gui/treetable/InputTreeTableXpathAreaPanel.java
new file mode 100644
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/gui/treetable/InputTreeTableXpathAreaPanel.java
@@ -0,0 +1,5 @@
+package com.puppycrawl.tools.checkstyle.gui.treetable;
+
+public class InputTreeTableXpathAreaPanel {
+    class Inner{}
+}