Added
Link Here
|
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2004 Ben Konrath <ben@bagu.org> |
3 |
* Copyright (c) 2006 Red Hat Incorporated |
4 |
* All rights reserved. This program and the accompanying materials |
5 |
* are made available under the terms of the Eclipse Public License v1.0 |
6 |
* which accompanies this distribution, and is available at |
7 |
* http://www.eclipse.org/legal/epl-v10.html |
8 |
* |
9 |
* Contributors: |
10 |
* Ben Konrath <ben@bagu.org> - initial implementation |
11 |
* Red Hat Incorporated - improvements based on comments from JDT developers |
12 |
*******************************************************************************/ |
13 |
|
14 |
package org.eclipse.jdt.core.formatter; |
15 |
|
16 |
import java.io.BufferedReader; |
17 |
import java.io.BufferedWriter; |
18 |
import java.io.File; |
19 |
import java.io.FileInputStream; |
20 |
import java.io.FileReader; |
21 |
import java.io.FileWriter; |
22 |
import java.io.IOException; |
23 |
import java.io.Writer; |
24 |
import java.text.MessageFormat; |
25 |
import java.util.ArrayList; |
26 |
import java.util.MissingResourceException; |
27 |
import java.util.Properties; |
28 |
import java.util.ResourceBundle; |
29 |
|
30 |
import org.eclipse.core.runtime.IPlatformRunnable; |
31 |
import org.eclipse.core.runtime.Platform; |
32 |
import org.eclipse.jdt.core.ToolFactory; |
33 |
import org.eclipse.jdt.internal.core.util.Util; |
34 |
import org.eclipse.jface.text.BadLocationException; |
35 |
import org.eclipse.jface.text.Document; |
36 |
import org.eclipse.jface.text.IDocument; |
37 |
import org.eclipse.text.edits.TextEdit; |
38 |
|
39 |
/** |
40 |
* Implements an Eclipse Application for org.eclipse.jdt.core.JavaCodeFormatter. |
41 |
* |
42 |
* There are a couple improvments that could be made: |
43 |
* 1. Make a list of all the files first so that a file does not get formatted twice. |
44 |
* 2. Use a text based progress monitor for output. |
45 |
* |
46 |
* @author Ben Konrath <bkonrath@redhat.com> |
47 |
* @since 3.2 |
48 |
*/ |
49 |
public class CodeFormatterApplication implements IPlatformRunnable { |
50 |
|
51 |
/** |
52 |
* Deals with the messages in the properties file (cut n' pasted from a |
53 |
* generated class). |
54 |
*/ |
55 |
private final static class FormatterAppMessages { |
56 |
private static final String BUNDLE_NAME = "org.eclipse.jdt.core.formatter.FormatterAppMessages";//$NON-NLS-1$ |
57 |
|
58 |
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME); |
59 |
|
60 |
public static String getString(String key) { |
61 |
try { |
62 |
return RESOURCE_BUNDLE.getString(key); |
63 |
} catch (MissingResourceException e) { |
64 |
return '!' + key + '!'; |
65 |
} |
66 |
} |
67 |
|
68 |
public static String getFormattedString(String key, String arg) { |
69 |
return getFormattedString(key, new String[] { arg }); |
70 |
} |
71 |
|
72 |
public static String getFormattedString(String key, String[] args) { |
73 |
return MessageFormat.format(getString(key), args); |
74 |
} |
75 |
} |
76 |
|
77 |
/** |
78 |
* Return a Java Properties file representing the options that are in the specified config file. |
79 |
*/ |
80 |
public Properties readConfig(String filename) { |
81 |
FileInputStream reader = null; |
82 |
try { |
83 |
reader = new FileInputStream(new File(filename)); |
84 |
final Properties formatterOptions = new Properties(); |
85 |
formatterOptions.load(reader); |
86 |
return formatterOptions; |
87 |
} catch (IOException e) { |
88 |
Util.log(e, FormatterAppMessages.getString("ConfigFile.reading.error")); //$NON-NLS-1$ |
89 |
} finally { |
90 |
try { |
91 |
if (reader != null) |
92 |
reader.close(); |
93 |
} catch (IOException e) { /* ignore */ } |
94 |
} |
95 |
return null; |
96 |
} |
97 |
|
98 |
/** |
99 |
* Runs the Java code formatter application |
100 |
*/ |
101 |
public Object run(Object args) throws Exception { |
102 |
|
103 |
ArrayList fileList = processCommandLine((String[]) args); |
104 |
|
105 |
// nothing to do |
106 |
if (fileList == null || fileList.isEmpty()) |
107 |
return EXIT_OK; |
108 |
|
109 |
if (!quiet) { |
110 |
if (configName != null) |
111 |
System.out.println(FormatterAppMessages.getFormattedString("CommandLine.config.file", configName)); //$NON-NLS-1$ |
112 |
System.out.println(FormatterAppMessages.getString("CommandLine.start")); //$NON-NLS-1$ |
113 |
} |
114 |
|
115 |
// format the list of files and/or directories |
116 |
while (!fileList.isEmpty()) { |
117 |
File file = (File) fileList.remove(0); |
118 |
|
119 |
if (file.isDirectory()) |
120 |
formatDirTree(file); |
121 |
else |
122 |
formatFile(file); |
123 |
} |
124 |
|
125 |
if (!quiet) { |
126 |
System.out.println(FormatterAppMessages.getString("CommandLine.done")); //$NON-NLS-1$ |
127 |
} |
128 |
|
129 |
return EXIT_OK; |
130 |
} |
131 |
|
132 |
private void displayHelp(String message) { |
133 |
System.err.println(message); |
134 |
System.out.println(""); //$NON-NLS-1$ |
135 |
displayHelp(); |
136 |
} |
137 |
|
138 |
private String configName; |
139 |
|
140 |
/* |
141 |
* The output will look like this: |
142 |
* |
143 |
* "Usage: eclipse -application org.eclipse.jdt.core.JavaCodeFormatter [ OPTIONS ] <files> |
144 |
* <files> Java source files and/or directories to format. |
145 |
* Only files ending with .java will be formatted in the given directory. |
146 |
* OPTIONS: |
147 |
* -config <file> Use the formatting style from the specified properties file. |
148 |
* Refer to the help documentation to find out how to generate this file.. |
149 |
* -help Display this message. |
150 |
* -quiet Only print error messages. |
151 |
* -verbose Be verbose about the formatting job. |
152 |
*/ |
153 |
private void displayHelp() { |
154 |
String binaryName = Platform.getOS().equals(Platform.OS_WIN32) ? "eclipse.exe" : "eclipse"; //$NON-NLS-1$ //$NON-NLS-2$ |
155 |
|
156 |
// this is UG-LY. is there a way to make this look nicer? |
157 |
System.out.println(FormatterAppMessages.getFormattedString("CommandLine.usage", //$NON-NLS-1$ |
158 |
binaryName + " -application org.eclipse.jdt.core.JavaCodeFormatter")); //$NON-NLS-1$ |
159 |
System.out.println(""); //$NON-NLS-1$ |
160 |
|
161 |
System.out.println(" " + FormatterAppMessages.getString("CommandLine.files") //$NON-NLS-1$ //$NON-NLS-2$ |
162 |
+ "\t" + FormatterAppMessages.getString("CommandLine.files.msg1")); //$NON-NLS-1$ //$NON-NLS-2$ |
163 |
System.out.println("\t\t" + FormatterAppMessages.getFormattedString("CommandLine.files.msg2", ".java")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
164 |
|
165 |
System.out.println(FormatterAppMessages.getString("CommandLine.options")); //$NON-NLS-1$ |
166 |
System.out.println(" " + FormatterAppMessages.getFormattedString("CommandLine.config", ARG_CONFIG) //$NON-NLS-1$ //$NON-NLS-2$ |
167 |
+ "\t" + FormatterAppMessages.getString("CommandLine.config.msg1")); //$NON-NLS-1$ //$NON-NLS-2$ |
168 |
System.out.println("\t\t\t" + FormatterAppMessages.getString("CommandLine.config.msg2")); //$NON-NLS-1$ //$NON-NLS-2$ |
169 |
System.out.println(" " + ARG_HELP + "\t\t" + FormatterAppMessages.getString("CommandLine.help")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
170 |
System.out.println(" " + ARG_QUIET + "\t\t" + FormatterAppMessages.getString("CommandLine.quiet")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
171 |
System.out.println(" " + ARG_VERBOSE +"\t\t" + FormatterAppMessages.getString("CommandLine.verbose")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
172 |
} |
173 |
|
174 |
private final String ARG_HELP = "-help"; //$NON-NLS-1$ |
175 |
private final String ARG_CONFIG = "-config"; //$NON-NLS-1$ |
176 |
private final String ARG_VERBOSE = "-verbose"; //$NON-NLS-1$ |
177 |
private final String ARG_QUIET = "-quiet"; //$NON-NLS-1$ |
178 |
private boolean verbose = false; |
179 |
private boolean quiet = false; |
180 |
|
181 |
private ArrayList processCommandLine(String[] argsArray) { |
182 |
|
183 |
ArrayList args = new ArrayList(); |
184 |
for (int i = 0; i < argsArray.length; i++) { |
185 |
args.add(argsArray[i]); |
186 |
} |
187 |
|
188 |
// look for flag-like args |
189 |
if (args.remove(ARG_HELP)) { |
190 |
displayHelp(); |
191 |
return null; |
192 |
} |
193 |
if (args.remove(ARG_VERBOSE)) |
194 |
verbose = true; |
195 |
if (args.remove(ARG_QUIET)) |
196 |
quiet = true; |
197 |
|
198 |
if (quiet && verbose) { |
199 |
displayHelp(FormatterAppMessages.getFormattedString |
200 |
("CommandLineError.quiet.verbose", new String[] {ARG_QUIET, ARG_VERBOSE})); //$NON-NLS-1$ |
201 |
return null; |
202 |
} |
203 |
args.remove("-pdelaunch"); //$NON-NLS-1$ |
204 |
|
205 |
// look for flag/param args |
206 |
int index = args.indexOf(ARG_CONFIG); |
207 |
if (index >= 0) { |
208 |
args.remove(index); |
209 |
String configFile = (String) args.remove(index); |
210 |
options = readConfig(configFile); |
211 |
if (options == null) { |
212 |
displayHelp(FormatterAppMessages.getFormattedString("CommandLineError.config", configFile)); //$NON-NLS-1$ |
213 |
return null; |
214 |
} |
215 |
} |
216 |
|
217 |
// only the files and directories should remain |
218 |
ArrayList fileList = new ArrayList(); |
219 |
while (!args.isEmpty()) { |
220 |
String fileName = (String) args.remove(0); |
221 |
File file = new File(fileName); |
222 |
if (file.exists()) { |
223 |
fileList.add(file); |
224 |
} else { |
225 |
displayHelp(FormatterAppMessages |
226 |
.getFormattedString("CommandLineError.file", fileName)); //$NON-NLS-1$ |
227 |
return null; |
228 |
} |
229 |
} |
230 |
|
231 |
if (fileList.isEmpty()) |
232 |
displayHelp(FormatterAppMessages.getString("CommandLineError.file.dir")); //$NON-NLS-1$ |
233 |
|
234 |
return fileList; |
235 |
} |
236 |
|
237 |
/** |
238 |
* Recursively format the Java source code that is contained in the |
239 |
* directory rooted at dir. |
240 |
*/ |
241 |
private void formatDirTree(File dir) { |
242 |
|
243 |
File[] files = dir.listFiles(); |
244 |
if (files == null) |
245 |
return; |
246 |
|
247 |
for (int i = 0; i < files.length; i++) { |
248 |
File file = files[i]; |
249 |
if (file.isDirectory()) { |
250 |
formatDirTree(file); |
251 |
} else if (file.getPath().endsWith(".java")) { //$NON-NLS-1$ |
252 |
formatFile(file); |
253 |
} |
254 |
} |
255 |
} |
256 |
|
257 |
private Properties options = null; |
258 |
|
259 |
/** |
260 |
* Format the given Java source file. |
261 |
*/ |
262 |
private void formatFile(File file) { |
263 |
|
264 |
IDocument doc = new Document(); |
265 |
try { |
266 |
// read the file |
267 |
final BufferedReader in = new BufferedReader(new FileReader(file)); |
268 |
if (verbose) { |
269 |
System.out.println(FormatterAppMessages.getFormattedString |
270 |
("CommandLine.formatting", file.getName())); //$NON-NLS-1$ |
271 |
} |
272 |
String line; |
273 |
String contents = ""; //$NON-NLS-1$ |
274 |
try { |
275 |
while ((line = in.readLine()) != null) |
276 |
contents = contents + System.getProperty("line.separator") + line; //$NON-NLS-1$ |
277 |
} finally { |
278 |
try { in.close(); } catch (IOException e) { /* ignore */ } |
279 |
} |
280 |
|
281 |
// format the file (the meat and potatoes) |
282 |
doc.set(contents); |
283 |
TextEdit edit = ToolFactory.createCodeFormatter(options).format(CodeFormatter.K_COMPILATION_UNIT, |
284 |
doc.get(), 0, doc.getLength(), 0, null); |
285 |
if (edit != null) { |
286 |
edit.apply(doc); |
287 |
} else { |
288 |
System.err.println(FormatterAppMessages.getFormattedString("Edit.problem", file.getName())); //$NON-NLS-1$ |
289 |
return; |
290 |
} |
291 |
|
292 |
// write the file |
293 |
final Writer out = new BufferedWriter(new FileWriter(file, false)); |
294 |
try { |
295 |
out.write(doc.get()); |
296 |
out.flush(); |
297 |
} finally { |
298 |
try { out.close(); } catch (IOException e) { /* ignore */ } |
299 |
} |
300 |
|
301 |
} catch (IOException e) { |
302 |
String errorMessage = FormatterAppMessages.getString("Exception.io") + " " //$NON-NLS-1$ //$NON-NLS-2$ |
303 |
+ e.getLocalizedMessage(); |
304 |
Util.log(e, errorMessage); |
305 |
System.err.println(errorMessage); |
306 |
System.err.println(FormatterAppMessages.getString("Exception.skip")); //$NON-NLS-1$ |
307 |
|
308 |
} catch (BadLocationException e) { |
309 |
String errorMessage = FormatterAppMessages.getString("Exception.bad.location") + " " //$NON-NLS-1$ //$NON-NLS-2$ |
310 |
+ e.getLocalizedMessage(); |
311 |
Util.log(e, errorMessage); |
312 |
System.err.println(errorMessage); |
313 |
System.err.println(FormatterAppMessages.getString("Exception.skip")); //$NON-NLS-1$ |
314 |
} |
315 |
} |
316 |
|
317 |
} |