PageRenderTime 53ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/platform-style-rules/src/main/java/com/atlassian/platform/style/ImportOrderCheck.java

https://bitbucket.org/jwalton/atlassian-platform-style
Java | 218 lines | 138 code | 28 blank | 52 comment | 22 complexity | 693b3e450edd140e5d8f1a6bc7540b25 MD5 | raw file
Possible License(s): LGPL-2.1
  1. ////////////////////////////////////////////////////////////////////////////////
  2. // checkstyle: Checks Java source code for adherence to a set of rules.
  3. // Copyright (C) 2001-2012 Oliver Burn
  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. package com.atlassian.platform.style;
  20. import java.util.regex.Matcher;
  21. import java.util.regex.Pattern;
  22. import com.puppycrawl.tools.checkstyle.api.Check;
  23. import com.puppycrawl.tools.checkstyle.api.DetailAST;
  24. import com.puppycrawl.tools.checkstyle.api.FullIdent;
  25. import com.puppycrawl.tools.checkstyle.api.TokenTypes;
  26. /**
  27. * <p>
  28. * Checks specifically for the Atlassian Platform import order:
  29. * </p>
  30. *
  31. * <ol>
  32. * <li>import java.*</li>
  33. * <li>import javax.*</li>
  34. * <li>import com.atlassian.*</li>
  35. * <li>import com.*</li>
  36. * <li>import org.*</li>
  37. * <li>import all other imports</li>
  38. * <li>import static all other imports</li>
  39. * </ol>
  40. *
  41. * <p>with blank lines between each group.</p>
  42. *
  43. * <p>Derived from {@link com.puppycrawl.tools.checkstyle.checks.imports.ImportOrderCheck}.</p>
  44. *
  45. * @author Bill Schneider
  46. * @author o_sukhodolsky
  47. * @author David DIDIER
  48. * @author Steve McKay
  49. */
  50. public class ImportOrderCheck extends Check
  51. {
  52. private static final Pattern[] mGroups = {
  53. Pattern.compile("^java\\."),
  54. Pattern.compile("^javax\\."),
  55. Pattern.compile("^com\\.atlassian\\."),
  56. Pattern.compile("^com\\."),
  57. Pattern.compile("^org\\."),
  58. };
  59. /** Require imports in group be separated. */
  60. private static final boolean mSeparated = true;
  61. /** Last imported group. */
  62. private CategorisedImport lastImport;
  63. private int lastImportLine;
  64. @Override
  65. public int[] getDefaultTokens()
  66. {
  67. return new int[] {TokenTypes.IMPORT, TokenTypes.STATIC_IMPORT};
  68. }
  69. @Override
  70. public void beginTree(DetailAST aRootAST)
  71. {
  72. lastImport = null;
  73. }
  74. @Override
  75. public void visitToken(DetailAST aAST)
  76. {
  77. FullIdent ident;
  78. boolean isStatic;
  79. int groupNumber;
  80. switch (aAST.getType())
  81. {
  82. case TokenTypes.IMPORT:
  83. ident = FullIdent.createFullIdentBelow(aAST);
  84. isStatic = false;
  85. groupNumber = getGroupNumber(ident.getText());
  86. break;
  87. case TokenTypes.STATIC_IMPORT:
  88. ident = FullIdent.createFullIdent(aAST.getFirstChild()
  89. .getNextSibling());
  90. isStatic = true;
  91. groupNumber = -1;
  92. break;
  93. default:
  94. throw new IllegalArgumentException("Not expecting to visit: " + aAST.getType());
  95. }
  96. CategorisedImport thisImport = new CategorisedImport(isStatic, groupNumber, ident.getText());
  97. int thisImportLine = ident.getLineNo();
  98. if (lastImport != null)
  99. {
  100. if (lastImport.compareTo(thisImport) > 0)
  101. {
  102. log(ident.getLineNo(), "import.ordering", thisImport);
  103. }
  104. if (mSeparated)
  105. {
  106. if (!lastImport.sameGroup(thisImport))
  107. {
  108. if (thisImportLine - lastImportLine < 2)
  109. {
  110. log(ident.getLineNo(), "import.separation", ident.getText());
  111. }
  112. }
  113. }
  114. }
  115. lastImport = thisImport;
  116. lastImportLine = thisImportLine;
  117. }
  118. /**
  119. * Finds out what group the specified import belongs to.
  120. *
  121. * @param aName the import name to find.
  122. * @return group number for given import name.
  123. */
  124. private int getGroupNumber(String aName)
  125. {
  126. int bestIndex = mGroups.length;
  127. int bestLength = -1;
  128. int bestPos = 0;
  129. // find out what group this belongs in
  130. // loop over mGroups and get index
  131. for (int i = 0; i < mGroups.length; i++) {
  132. final Matcher matcher = mGroups[i].matcher(aName);
  133. while (matcher.find()) {
  134. final int length = matcher.end() - matcher.start();
  135. if ((length > bestLength)
  136. || ((length == bestLength) && (matcher.start() < bestPos)))
  137. {
  138. bestIndex = i;
  139. bestLength = length;
  140. bestPos = matcher.start();
  141. }
  142. }
  143. }
  144. return bestIndex;
  145. }
  146. private static class CategorisedImport implements Comparable<CategorisedImport>
  147. {
  148. private final boolean isStatic;
  149. private final int groupNumber;
  150. private final String importValue;
  151. public CategorisedImport(boolean isStatic, int groupNumber, String importValue)
  152. {
  153. this.isStatic = isStatic;
  154. this.groupNumber = groupNumber;
  155. this.importValue = importValue;
  156. }
  157. boolean sameGroup(CategorisedImport o)
  158. {
  159. if (isStatic && o.isStatic)
  160. {
  161. return true;
  162. }
  163. if (isStatic != o.isStatic)
  164. {
  165. return false;
  166. }
  167. return groupNumber == o.groupNumber;
  168. }
  169. @Override
  170. public int compareTo(CategorisedImport o)
  171. {
  172. int bc = Boolean.valueOf(isStatic).compareTo(Boolean.valueOf(o.isStatic));
  173. if (bc != 0)
  174. {
  175. return bc;
  176. }
  177. int gc = Integer.valueOf(groupNumber).compareTo(Integer.valueOf(o.groupNumber));
  178. if (gc != 0)
  179. {
  180. return gc;
  181. }
  182. return importValue.compareTo(o.importValue);
  183. }
  184. @Override
  185. public String toString()
  186. {
  187. return (isStatic ? "static " : "") + importValue; // + " (matches group " + groupNumber + ")";
  188. }
  189. }
  190. }