1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.gui;
21  
22  import java.util.List;
23  
24  import com.puppycrawl.tools.checkstyle.api.DetailAST;
25  import com.puppycrawl.tools.checkstyle.api.DetailNode;
26  import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
27  
28  /**
29   * Presentation model for CodeSelector.
30   */
31  public class CodeSelectorPresentation {
32  
33      /** DetailAST or DetailNode node. */
34      private final Object node;
35      /** Mapping. */
36      private final List<Integer> lines2position;
37      /** Selection start position. */
38      private int selectionStart;
39      /** Selection end position. */
40      private int selectionEnd;
41  
42      /**
43       * Constructor.
44       * @param ast ast node.
45       * @param lines2position list to map lines.
46       * @noinspection AssignmentOrReturnOfFieldWithMutableType
47       */
48      public CodeSelectorPresentation(DetailAST ast, List<Integer> lines2position) {
49          node = ast;
50          this.lines2position = lines2position;
51      }
52  
53      /**
54       * Constructor.
55       * @param node DetailNode node.
56       * @param lines2position list to map lines.
57       * @noinspection AssignmentOrReturnOfFieldWithMutableType
58       */
59      public CodeSelectorPresentation(DetailNode node, List<Integer> lines2position) {
60          this.node = node;
61          this.lines2position = lines2position;
62      }
63  
64      /**
65       * Returns selection start position.
66       * @return selection start position.
67       */
68      public int getSelectionStart() {
69          return selectionStart;
70      }
71  
72      /**
73       * Returns selection end position.
74       * @return selection end position.
75       */
76      public int getSelectionEnd() {
77          return selectionEnd;
78      }
79  
80      /**
81       * Find start and end selection positions from AST line and Column.
82       */
83      public void findSelectionPositions() {
84          if (node instanceof DetailAST) {
85              findSelectionPositions((DetailAST) node);
86          }
87          else {
88              findSelectionPositions((DetailNode) node);
89          }
90      }
91  
92      /**
93       * Find start and end selection positions from AST line and Column.
94       * @param ast DetailAST node for which selection finds
95       */
96      private void findSelectionPositions(DetailAST ast) {
97          selectionStart = lines2position.get(ast.getLineNo()) + ast.getColumnNo();
98  
99          if (ast.getChildCount() == 0
100                 && TokenUtil.getTokenName(ast.getType()).equals(ast.getText())) {
101             selectionEnd = selectionStart;
102         }
103         else {
104             selectionEnd = findLastPosition(ast);
105         }
106     }
107 
108     /**
109      * Find start and end selection positions from DetailNode line and Column.
110      * @param detailNode DetailNode node for which selection finds
111      */
112     private void findSelectionPositions(DetailNode detailNode) {
113         selectionStart = lines2position.get(detailNode.getLineNumber())
114                             + detailNode.getColumnNumber();
115 
116         selectionEnd = findLastPosition(detailNode);
117     }
118 
119     /**
120      * Finds the last position of node without children.
121      * @param astNode DetailAST node.
122      * @return Last position of node without children.
123      */
124     private int findLastPosition(final DetailAST astNode) {
125         final int lastPosition;
126         if (astNode.getChildCount() == 0) {
127             lastPosition = lines2position.get(astNode.getLineNo()) + astNode.getColumnNo()
128                     + astNode.getText().length();
129         }
130         else {
131             lastPosition = findLastPosition(astNode.getLastChild());
132         }
133         return lastPosition;
134     }
135 
136     /**
137      * Finds the last position of node without children.
138      * @param detailNode DetailNode node.
139      * @return Last position of node without children.
140      */
141     private int findLastPosition(final DetailNode detailNode) {
142         final int lastPosition;
143         if (detailNode.getChildren().length == 0) {
144             lastPosition = lines2position.get(detailNode.getLineNumber())
145                     + detailNode.getColumnNumber() + detailNode.getText().length();
146         }
147         else {
148             final DetailNode lastChild =
149                     detailNode.getChildren()[detailNode.getChildren().length - 1];
150             lastPosition = findLastPosition(lastChild);
151         }
152         return lastPosition;
153     }
154 
155 }