001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2018 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018//////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.gui; 021 022import java.io.File; 023import java.io.IOException; 024import java.nio.charset.StandardCharsets; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.Locale; 028 029import com.puppycrawl.tools.checkstyle.JavaParser; 030import com.puppycrawl.tools.checkstyle.api.CheckstyleException; 031import com.puppycrawl.tools.checkstyle.api.DetailAST; 032import com.puppycrawl.tools.checkstyle.api.FileText; 033 034/** 035 * Model for checkstyle frame. 036 */ 037public class MainFrameModel { 038 039 /** 040 * Parsing modes which available in GUI. 041 */ 042 public enum ParseMode { 043 044 /** Only Java tokens without comments. */ 045 PLAIN_JAVA("Plain Java"), 046 047 /** Java tokens and comment nodes (singleline comments and block comments). */ 048 JAVA_WITH_COMMENTS("Java with comments"), 049 050 /** 051 * Java tokens, comments and Javadoc comments nodes 052 * (which are parsed from block comments). 053 */ 054 JAVA_WITH_JAVADOC_AND_COMMENTS("Java with comments and Javadocs"); 055 056 /** 057 * Mode's short description. 058 */ 059 private final String description; 060 061 /** 062 * Provides description. 063 * @param descr description 064 */ 065 ParseMode(String descr) { 066 description = descr; 067 } 068 069 @Override 070 public String toString() { 071 return description; 072 } 073 074 } 075 076 /** Parse tree model. */ 077 private final ParseTreeTableModel parseTreeTableModel; 078 079 /** Lines to position map. */ 080 private List<Integer> linesToPosition = new ArrayList<>(); 081 082 /** Current mode. */ 083 private ParseMode parseMode = ParseMode.PLAIN_JAVA; 084 085 /** The file which is being parsed. */ 086 private File currentFile; 087 088 /** Text for a frame's text area. */ 089 private String text; 090 091 /** Title for the main frame. */ 092 private String title = "Checkstyle GUI"; 093 094 /** Whether the reload action is enabled. */ 095 private boolean reloadActionEnabled; 096 097 /** Instantiate the model. */ 098 public MainFrameModel() { 099 parseTreeTableModel = new ParseTreeTableModel(null); 100 } 101 102 /** 103 * Set current parse mode. 104 * @param mode ParseMode enum. 105 */ 106 public void setParseMode(ParseMode mode) { 107 parseMode = mode; 108 } 109 110 /** 111 * Get parse tree table model. 112 * @return parse tree table model. 113 */ 114 public ParseTreeTableModel getParseTreeTableModel() { 115 return parseTreeTableModel; 116 } 117 118 /** 119 * Get text to display in a text area. 120 * @return text to display in a text area. 121 */ 122 public String getText() { 123 return text; 124 } 125 126 /** 127 * Returns title for the main frame. 128 * @return title for the main frame. 129 */ 130 public String getTitle() { 131 return title; 132 } 133 134 /** 135 * Returns true if the reload action is enabled, false otherwise. 136 * @return true if the reload action is enabled. 137 */ 138 public boolean isReloadActionEnabled() { 139 return reloadActionEnabled; 140 } 141 142 /** 143 * Whether a file chooser should accept the file as a source file. 144 * @param file the file to check. 145 * @return true if the file should be accepted. 146 */ 147 public static boolean shouldAcceptFile(File file) { 148 return file.isDirectory() || file.getName().endsWith(".java"); 149 } 150 151 /** 152 * Get the directory of the last loaded file. 153 * @return directory of the last loaded file. 154 */ 155 public File getLastDirectory() { 156 File lastDirectory = null; 157 if (currentFile != null) { 158 lastDirectory = new File(currentFile.getParent()); 159 } 160 return lastDirectory; 161 } 162 163 /** 164 * Get current file. 165 * @return current file. 166 */ 167 public File getCurrentFile() { 168 return currentFile; 169 } 170 171 /** 172 * Get lines to position map. 173 * It returns unmodifiable collection to 174 * prevent additional overhead of copying 175 * and possible state modifications. 176 * @return lines to position map. 177 */ 178 public List<Integer> getLinesToPosition() { 179 return new ArrayList<>(linesToPosition); 180 } 181 182 /** 183 * Open file and load the file. 184 * @param file the file to open. 185 * @throws CheckstyleException if the file can not be parsed. 186 */ 187 public void openFile(File file) throws CheckstyleException { 188 if (file != null) { 189 try { 190 currentFile = file; 191 title = "Checkstyle GUI : " + file.getName(); 192 reloadActionEnabled = true; 193 final DetailAST parseTree; 194 195 switch (parseMode) { 196 case PLAIN_JAVA: 197 parseTree = JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS); 198 break; 199 case JAVA_WITH_COMMENTS: 200 case JAVA_WITH_JAVADOC_AND_COMMENTS: 201 parseTree = JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS); 202 break; 203 default: 204 throw new IllegalArgumentException("Unknown mode: " + parseMode); 205 } 206 207 parseTreeTableModel.setParseTree(parseTree); 208 parseTreeTableModel.setParseMode(parseMode); 209 final String[] sourceLines = getFileText(file).toLinesArray(); 210 211 final List<Integer> linesToPositionTemp = new ArrayList<>(); 212 // starts line counting at 1 213 linesToPositionTemp.add(0); 214 215 final StringBuilder sb = new StringBuilder(1024); 216 // insert the contents of the file to the text area 217 for (final String element : sourceLines) { 218 linesToPositionTemp.add(sb.length()); 219 sb.append(element).append(System.lineSeparator()); 220 } 221 linesToPosition = linesToPositionTemp; 222 text = sb.toString(); 223 } 224 catch (IOException ex) { 225 final String exceptionMsg = String.format(Locale.ROOT, 226 "%s occurred while opening file %s.", 227 ex.getClass().getSimpleName(), file.getPath()); 228 throw new CheckstyleException(exceptionMsg, ex); 229 } 230 } 231 } 232 233 /** 234 * Get FileText from a file. 235 * @param file the file to get the FileText from. 236 * @return the FileText. 237 * @throws IOException if the file could not be read. 238 */ 239 private static FileText getFileText(File file) throws IOException { 240 return new FileText(file.getAbsoluteFile(), 241 System.getProperty("file.encoding", StandardCharsets.UTF_8.name())); 242 } 243 244}