View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 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.checks.indentation;
21  
22  import java.util.BitSet;
23  
24  /**
25   * Encapsulates representation of notion of expected indentation levels.
26   * Provide a way to have multiple acceptable levels.
27   * This class is immutable.
28   */
29  public class IndentLevel {
30  
31      /** Set of acceptable indentation levels. */
32      private final BitSet levels = new BitSet();
33  
34      /**
35       * Creates new instance with one acceptable indentation level.
36       *
37       * @param indent acceptable indentation level.
38       */
39      public IndentLevel(int indent) {
40          levels.set(indent);
41      }
42  
43      /**
44       * Creates new instance for nested structure.
45       *
46       * @param base parent's level
47       * @param offsets offsets from parent's level.
48       */
49      public IndentLevel(IndentLevel base, int... offsets) {
50          final BitSet src = base.levels;
51          for (int i = src.nextSetBit(0); i >= 0; i = src.nextSetBit(i + 1)) {
52              for (int offset : offsets) {
53                  levels.set(i + offset);
54              }
55          }
56      }
57  
58      /**
59       * Creates new instance with no acceptable indentation level.
60       * This is only used internally to combine multiple levels.
61       */
62      private IndentLevel() {
63      }
64  
65      /**
66       * Checks whether we have more than one level.
67       *
68       * @return whether we have more than one level.
69       */
70      public final boolean isMultiLevel() {
71          return levels.cardinality() > 1;
72      }
73  
74      /**
75       * Checks if given indentation is acceptable.
76       *
77       * @param indent indentation to check.
78       * @return true if given indentation is acceptable,
79       *         false otherwise.
80       */
81      public boolean isAcceptable(int indent) {
82          return levels.get(indent);
83      }
84  
85      /**
86       * Returns true if indent less than minimal of
87       * acceptable indentation levels, false otherwise.
88       *
89       * @param indent indentation to check.
90       * @return true if {@code indent} less than minimal of
91       *         acceptable indentation levels, false otherwise.
92       */
93      public boolean isGreaterThan(int indent) {
94          return levels.nextSetBit(0) > indent;
95      }
96  
97      /**
98       * Adds one or more acceptable indentation level.
99       *
100      * @param base class to add new indentations to.
101      * @param additions new acceptable indentation.
102      * @return New acceptable indentation level instance.
103      */
104     public static IndentLevel addAcceptable(IndentLevel base, int... additions) {
105         final IndentLevel result = new IndentLevel();
106         result.levels.or(base.levels);
107         for (int addition : additions) {
108             result.levels.set(addition);
109         }
110         return result;
111     }
112 
113     /**
114      * Combines 2 acceptable indentation level classes.
115      *
116      * @param base class to add new indentations to.
117      * @param addition new acceptable indentation.
118      * @return New acceptable indentation level instance.
119      */
120     public static IndentLevel addAcceptable(IndentLevel base, IndentLevel addition) {
121         final IndentLevel result = new IndentLevel();
122         result.levels.or(base.levels);
123         result.levels.or(addition.levels);
124         return result;
125     }
126 
127     /**
128      * Returns first indentation level.
129      *
130      * @return indentation level.
131      */
132     public int getFirstIndentLevel() {
133         return levels.nextSetBit(0);
134     }
135 
136     /**
137      * Returns last indentation level.
138      *
139      * @return indentation level.
140      */
141     public int getLastIndentLevel() {
142         return levels.length() - 1;
143     }
144 
145     @Override
146     public String toString() {
147         final String result;
148         if (levels.cardinality() == 1) {
149             result = String.valueOf(levels.nextSetBit(0));
150         }
151         else {
152             final StringBuilder sb = new StringBuilder(50);
153             for (int i = levels.nextSetBit(0); i >= 0;
154                  i = levels.nextSetBit(i + 1)) {
155                 if (sb.length() > 0) {
156                     sb.append(", ");
157                 }
158                 sb.append(i);
159             }
160             result = sb.toString();
161         }
162         return result;
163     }
164 
165 }