1 /*******************************************************************************
2 * Copyright (c) 2000, 2019 IBM Corporation and others.
3 *
4 * This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License 2.0
6 * which accompanies this distribution, and is available at
7 * https://www.eclipse.org/legal/epl-2.0/
8 *
9 * SPDX-License-Identifier: EPL-2.0
10 *
11 * Contributors:
12 * IBM Corporation - initial API and implementation
13 * Tom Tromey - Contribution for bug 125961
14 * Tom Tromey - Contribution for bug 159641
15 * Benjamin Muskalla - Contribution for bug 239066
16 * Stephan Herrmann - Contributions for
17 * bug 236385 - [compiler] Warn for potential programming problem if an object is created but not used
18 * bug 295551 - Add option to automatically promote all warnings to errors
19 * bug 359721 - [options] add command line option for new warning token "resource"
20 * bug 365208 - [compiler][batch] command line options for annotation based null analysis
21 * bug 374605 - Unreasonable warning for enum-based switch statements
22 * bug 375366 - ECJ ignores unusedParameterIncludeDocCommentReference unless enableJavadoc option is set
23 * bug 388281 - [compiler][null] inheritance of null annotations as an option
24 * bug 381443 - [compiler][null] Allow parameter widening from @NonNull to unannotated
25 * Bug 440477 - [null] Infrastructure for feeding external annotations into compilation
26 * Bug 440687 - [compiler][batch][null] improve command line option for external annotations
27 * Bug 408815 - [batch][null] Add CLI option for COMPILER_PB_SYNTACTIC_NULL_ANALYSIS_FOR_FIELDS
28 * Jesper S Moller - Contributions for
29 * bug 407297 - [1.8][compiler] Control generation of parameter names by option
30 * Mat Booth - Contribution for bug 405176
31 * Frits Jalvingh - fix for bug 533830.
32 *******************************************************************************/
33 package org.eclipse.jdt.internal.compiler.batch;
34
35 import java.io.BufferedInputStream;
36 import java.io.ByteArrayInputStream;
37 import java.io.File;
38 import java.io.FileInputStream;
39 import java.io.FileNotFoundException;
40 import java.io.FileOutputStream;
41 import java.io.FileReader;
42 import java.io.FilenameFilter;
43 import java.io.IOException;
44 import java.io.InputStreamReader;
45 import java.io.LineNumberReader;
46 import java.io.OutputStreamWriter;
47 import java.io.PrintWriter;
48 import java.io.StringReader;
49 import java.io.StringWriter;
50 import java.io.UnsupportedEncodingException;
51 import java.lang.reflect.Field;
52 import java.lang.reflect.InvocationTargetException;
53 import java.lang.reflect.Method;
54 import java.nio.file.Path;
55 import java.nio.file.Paths;
56 import java.text.DateFormat;
57 import java.text.MessageFormat;
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.Collections;
61 import java.util.Comparator;
62 import java.util.Date;
63 import java.util.HashMap;
64 import java.util.HashSet;
65 import java.util.Iterator;
66 import java.util.List;
67 import java.util.Locale;
68 import java.util.Map;
69 import java.util.Map.Entry;
70 import java.util.MissingResourceException;
71 import java.util.Properties;
72 import java.util.ResourceBundle;
73 import java.util.Set;
74 import java.util.StringTokenizer;
75
76 import org.eclipse.jdt.core.compiler.CategorizedProblem;
77 import org.eclipse.jdt.core.compiler.CharOperation;
78 import org.eclipse.jdt.core.compiler.CompilationProgress;
79 import org.eclipse.jdt.core.compiler.IProblem;
80 import org.eclipse.jdt.core.compiler.batch.BatchCompiler;
81 import org.eclipse.jdt.internal.compiler.AbstractAnnotationProcessorManager;
82 import org.eclipse.jdt.internal.compiler.ClassFile;
83 import org.eclipse.jdt.internal.compiler.CompilationResult;
84 import org.eclipse.jdt.internal.compiler.Compiler;
85 import org.eclipse.jdt.internal.compiler.ICompilerRequestor;
86 import org.eclipse.jdt.internal.compiler.IErrorHandlingPolicy;
87 import org.eclipse.jdt.internal.compiler.IProblemFactory;
88 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
89 import org.eclipse.jdt.internal.compiler.batch.FileSystem.Classpath;
90 import org.eclipse.jdt.internal.compiler.batch.ModuleFinder.AddExport;
91 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
92 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
93 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
94 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
95 import org.eclipse.jdt.internal.compiler.env.AccessRule;
96 import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
97 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
98 import org.eclipse.jdt.internal.compiler.env.IModule;
99 import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport;
100 import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind;
101 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
102 import org.eclipse.jdt.internal.compiler.impl.CompilerStats;
103 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
104 import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
105 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
106 import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
107 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
108 import org.eclipse.jdt.internal.compiler.parser.Parser;
109 import org.eclipse.jdt.internal.compiler.problem.DefaultProblem;
110 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
111 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
112 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
113 import org.eclipse.jdt.internal.compiler.util.GenericXMLWriter;
114 import org.eclipse.jdt.internal.compiler.util.HashtableOfInt;
115 import org.eclipse.jdt.internal.compiler.util.HashtableOfObject;
116 import org.eclipse.jdt.internal.compiler.util.Messages;
117 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
118 import org.eclipse.jdt.internal.compiler.util.Util;
119
120 public class Main implements ProblemSeverities, SuffixConstants {
121
122 public static class Logger {
123 private PrintWriter err;
124 private PrintWriter log;
125 private Main main;
126 private PrintWriter out;
127 private HashMap<String, Object> parameters;
128 int tagBits;
129 private static final String CLASS = "class"; //$NON-NLS-1$
130 private static final String CLASS_FILE = "classfile"; //$NON-NLS-1$
131 private static final String CLASSPATH = "classpath"; //$NON-NLS-1$
132 private static final String CLASSPATH_FILE = "FILE"; //$NON-NLS-1$
133 private static final String CLASSPATH_FOLDER = "FOLDER"; //$NON-NLS-1$
134 private static final String CLASSPATH_ID = "id"; //$NON-NLS-1$
135 private static final String CLASSPATH_JAR = "JAR"; //$NON-NLS-1$
136 private static final String CLASSPATHS = "classpaths"; //$NON-NLS-1$
137 private static final String COMMAND_LINE_ARGUMENT = "argument"; //$NON-NLS-1$
138 private static final String COMMAND_LINE_ARGUMENTS = "command_line"; //$NON-NLS-1$
139 private static final String COMPILER = "compiler"; //$NON-NLS-1$
140 private static final String COMPILER_COPYRIGHT = "copyright"; //$NON-NLS-1$
141 private static final String COMPILER_NAME = "name"; //$NON-NLS-1$
142 private static final String COMPILER_VERSION = "version"; //$NON-NLS-1$
143 public static final int EMACS = 2;
144 private static final String ERROR = "ERROR"; //$NON-NLS-1$
145 private static final String ERROR_TAG = "error"; //$NON-NLS-1$
146 private static final String WARNING_TAG = "warning"; //$NON-NLS-1$
147 private static final String EXCEPTION = "exception"; //$NON-NLS-1$
148 private static final String EXTRA_PROBLEM_TAG = "extra_problem"; //$NON-NLS-1$
149 private static final String EXTRA_PROBLEMS = "extra_problems"; //$NON-NLS-1$
150 private static final HashtableOfInt FIELD_TABLE = new HashtableOfInt();
151 private static final String KEY = "key"; //$NON-NLS-1$
152 private static final String MESSAGE = "message"; //$NON-NLS-1$
153 private static final String NUMBER_OF_CLASSFILES = "number_of_classfiles"; //$NON-NLS-1$
154 private static final String NUMBER_OF_ERRORS = "errors"; //$NON-NLS-1$
155 private static final String NUMBER_OF_LINES = "number_of_lines"; //$NON-NLS-1$
156 private static final String NUMBER_OF_PROBLEMS = "problems"; //$NON-NLS-1$
157 private static final String NUMBER_OF_TASKS = "tasks"; //$NON-NLS-1$
158 private static final String NUMBER_OF_WARNINGS = "warnings"; //$NON-NLS-1$
159 private static final String NUMBER_OF_INFOS = "infos"; //$NON-NLS-1$
160 private static final String OPTION = "option"; //$NON-NLS-1$
161 private static final String OPTIONS = "options"; //$NON-NLS-1$
162 private static final String OUTPUT = "output"; //$NON-NLS-1$
163 private static final String PACKAGE = "package"; //$NON-NLS-1$
164 private static final String PATH = "path"; //$NON-NLS-1$
165 private static final String PROBLEM_ARGUMENT = "argument"; //$NON-NLS-1$
166 private static final String PROBLEM_ARGUMENT_VALUE = "value"; //$NON-NLS-1$
167 private static final String PROBLEM_ARGUMENTS = "arguments"; //$NON-NLS-1$
168 private static final String PROBLEM_CATEGORY_ID = "categoryID"; //$NON-NLS-1$
169 private static final String ID = "id"; //$NON-NLS-1$
170 private static final String PROBLEM_ID = "problemID"; //$NON-NLS-1$
171 private static final String PROBLEM_LINE = "line"; //$NON-NLS-1$
172 private static final String PROBLEM_OPTION_KEY = "optionKey"; //$NON-NLS-1$
173 private static final String PROBLEM_MESSAGE = "message"; //$NON-NLS-1$
174 private static final String PROBLEM_SEVERITY = "severity"; //$NON-NLS-1$
175 private static final String PROBLEM_SOURCE_END = "charEnd"; //$NON-NLS-1$
176 private static final String PROBLEM_SOURCE_START = "charStart"; //$NON-NLS-1$
177 private static final String PROBLEM_SUMMARY = "problem_summary"; //$NON-NLS-1$
178 private static final String PROBLEM_TAG = "problem"; //$NON-NLS-1$
179 private static final String PROBLEMS = "problems"; //$NON-NLS-1$
180 private static final String SOURCE = "source"; //$NON-NLS-1$
181 private static final String SOURCE_CONTEXT = "source_context"; //$NON-NLS-1$
182 private static final String SOURCE_END = "sourceEnd"; //$NON-NLS-1$
183 private static final String SOURCE_START = "sourceStart"; //$NON-NLS-1$
184 private static final String SOURCES = "sources"; //$NON-NLS-1$
185
186 private static final String STATS = "stats"; //$NON-NLS-1$
187
188 private static final String TASK = "task"; //$NON-NLS-1$
189 private static final String TASKS = "tasks"; //$NON-NLS-1$
190 private static final String TIME = "time"; //$NON-NLS-1$
191 private static final String VALUE = "value"; //$NON-NLS-1$
192 private static final String WARNING = "WARNING"; //$NON-NLS-1$
193 private static final String INFO = "INFO"; //$NON-NLS-1$
194
195 public static final int XML = 1;
196 private static final String XML_DTD_DECLARATION = "<!DOCTYPE compiler PUBLIC \"-//Eclipse.org//DTD Eclipse JDT 3.2.006 Compiler//EN\" \"http://www.eclipse.org/jdt/core/compiler_32_006.dtd\">"; //$NON-NLS-1$
197 static {
198 try {
199 Class<?> c = IProblem.class;
200 Field[] fields = c.getFields();
201 for (int i = 0, max = fields.length; i < max; i++) {
202 Field field = fields[i];
203 if (field.getType().equals(Integer.TYPE)) {
204 Integer value = (Integer) field.get(null);
205 int key2 = value.intValue() & IProblem.IgnoreCategoriesMask;
206 if (key2 == 0) {
207 key2 = Integer.MAX_VALUE;
208 }
Logger.FIELD_TABLE.put(key2, field.getName())209 Logger.FIELD_TABLE.put(key2, field.getName());
210 }
211 }
212 } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
213 e.printStackTrace();
214 }
215 }
Logger(Main main, PrintWriter out, PrintWriter err)216 public Logger(Main main, PrintWriter out, PrintWriter err) {
217 this.out = out;
218 this.err = err;
219 this.parameters = new HashMap<>();
220 this.main = main;
221 }
222
buildFileName( String outputPath, String relativeFileName)223 public String buildFileName(
224 String outputPath,
225 String relativeFileName) {
226 char fileSeparatorChar = File.separatorChar;
227 String fileSeparator = File.separator;
228
229 outputPath = outputPath.replace('/', fileSeparatorChar);
230 // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
231 StringBuffer outDir = new StringBuffer(outputPath);
232 if (!outputPath.endsWith(fileSeparator)) {
233 outDir.append(fileSeparator);
234 }
235 StringTokenizer tokenizer =
236 new StringTokenizer(relativeFileName, fileSeparator);
237 String token = tokenizer.nextToken();
238 while (tokenizer.hasMoreTokens()) {
239 outDir.append(token).append(fileSeparator);
240 token = tokenizer.nextToken();
241 }
242 // token contains the last one
243 return outDir.append(token).toString();
244 }
245
close()246 public void close() {
247 if (this.log != null) {
248 if ((this.tagBits & Logger.XML) != 0) {
249 endTag(Logger.COMPILER);
250 flush();
251 }
252 this.log.close();
253 }
254 }
255
256 /**
257 *
258 */
compiling()259 public void compiling() {
260 printlnOut(this.main.bind("progress.compiling")); //$NON-NLS-1$
261 }
endLoggingExtraProblems()262 private void endLoggingExtraProblems() {
263 endTag(Logger.EXTRA_PROBLEMS);
264 }
265 /**
266 * Used to stop logging problems.
267 * Only use in xml mode.
268 */
endLoggingProblems()269 private void endLoggingProblems() {
270 endTag(Logger.PROBLEMS);
271 }
endLoggingSource()272 public void endLoggingSource() {
273 if ((this.tagBits & Logger.XML) != 0) {
274 endTag(Logger.SOURCE);
275 }
276 }
277
endLoggingSources()278 public void endLoggingSources() {
279 if ((this.tagBits & Logger.XML) != 0) {
280 endTag(Logger.SOURCES);
281 }
282 }
283
endLoggingTasks()284 public void endLoggingTasks() {
285 if ((this.tagBits & Logger.XML) != 0) {
286 endTag(Logger.TASKS);
287 }
288 }
endTag(String name)289 private void endTag(String name) {
290 if (this.log != null) {
291 ((GenericXMLWriter) this.log).endTag(name, true, true);
292 }
293 }
errorReportSource(CategorizedProblem problem, char[] unitSource, int bits)294 private String errorReportSource(CategorizedProblem problem, char[] unitSource, int bits) {
295 //extra from the source the innacurate token
296 //and "highlight" it using some underneath ^^^^^
297 //put some context around too.
298
299 //this code assumes that the font used in the console is fixed size
300
301 //sanity .....
302 int startPosition = problem.getSourceStart();
303 int endPosition = problem.getSourceEnd();
304 if (unitSource == null) {
305 if (problem.getOriginatingFileName() != null) {
306 try {
307 unitSource = Util.getFileCharContent(new File(new String(problem.getOriginatingFileName())), null);
308 } catch (IOException e) {
309 // ignore;
310 }
311 }
312 }
313 int length;
314 if ((startPosition > endPosition)
315 || ((startPosition < 0) && (endPosition < 0))
316 || (unitSource == null)
317 || (length = unitSource.length) == 0)
318 return Messages.problem_noSourceInformation;
319
320 StringBuffer errorBuffer = new StringBuffer();
321 if ((bits & Main.Logger.EMACS) == 0) {
322 errorBuffer.append(' ').append(Messages.bind(Messages.problem_atLine, String.valueOf(problem.getSourceLineNumber())));
323 errorBuffer.append(Util.LINE_SEPARATOR);
324 }
325 errorBuffer.append('\t');
326
327 char c;
328 final char SPACE = '\u0020';
329 final char MARK = '^';
330 final char TAB = '\t';
331 //the next code tries to underline the token.....
332 //it assumes (for a good display) that token source does not
333 //contain any \r \n. This is false on statements !
334 //(the code still works but the display is not optimal !)
335
336 // expand to line limits
337 int begin;
338 int end;
339 for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) {
340 if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
341 }
342 for (end = endPosition >= length ? length - 1 : endPosition ; end+1 < length; end++) {
343 if ((c = unitSource[end + 1]) == '\r' || c == '\n') break;
344 }
345
346 // trim left and right spaces/tabs
347 while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
348 //while ((c = unitSource[end]) == ' ' || c == '\t') end--; TODO (philippe) should also trim right, but all tests are to be updated
349
350 // copy source
351 errorBuffer.append(unitSource, begin, end-begin+1);
352 errorBuffer.append(Util.LINE_SEPARATOR).append("\t"); //$NON-NLS-1$
353
354 // compute underline
355 for (int i = begin; i <startPosition; i++) {
356 errorBuffer.append((unitSource[i] == TAB) ? TAB : SPACE);
357 }
358 for (int i = startPosition; i <= (endPosition >= length ? length - 1 : endPosition); i++) {
359 errorBuffer.append(MARK);
360 }
361 return errorBuffer.toString();
362 }
363
extractContext(CategorizedProblem problem, char[] unitSource)364 private void extractContext(CategorizedProblem problem, char[] unitSource) {
365 //sanity .....
366 int startPosition = problem.getSourceStart();
367 int endPosition = problem.getSourceEnd();
368 if (unitSource == null) {
369 if (problem.getOriginatingFileName() != null) {
370 try {
371 unitSource = Util.getFileCharContent(new File(new String(problem.getOriginatingFileName())), null);
372 } catch(IOException e) {
373 // ignore
374 }
375 }
376 }
377 int length;
378 if ((startPosition > endPosition)
379 || ((startPosition < 0) && (endPosition < 0))
380 || (unitSource == null)
381 || ((length = unitSource.length) <= 0)
382 || (endPosition > length)) {
383 this.parameters.put(Logger.VALUE, Messages.problem_noSourceInformation);
384 this.parameters.put(Logger.SOURCE_START, "-1"); //$NON-NLS-1$
385 this.parameters.put(Logger.SOURCE_END, "-1"); //$NON-NLS-1$
386 printTag(Logger.SOURCE_CONTEXT, this.parameters, true, true);
387 return;
388 }
389
390 char c;
391 //the next code tries to underline the token.....
392 //it assumes (for a good display) that token source does not
393 //contain any \r \n. This is false on statements !
394 //(the code still works but the display is not optimal !)
395
396 // expand to line limits
397 int begin, end;
398 for (begin = startPosition >= length ? length - 1 : startPosition; begin > 0; begin--) {
399 if ((c = unitSource[begin - 1]) == '\n' || c == '\r') break;
400 }
401 for (end = endPosition >= length ? length - 1 : endPosition ; end+1 < length; end++) {
402 if ((c = unitSource[end + 1]) == '\r' || c == '\n') break;
403 }
404
405 // trim left and right spaces/tabs
406 while ((c = unitSource[begin]) == ' ' || c == '\t') begin++;
407 while ((c = unitSource[end]) == ' ' || c == '\t') end--;
408
409 // copy source
410 StringBuffer buffer = new StringBuffer();
411 buffer.append(unitSource, begin, end - begin + 1);
412
413 this.parameters.put(Logger.VALUE, String.valueOf(buffer));
414 this.parameters.put(Logger.SOURCE_START, Integer.toString(startPosition - begin));
415 this.parameters.put(Logger.SOURCE_END, Integer.toString(endPosition - begin));
416 printTag(Logger.SOURCE_CONTEXT, this.parameters, true, true);
417 }
flush()418 public void flush() {
419 this.out.flush();
420 this.err.flush();
421 if (this.log != null) {
422 this.log.flush();
423 }
424 }
425
getFieldName(int id)426 private String getFieldName(int id) {
427 int key2 = id & IProblem.IgnoreCategoriesMask;
428 if (key2 == 0) {
429 key2 = Integer.MAX_VALUE;
430 }
431 return (String) Logger.FIELD_TABLE.get(key2);
432 }
433
434 // find out an option name controlling a given problemID
getProblemOptionKey(int problemID)435 private String getProblemOptionKey(int problemID) {
436 int irritant = ProblemReporter.getIrritant(problemID);
437 return CompilerOptions.optionKeyFromIrritant(irritant);
438 }
439
logAverage()440 public void logAverage() {
441 Arrays.sort(this.main.compilerStats);
442 long lineCount = this.main.compilerStats[0].lineCount;
443 final int length = this.main.maxRepetition;
444 long sum = 0;
445 long parseSum = 0, resolveSum = 0, analyzeSum = 0, generateSum = 0;
446 for (int i = 1, max = length - 1; i < max; i++) {
447 CompilerStats stats = this.main.compilerStats[i];
448 sum += stats.elapsedTime();
449 parseSum += stats.parseTime;
450 resolveSum += stats.resolveTime;
451 analyzeSum += stats.analyzeTime;
452 generateSum += stats.generateTime;
453 }
454 long time = sum / (length - 2);
455 long parseTime = parseSum/(length - 2);
456 long resolveTime = resolveSum/(length - 2);
457 long analyzeTime = analyzeSum/(length - 2);
458 long generateTime = generateSum/(length - 2);
459 printlnOut(this.main.bind(
460 "compile.averageTime", //$NON-NLS-1$
461 new String[] {
462 String.valueOf(lineCount),
463 String.valueOf(time),
464 String.valueOf(((int) (lineCount * 10000.0 / time)) / 10.0),
465 }));
466 if ((this.main.timing & Main.TIMING_DETAILED) != 0) {
467 printlnOut(
468 this.main.bind("compile.detailedTime", //$NON-NLS-1$
469 new String[] {
470 String.valueOf(parseTime),
471 String.valueOf(((int) (parseTime * 1000.0 / time)) / 10.0),
472 String.valueOf(resolveTime),
473 String.valueOf(((int) (resolveTime * 1000.0 / time)) / 10.0),
474 String.valueOf(analyzeTime),
475 String.valueOf(((int) (analyzeTime * 1000.0 / time)) / 10.0),
476 String.valueOf(generateTime),
477 String.valueOf(((int) (generateTime * 1000.0 / time)) / 10.0),
478 }));
479 }
480 }
logClassFile(boolean generatePackagesStructure, String outputPath, String relativeFileName)481 public void logClassFile(boolean generatePackagesStructure, String outputPath, String relativeFileName) {
482 if ((this.tagBits & Logger.XML) != 0) {
483 String fileName = null;
484 if (generatePackagesStructure) {
485 fileName = buildFileName(outputPath, relativeFileName);
486 } else {
487 char fileSeparatorChar = File.separatorChar;
488 String fileSeparator = File.separator;
489 // First we ensure that the outputPath exists
490 outputPath = outputPath.replace('/', fileSeparatorChar);
491 // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
492 int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
493 if (indexOfPackageSeparator == -1) {
494 if (outputPath.endsWith(fileSeparator)) {
495 fileName = outputPath + relativeFileName;
496 } else {
497 fileName = outputPath + fileSeparator + relativeFileName;
498 }
499 } else {
500 int length = relativeFileName.length();
501 if (outputPath.endsWith(fileSeparator)) {
502 fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
503 } else {
504 fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
505 }
506 }
507 }
508 File f = new File(fileName);
509 try {
510 this.parameters.put(Logger.PATH, f.getCanonicalPath());
511 printTag(Logger.CLASS_FILE, this.parameters, true, true);
512 } catch (IOException e) {
513 logNoClassFileCreated(outputPath, relativeFileName, e);
514 }
515 }
516 }
logClasspath(FileSystem.Classpath[] classpaths)517 public void logClasspath(FileSystem.Classpath[] classpaths) {
518 if (classpaths == null) return;
519 if ((this.tagBits & Logger.XML) != 0) {
520 final int length = classpaths.length;
521 if (length != 0) {
522 // generate xml output
523 printTag(Logger.CLASSPATHS, null, true, false);
524 for (int i = 0; i < length; i++) {
525 String classpath = classpaths[i].getPath();
526 this.parameters.put(Logger.PATH, classpath);
527 File f = new File(classpath);
528 String id = null;
529 if (f.isFile()) {
530 int kind = Util.archiveFormat(classpath);
531 switch (kind) {
532 case Util.ZIP_FILE:
533 id = Logger.CLASSPATH_JAR;
534 break;
535 default:
536 id = Logger.CLASSPATH_FILE;
537 break;
538 }
539 } else if (f.isDirectory()) {
540 id = Logger.CLASSPATH_FOLDER;
541 }
542 if (id != null) {
543 this.parameters.put(Logger.CLASSPATH_ID, id);
544 printTag(Logger.CLASSPATH, this.parameters, true, true);
545 }
546 }
547 endTag(Logger.CLASSPATHS);
548 }
549 }
550
551 }
552
logCommandLineArguments(String[] commandLineArguments)553 public void logCommandLineArguments(String[] commandLineArguments) {
554 if (commandLineArguments == null) return;
555 if ((this.tagBits & Logger.XML) != 0) {
556 final int length = commandLineArguments.length;
557 if (length != 0) {
558 // generate xml output
559 printTag(Logger.COMMAND_LINE_ARGUMENTS, null, true, false);
560 for (int i = 0; i < length; i++) {
561 this.parameters.put(Logger.VALUE, commandLineArguments[i]);
562 printTag(Logger.COMMAND_LINE_ARGUMENT, this.parameters, true, true);
563 }
564 endTag(Logger.COMMAND_LINE_ARGUMENTS);
565 }
566 }
567 }
568
569 /**
570 * @param e the given exception to log
571 */
logException(Exception e)572 public void logException(Exception e) {
573 StringWriter writer = new StringWriter();
574 PrintWriter printWriter = new PrintWriter(writer);
575 e.printStackTrace(printWriter);
576 printWriter.flush();
577 printWriter.close();
578 final String stackTrace = writer.toString();
579 if ((this.tagBits & Logger.XML) != 0) {
580 LineNumberReader reader = new LineNumberReader(new StringReader(stackTrace));
581 String line;
582 int i = 0;
583 StringBuffer buffer = new StringBuffer();
584 String message = e.getMessage();
585 if (message != null) {
586 buffer.append(message).append(Util.LINE_SEPARATOR);
587 }
588 try {
589 while ((line = reader.readLine()) != null && i < 4) {
590 buffer.append(line).append(Util.LINE_SEPARATOR);
591 i++;
592 }
593 reader.close();
594 } catch (IOException e1) {
595 // ignore
596 }
597 message = buffer.toString();
598 this.parameters.put(Logger.MESSAGE, message);
599 this.parameters.put(Logger.CLASS, e.getClass());
600 printTag(Logger.EXCEPTION, this.parameters, true, true);
601 }
602 String message = e.getMessage();
603 if (message == null) {
604 this.printlnErr(stackTrace);
605 } else {
606 this.printlnErr(message);
607 }
608 }
609
logExtraProblem(CategorizedProblem problem, int localErrorCount, int globalErrorCount)610 private void logExtraProblem(CategorizedProblem problem, int localErrorCount, int globalErrorCount) {
611 char[] originatingFileName = problem.getOriginatingFileName();
612 if (originatingFileName == null) {
613 // simplified message output
614 String severity = problem.isError() ? "requestor.extraerror" //$NON-NLS-1$
615 : problem.isInfo() ? "requestor.extrainfo" : "requestor.extrawarning"; //$NON-NLS-1$ //$NON-NLS-2$
616 printErr(this.main.bind(
617 severity,
618 Integer.toString(globalErrorCount)));
619 printErr(" "); //$NON-NLS-1$
620 this.printlnErr(problem.getMessage());
621 } else {
622 String fileName = new String(originatingFileName);
623 if ((this.tagBits & Logger.EMACS) != 0) {
624 String severity = problem.isError() ? "output.emacs.error" : //$NON-NLS-1$
625 problem.isInfo() ? "output.emacs.info" //$NON-NLS-1$
626 : "output.emacs.warning"; //$NON-NLS-1$
627 String result = fileName
628 + ":" //$NON-NLS-1$
629 + problem.getSourceLineNumber()
630 + ": " //$NON-NLS-1$
631 + this.main.bind(severity)
632 + ": " //$NON-NLS-1$
633 + problem.getMessage();
634 this.printlnErr(result);
635 final String errorReportSource = errorReportSource(problem, null, this.tagBits);
636 this.printlnErr(errorReportSource);
637 } else {
638 if (localErrorCount == 0) {
639 this.printlnErr("----------"); //$NON-NLS-1$
640 }
641 String severity = problem.isError() ? "requestor.error" //$NON-NLS-1$
642 : problem.isInfo() ? "requestor.info" : "requestor.warning"; //$NON-NLS-1$ //$NON-NLS-2$
643 printErr(this.main.bind(
644 severity,
645 Integer.toString(globalErrorCount),
646 fileName));
647 final String errorReportSource = errorReportSource(problem, null, 0);
648 this.printlnErr(errorReportSource);
649 this.printlnErr(problem.getMessage());
650 this.printlnErr("----------"); //$NON-NLS-1$
651 }
652 }
653 }
654
loggingExtraProblems(Main currentMain)655 public void loggingExtraProblems(Main currentMain) {
656 ArrayList<CategorizedProblem> problems = currentMain.extraProblems;
657 final int count = problems.size();
658 int localProblemCount = 0;
659 if (count != 0) {
660 int errors = 0;
661 int warnings = 0;
662 int infos = 0;
663 for (int i = 0; i < count; i++) {
664 CategorizedProblem problem = problems.get(i);
665 if (!this.main.isIgnored(problem)) {
666 currentMain.globalProblemsCount++;
667 logExtraProblem(problem, localProblemCount, currentMain.globalProblemsCount);
668 localProblemCount++;
669 if (problem.isError()) {
670 errors++;
671 currentMain.globalErrorsCount++;
672 } else if (problem.isInfo()) {
673 currentMain.globalInfoCount++;
674 infos++;
675 } else {
676 currentMain.globalWarningsCount++;
677 warnings++;
678 }
679 }
680 }
681 if ((this.tagBits & Logger.XML) != 0) {
682 if ((errors + warnings + infos) != 0) {
683 startLoggingExtraProblems(count);
684 for (int i = 0; i < count; i++) {
685 CategorizedProblem problem = problems.get(i);
686 if (!this.main.isIgnored(problem)) {
687 if (problem.getID() != IProblem.Task) {
688 logXmlExtraProblem(problem, localProblemCount, currentMain.globalProblemsCount);
689 }
690 }
691 }
692 endLoggingExtraProblems();
693 }
694 }
695 }
696 }
697
logUnavaibleAPT(String className)698 public void logUnavaibleAPT(String className) {
699 if ((this.tagBits & Logger.XML) != 0) {
700 this.parameters.put(Logger.MESSAGE, this.main.bind("configure.unavailableAPT", className)); //$NON-NLS-1$
701 printTag(Logger.ERROR_TAG, this.parameters, true, true);
702 }
703 this.printlnErr(this.main.bind("configure.unavailableAPT", className)); //$NON-NLS-1$
704 }
705
logIncorrectVMVersionForAnnotationProcessing()706 public void logIncorrectVMVersionForAnnotationProcessing() {
707 if ((this.tagBits & Logger.XML) != 0) {
708 this.parameters.put(Logger.MESSAGE, this.main.bind("configure.incorrectVMVersionforAPT")); //$NON-NLS-1$
709 printTag(Logger.ERROR_TAG, this.parameters, true, true);
710 }
711 this.printlnErr(this.main.bind("configure.incorrectVMVersionforAPT")); //$NON-NLS-1$
712 }
713
714 /**
715 *
716 */
logNoClassFileCreated(String outputDir, String relativeFileName, IOException e)717 public void logNoClassFileCreated(String outputDir, String relativeFileName, IOException e) {
718 if ((this.tagBits & Logger.XML) != 0) {
719 this.parameters.put(Logger.MESSAGE, this.main.bind("output.noClassFileCreated", //$NON-NLS-1$
720 new String[] {
721 outputDir,
722 relativeFileName,
723 e.getMessage()
724 }));
725 printTag(Logger.ERROR_TAG, this.parameters, true, true);
726 }
727 this.printlnErr(this.main.bind("output.noClassFileCreated", //$NON-NLS-1$
728 new String[] {
729 outputDir,
730 relativeFileName,
731 e.getMessage()
732 }));
733 }
734
735 /**
736 * @param exportedClassFilesCounter
737 */
logNumberOfClassFilesGenerated(int exportedClassFilesCounter)738 public void logNumberOfClassFilesGenerated(int exportedClassFilesCounter) {
739 if ((this.tagBits & Logger.XML) != 0) {
740 this.parameters.put(Logger.VALUE, Integer.valueOf(exportedClassFilesCounter));
741 printTag(Logger.NUMBER_OF_CLASSFILES, this.parameters, true, true);
742 }
743 if (exportedClassFilesCounter == 1) {
744 printlnOut(this.main.bind("compile.oneClassFileGenerated")); //$NON-NLS-1$
745 } else {
746 printlnOut(this.main.bind("compile.severalClassFilesGenerated", //$NON-NLS-1$
747 String.valueOf(exportedClassFilesCounter)));
748 }
749 }
750
751 /**
752 * @param options the given compiler options
753 */
logOptions(Map<String, String> options)754 public void logOptions(Map<String, String> options) {
755 if ((this.tagBits & Logger.XML) != 0) {
756 printTag(Logger.OPTIONS, null, true, false);
757 final Set<Map.Entry<String, String>> entriesSet = options.entrySet();
758 Map.Entry<String, String>[] entries = entriesSet.toArray(new Map.Entry[entriesSet.size()]);
759 Arrays.sort(entries, new Comparator<Map.Entry<String, String>>() {
760 @Override
761 public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
762 Map.Entry<String, String> entry1 = o1;
763 Map.Entry<String, String> entry2 = o2;
764 return entry1.getKey().compareTo(entry2.getKey());
765 }
766 });
767 for (int i = 0, max = entries.length; i < max; i++) {
768 Map.Entry<String, String> entry = entries[i];
769 String key = entry.getKey();
770 this.parameters.put(Logger.KEY, key);
771 this.parameters.put(Logger.VALUE, entry.getValue());
772 printTag(Logger.OPTION, this.parameters, true, true);
773 }
774 endTag(Logger.OPTIONS);
775 }
776 }
777
778 /**
779 * @param error the given error
780 */
logPendingError(String error)781 public void logPendingError(String error) {
782 if ((this.tagBits & Logger.XML) != 0) {
783 this.parameters.put(Logger.MESSAGE, error);
784 printTag(Logger.ERROR_TAG, this.parameters, true, true);
785 }
786 this.printlnErr(error);
787 }
788
789 /**
790 * @param message the given message
791 */
logWarning(String message)792 public void logWarning(String message) {
793 if ((this.tagBits & Logger.XML) != 0) {
794 this.parameters.put(Logger.MESSAGE, message);
795 printTag(Logger.WARNING_TAG, this.parameters, true, true);
796 }
797 this.printlnOut(message);
798 }
799
logProblem(CategorizedProblem problem, int localErrorCount, int globalErrorCount, char[] unitSource)800 private void logProblem(CategorizedProblem problem, int localErrorCount,
801 int globalErrorCount, char[] unitSource) {
802 if(problem instanceof DefaultProblem) {
803 ((DefaultProblem) problem).reportError();
804 }
805 if ((this.tagBits & Logger.EMACS) != 0) {
806 String severity = problem.isError() ? "output.emacs.error" : //$NON-NLS-1$
807 problem.isInfo() ? "output.emacs.info" //$NON-NLS-1$
808 : "output.emacs.warning"; //$NON-NLS-1$
809 String result = (new String(problem.getOriginatingFileName())
810 + ":" //$NON-NLS-1$
811 + problem.getSourceLineNumber()
812 + ": " //$NON-NLS-1$
813 + (this.main.bind(severity))
814 + ": " //$NON-NLS-1$
815 + problem.getMessage());
816 this.printlnErr(result);
817 final String errorReportSource = errorReportSource(problem, unitSource, this.tagBits);
818 if (errorReportSource.length() != 0) this.printlnErr(errorReportSource);
819 } else {
820 if (localErrorCount == 0) {
821 this.printlnErr("----------"); //$NON-NLS-1$
822 }
823 String severity = problem.isError() ? "requestor.error" : problem.isInfo() ? "requestor.info" : "requestor.warning"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
824 printErr(this.main.bind(severity,
825 Integer.toString(globalErrorCount),
826 new String(problem.getOriginatingFileName())));
827 try {
828 final String errorReportSource = errorReportSource(problem, unitSource, 0);
829 this.printlnErr(errorReportSource);
830 this.printlnErr(problem.getMessage());
831 } catch (Exception e) {
832 this.printlnErr(this.main.bind(
833 "requestor.notRetrieveErrorMessage", problem.toString())); //$NON-NLS-1$
834 }
835 this.printlnErr("----------"); //$NON-NLS-1$
836 }
837 }
838
logProblems(CategorizedProblem[] problems, char[] unitSource, Main currentMain)839 public int logProblems(CategorizedProblem[] problems, char[] unitSource, Main currentMain) {
840 final int count = problems.length;
841 int localErrorCount = 0;
842 int localProblemCount = 0;
843 if (count != 0) {
844 int errors = 0;
845 int warnings = 0;
846 int infos = 0;
847 int tasks = 0;
848 for (int i = 0; i < count; i++) {
849 CategorizedProblem problem = problems[i];
850 if (problem != null) {
851 currentMain.globalProblemsCount++;
852 logProblem(problem, localProblemCount, currentMain.globalProblemsCount, unitSource);
853 localProblemCount++;
854 if (problem.isError()) {
855 localErrorCount++;
856 errors++;
857 currentMain.globalErrorsCount++;
858 } else if (problem.getID() == IProblem.Task) {
859 currentMain.globalTasksCount++;
860 tasks++;
861 } else if (problem.isInfo()) {
862 currentMain.globalInfoCount++;
863 infos++;
864 } else {
865 currentMain.globalWarningsCount++;
866 warnings++;
867 }
868 }
869 }
870 if ((this.tagBits & Logger.XML) != 0) {
871 if ((errors + warnings + infos) != 0) {
872 startLoggingProblems(errors, warnings, infos);
873 for (int i = 0; i < count; i++) {
874 CategorizedProblem problem = problems[i];
875 if (problem!= null) {
876 if (problem.getID() != IProblem.Task) {
877 logXmlProblem(problem, unitSource);
878 }
879 }
880 }
881 endLoggingProblems();
882 }
883 if (tasks != 0) {
884 startLoggingTasks(tasks);
885 for (int i = 0; i < count; i++) {
886 CategorizedProblem problem = problems[i];
887 if (problem!= null) {
888 if (problem.getID() == IProblem.Task) {
889 logXmlTask(problem, unitSource);
890 }
891 }
892 }
893 endLoggingTasks();
894 }
895 }
896 }
897 return localErrorCount;
898 }
899
900 /**
901 * @param globalProblemsCount
902 * @param globalErrorsCount
903 * @param globalWarningsCount
904 */
logProblemsSummary(int globalProblemsCount, int globalErrorsCount, int globalWarningsCount, int globalInfoCount, int globalTasksCount)905 public void logProblemsSummary(int globalProblemsCount,
906 int globalErrorsCount, int globalWarningsCount, int globalInfoCount, int globalTasksCount) {
907 if ((this.tagBits & Logger.XML) != 0) {
908 // generate xml
909 this.parameters.put(Logger.NUMBER_OF_PROBLEMS, Integer.valueOf(globalProblemsCount));
910 this.parameters.put(Logger.NUMBER_OF_ERRORS, Integer.valueOf(globalErrorsCount));
911 this.parameters.put(Logger.NUMBER_OF_WARNINGS, Integer.valueOf(globalWarningsCount));
912 this.parameters.put(Logger.NUMBER_OF_INFOS, Integer.valueOf(globalInfoCount));
913 this.parameters.put(Logger.NUMBER_OF_TASKS, Integer.valueOf(globalTasksCount));
914 printTag(Logger.PROBLEM_SUMMARY, this.parameters, true, true);
915 }
916 if (globalProblemsCount == 1) {
917 String message = null;
918 if (globalErrorsCount == 1) {
919 message = this.main.bind("compile.oneError"); //$NON-NLS-1$
920 } else if (globalInfoCount == 1) {
921 message = this.main.bind("compile.oneInfo"); //$NON-NLS-1$
922 } else {
923 message = this.main.bind("compile.oneWarning"); //$NON-NLS-1$
924 }
925 printErr(this.main.bind("compile.oneProblem", message)); //$NON-NLS-1$
926 } else {
927 String errorMessage = null;
928 String warningMessage = null;
929 String infoMessage = null;
930 if (globalErrorsCount > 0) {
931 if (globalErrorsCount == 1) {
932 errorMessage = this.main.bind("compile.oneError"); //$NON-NLS-1$
933 } else {
934 errorMessage = this.main.bind("compile.severalErrors", String.valueOf(globalErrorsCount)); //$NON-NLS-1$
935 }
936 }
937 int warningsNumber = globalWarningsCount + globalTasksCount;
938 if (warningsNumber > 0) {
939 if (warningsNumber == 1) {
940 warningMessage = this.main.bind("compile.oneWarning"); //$NON-NLS-1$
941 } else {
942 warningMessage = this.main.bind("compile.severalWarnings", String.valueOf(warningsNumber)); //$NON-NLS-1$
943 }
944 }
945 if (globalInfoCount == 1) {
946 infoMessage = this.main.bind("compile.oneInfo"); //$NON-NLS-1$
947 } else if (globalInfoCount > 1) {
948 infoMessage = this.main.bind("compile.severalInfos", String.valueOf(warningsNumber)); //$NON-NLS-1$
949 }
950 if (globalProblemsCount == globalInfoCount || globalProblemsCount == globalErrorsCount || globalProblemsCount == globalWarningsCount) {
951 String msg = errorMessage != null ? errorMessage : warningMessage != null ? warningMessage : infoMessage;
952 printErr(this.main.bind(
953 "compile.severalProblemsErrorsOrWarnings", //$NON-NLS-1$
954 String.valueOf(globalProblemsCount),
955 msg));
956 } else {
957 if (globalInfoCount == 0) {
958 printErr(this.main.bind(
959 "compile.severalProblemsErrorsAndWarnings", //$NON-NLS-1$
960 new String[] {
961 String.valueOf(globalProblemsCount),
962 errorMessage,
963 warningMessage
964 }));
965 } else {
966 if (errorMessage == null) {
967 errorMessage = this.main.bind("compile.severalErrors", String.valueOf(globalErrorsCount)); //$NON-NLS-1$
968 }
969 if (warningMessage == null) {
970 warningMessage = this.main.bind("compile.severalWarnings", String.valueOf(warningsNumber)); //$NON-NLS-1$
971 }
972 printErr(this.main.bind(
973 "compile.severalProblems", //$NON-NLS-1$
974 new String[] {
975 String.valueOf(globalProblemsCount),
976 errorMessage,
977 warningMessage,
978 infoMessage
979 }));
980 }
981 }
982 }
983 if (this.main.failOnWarning && globalWarningsCount > 0) {
984 printErr("\n"); //$NON-NLS-1$
985 printErr(this.main.bind("compile.failOnWarning")); //$NON-NLS-1$
986 }
987 if ((this.tagBits & Logger.XML) == 0) {
988 this.printlnErr();
989 }
990 }
991
992 /**
993 *
994 */
logProgress()995 public void logProgress() {
996 printOut('.');
997 }
998
999 /**
1000 * @param i
1001 * the current repetition number
1002 * @param repetitions
1003 * the given number of repetitions
1004 */
logRepetition(int i, int repetitions)1005 public void logRepetition(int i, int repetitions) {
1006 printlnOut(this.main.bind("compile.repetition", //$NON-NLS-1$
1007 String.valueOf(i + 1), String.valueOf(repetitions)));
1008 }
1009 /**
1010 * @param compilerStats
1011 */
logTiming(CompilerStats compilerStats)1012 public void logTiming(CompilerStats compilerStats) {
1013 long time = compilerStats.elapsedTime();
1014 long lineCount = compilerStats.lineCount;
1015 if ((this.tagBits & Logger.XML) != 0) {
1016 this.parameters.put(Logger.VALUE, Long.valueOf(time));
1017 printTag(Logger.TIME, this.parameters, true, true);
1018 this.parameters.put(Logger.VALUE, Long.valueOf(lineCount));
1019 printTag(Logger.NUMBER_OF_LINES, this.parameters, true, true);
1020 }
1021 if (lineCount != 0) {
1022 printlnOut(
1023 this.main.bind("compile.instantTime", //$NON-NLS-1$
1024 new String[] {
1025 String.valueOf(lineCount),
1026 String.valueOf(time),
1027 String.valueOf(((int) (lineCount * 10000.0 / time)) / 10.0),
1028 }));
1029 } else {
1030 printlnOut(
1031 this.main.bind("compile.totalTime", //$NON-NLS-1$
1032 new String[] {
1033 String.valueOf(time),
1034 }));
1035 }
1036 if ((this.main.timing & Main.TIMING_DETAILED) != 0) {
1037 printlnOut(
1038 this.main.bind("compile.detailedTime", //$NON-NLS-1$
1039 new String[] {
1040 String.valueOf(compilerStats.parseTime),
1041 String.valueOf(((int) (compilerStats.parseTime * 1000.0 / time)) / 10.0),
1042 String.valueOf(compilerStats.resolveTime),
1043 String.valueOf(((int) (compilerStats.resolveTime * 1000.0 / time)) / 10.0),
1044 String.valueOf(compilerStats.analyzeTime),
1045 String.valueOf(((int) (compilerStats.analyzeTime * 1000.0 / time)) / 10.0),
1046 String.valueOf(compilerStats.generateTime),
1047 String.valueOf(((int) (compilerStats.generateTime * 1000.0 / time)) / 10.0),
1048 }));
1049 }
1050 }
1051
1052 /**
1053 * Print the usage of the compiler
1054 * @param usage
1055 */
logUsage(String usage)1056 public void logUsage(String usage) {
1057 printlnOut(usage);
1058 }
1059
1060 /**
1061 * Print the version of the compiler in the log and/or the out field
1062 */
logVersion(final boolean printToOut)1063 public void logVersion(final boolean printToOut) {
1064 if (this.log != null && (this.tagBits & Logger.XML) == 0) {
1065 final String version = this.main.bind("misc.version", //$NON-NLS-1$
1066 new String[] {
1067 this.main.bind("compiler.name"), //$NON-NLS-1$
1068 this.main.bind("compiler.version"), //$NON-NLS-1$
1069 this.main.bind("compiler.copyright") //$NON-NLS-1$
1070 }
1071 );
1072 this.log.println("# " + version); //$NON-NLS-1$
1073 if (printToOut) {
1074 this.out.println(version);
1075 this.out.flush();
1076 }
1077 } else if (printToOut) {
1078 final String version = this.main.bind("misc.version", //$NON-NLS-1$
1079 new String[] {
1080 this.main.bind("compiler.name"), //$NON-NLS-1$
1081 this.main.bind("compiler.version"), //$NON-NLS-1$
1082 this.main.bind("compiler.copyright") //$NON-NLS-1$
1083 }
1084 );
1085 this.out.println(version);
1086 this.out.flush();
1087 }
1088 }
1089
1090 /**
1091 * Print the usage of wrong JDK
1092 */
logWrongJDK()1093 public void logWrongJDK() {
1094 if ((this.tagBits & Logger.XML) != 0) {
1095 this.parameters.put(Logger.MESSAGE, this.main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
1096 printTag(Logger.ERROR, this.parameters, true, true);
1097 }
1098 this.printlnErr(this.main.bind("configure.requiresJDK1.2orAbove")); //$NON-NLS-1$
1099 }
1100
logXmlExtraProblem(CategorizedProblem problem, int globalErrorCount, int localErrorCount)1101 private void logXmlExtraProblem(CategorizedProblem problem, int globalErrorCount, int localErrorCount) {
1102 final int sourceStart = problem.getSourceStart();
1103 final int sourceEnd = problem.getSourceEnd();
1104 boolean isError = problem.isError();
1105 this.parameters.put(Logger.PROBLEM_SEVERITY, isError ? Logger.ERROR : (problem.isInfo() ? Logger.INFO : Logger.WARNING));
1106 this.parameters.put(Logger.PROBLEM_LINE, Integer.valueOf(problem.getSourceLineNumber()));
1107 this.parameters.put(Logger.PROBLEM_SOURCE_START, Integer.valueOf(sourceStart));
1108 this.parameters.put(Logger.PROBLEM_SOURCE_END, Integer.valueOf(sourceEnd));
1109 printTag(Logger.EXTRA_PROBLEM_TAG, this.parameters, true, false);
1110 this.parameters.put(Logger.VALUE, problem.getMessage());
1111 printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
1112 extractContext(problem, null);
1113 endTag(Logger.EXTRA_PROBLEM_TAG);
1114 }
1115 /**
1116 * @param problem
1117 * the given problem to log
1118 * @param unitSource
1119 * the given unit source
1120 */
logXmlProblem(CategorizedProblem problem, char[] unitSource)1121 private void logXmlProblem(CategorizedProblem problem, char[] unitSource) {
1122 final int sourceStart = problem.getSourceStart();
1123 final int sourceEnd = problem.getSourceEnd();
1124 final int id = problem.getID();
1125 this.parameters.put(Logger.ID, getFieldName(id)); // ID as field name
1126 this.parameters.put(Logger.PROBLEM_ID, Integer.valueOf(id)); // ID as numeric value
1127 boolean isError = problem.isError();
1128 int severity = isError ? ProblemSeverities.Error : ProblemSeverities.Warning;
1129 this.parameters.put(Logger.PROBLEM_SEVERITY, isError ? Logger.ERROR : (problem.isInfo() ? Logger.INFO : Logger.WARNING));
1130 this.parameters.put(Logger.PROBLEM_LINE, Integer.valueOf(problem.getSourceLineNumber()));
1131 this.parameters.put(Logger.PROBLEM_SOURCE_START, Integer.valueOf(sourceStart));
1132 this.parameters.put(Logger.PROBLEM_SOURCE_END, Integer.valueOf(sourceEnd));
1133 String problemOptionKey = getProblemOptionKey(id);
1134 if (problemOptionKey != null) {
1135 this.parameters.put(Logger.PROBLEM_OPTION_KEY, problemOptionKey);
1136 }
1137 int categoryID = ProblemReporter.getProblemCategory(severity, id);
1138 this.parameters.put(Logger.PROBLEM_CATEGORY_ID, Integer.valueOf(categoryID));
1139 printTag(Logger.PROBLEM_TAG, this.parameters, true, false);
1140 this.parameters.put(Logger.VALUE, problem.getMessage());
1141 printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
1142 extractContext(problem, unitSource);
1143 String[] arguments = problem.getArguments();
1144 final int length = arguments.length;
1145 if (length != 0) {
1146 printTag(Logger.PROBLEM_ARGUMENTS, null, true, false);
1147 for (int i = 0; i < length; i++) {
1148 this.parameters.put(Logger.PROBLEM_ARGUMENT_VALUE, arguments[i]);
1149 printTag(Logger.PROBLEM_ARGUMENT, this.parameters, true, true);
1150 }
1151 endTag(Logger.PROBLEM_ARGUMENTS);
1152 }
1153 endTag(Logger.PROBLEM_TAG);
1154 }
1155 /**
1156 * @param problem
1157 * the given problem to log
1158 * @param unitSource
1159 * the given unit source
1160 */
logXmlTask(CategorizedProblem problem, char[] unitSource)1161 private void logXmlTask(CategorizedProblem problem, char[] unitSource) {
1162 this.parameters.put(Logger.PROBLEM_LINE, Integer.valueOf(problem.getSourceLineNumber()));
1163 this.parameters.put(Logger.PROBLEM_SOURCE_START, Integer.valueOf(problem.getSourceStart()));
1164 this.parameters.put(Logger.PROBLEM_SOURCE_END, Integer.valueOf(problem.getSourceEnd()));
1165 String problemOptionKey = getProblemOptionKey(problem.getID());
1166 if (problemOptionKey != null) {
1167 this.parameters.put(Logger.PROBLEM_OPTION_KEY, problemOptionKey);
1168 }
1169 printTag(Logger.TASK, this.parameters, true, false);
1170 this.parameters.put(Logger.VALUE, problem.getMessage());
1171 printTag(Logger.PROBLEM_MESSAGE, this.parameters, true, true);
1172 extractContext(problem, unitSource);
1173 endTag(Logger.TASK);
1174 }
1175
printErr(String s)1176 private void printErr(String s) {
1177 this.err.print(s);
1178 if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
1179 this.log.print(s);
1180 }
1181 }
1182
printlnErr()1183 private void printlnErr() {
1184 this.err.println();
1185 if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
1186 this.log.println();
1187 }
1188 }
1189
printlnErr(String s)1190 private void printlnErr(String s) {
1191 this.err.println(s);
1192 if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
1193 this.log.println(s);
1194 }
1195 }
1196
printlnOut(String s)1197 private void printlnOut(String s) {
1198 this.out.println(s);
1199 if ((this.tagBits & Logger.XML) == 0 && this.log != null) {
1200 this.log.println(s);
1201 }
1202 }
1203
1204 /**
1205 *
1206 */
printNewLine()1207 public void printNewLine() {
1208 this.out.println();
1209 }
1210
printOut(char c)1211 private void printOut(char c) {
1212 this.out.print(c);
1213 }
1214
printStats()1215 public void printStats() {
1216 final boolean isTimed = (this.main.timing & TIMING_ENABLED) != 0;
1217 if ((this.tagBits & Logger.XML) != 0) {
1218 printTag(Logger.STATS, null, true, false);
1219 }
1220 if (isTimed) {
1221 CompilerStats compilerStats = this.main.batchCompiler.stats;
1222 compilerStats.startTime = this.main.startTime; // also include batch initialization times
1223 compilerStats.endTime = System.currentTimeMillis(); // also include batch output times
1224 logTiming(compilerStats);
1225 }
1226 if (this.main.globalProblemsCount > 0) {
1227 logProblemsSummary(this.main.globalProblemsCount, this.main.globalErrorsCount, this.main.globalWarningsCount,
1228 this.main.globalInfoCount, this.main.globalTasksCount);
1229 }
1230 if (this.main.exportedClassFilesCounter != 0
1231 && (this.main.showProgress || isTimed || this.main.verbose)) {
1232 logNumberOfClassFilesGenerated(this.main.exportedClassFilesCounter);
1233 }
1234 if ((this.tagBits & Logger.XML) != 0) {
1235 endTag(Logger.STATS);
1236 }
1237 }
1238
printTag(String name, HashMap<String, Object> params, boolean insertNewLine, boolean closeTag)1239 private void printTag(String name, HashMap<String, Object> params, boolean insertNewLine, boolean closeTag) {
1240 if (this.log != null) {
1241 ((GenericXMLWriter) this.log).printTag(name, this.parameters, true, insertNewLine, closeTag);
1242 }
1243 this.parameters.clear();
1244 }
1245
setEmacs()1246 public void setEmacs() {
1247 this.tagBits |= Logger.EMACS;
1248 }
setLog(String logFileName)1249 public void setLog(String logFileName) {
1250 final Date date = new Date();
1251 final DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, Locale.getDefault());
1252 try {
1253 int index = logFileName.lastIndexOf('.');
1254 if (index != -1) {
1255 if (logFileName.substring(index).toLowerCase().equals(".xml")) { //$NON-NLS-1$
1256 this.log = new GenericXMLWriter(new OutputStreamWriter(new FileOutputStream(logFileName, false), Util.UTF_8), Util.LINE_SEPARATOR, true);
1257 this.tagBits |= Logger.XML;
1258 // insert time stamp as comment
1259 this.log.println("<!-- " + dateFormat.format(date) + " -->");//$NON-NLS-1$//$NON-NLS-2$
1260 this.log.println(Logger.XML_DTD_DECLARATION);
1261 this.parameters.put(Logger.COMPILER_NAME, this.main.bind("compiler.name")); //$NON-NLS-1$
1262 this.parameters.put(Logger.COMPILER_VERSION, this.main.bind("compiler.version")); //$NON-NLS-1$
1263 this.parameters.put(Logger.COMPILER_COPYRIGHT, this.main.bind("compiler.copyright")); //$NON-NLS-1$
1264 printTag(Logger.COMPILER, this.parameters, true, false);
1265 } else {
1266 this.log = new PrintWriter(new FileOutputStream(logFileName, false));
1267 this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$
1268 }
1269 } else {
1270 this.log = new PrintWriter(new FileOutputStream(logFileName, false));
1271 this.log.println("# " + dateFormat.format(date));//$NON-NLS-1$
1272 }
1273 } catch (FileNotFoundException e) {
1274 throw new IllegalArgumentException(this.main.bind("configure.cannotOpenLog", logFileName), e); //$NON-NLS-1$
1275 } catch (UnsupportedEncodingException e) {
1276 throw new IllegalArgumentException(this.main.bind("configure.cannotOpenLogInvalidEncoding", logFileName), e); //$NON-NLS-1$
1277 }
1278 }
startLoggingExtraProblems(int count)1279 private void startLoggingExtraProblems(int count) {
1280 this.parameters.put(Logger.NUMBER_OF_PROBLEMS, Integer.valueOf(count));
1281 printTag(Logger.EXTRA_PROBLEMS, this.parameters, true, false);
1282 }
1283
1284 /**
1285 * Used to start logging problems.
1286 * Only use in xml mode.
1287 */
startLoggingProblems(int errors, int warnings, int infos)1288 private void startLoggingProblems(int errors, int warnings, int infos) {
1289 this.parameters.put(Logger.NUMBER_OF_PROBLEMS, Integer.valueOf(errors + warnings));
1290 this.parameters.put(Logger.NUMBER_OF_ERRORS, Integer.valueOf(errors));
1291 this.parameters.put(Logger.NUMBER_OF_WARNINGS, Integer.valueOf(warnings));
1292 this.parameters.put(Logger.NUMBER_OF_INFOS, Integer.valueOf(infos));
1293 printTag(Logger.PROBLEMS, this.parameters, true, false);
1294 }
1295
startLoggingSource(CompilationResult compilationResult)1296 public void startLoggingSource(CompilationResult compilationResult) {
1297 if ((this.tagBits & Logger.XML) != 0) {
1298 ICompilationUnit compilationUnit = compilationResult.compilationUnit;
1299 if (compilationUnit != null) {
1300 char[] fileName = compilationUnit.getFileName();
1301 File f = new File(new String(fileName));
1302 if (fileName != null) {
1303 this.parameters.put(Logger.PATH, f.getAbsolutePath());
1304 }
1305 char[][] packageName = compilationResult.packageName;
1306 if (packageName != null) {
1307 this.parameters.put(
1308 Logger.PACKAGE,
1309 new String(CharOperation.concatWith(packageName, File.separatorChar)));
1310 }
1311 CompilationUnit unit = (CompilationUnit) compilationUnit;
1312 String destinationPath = unit.destinationPath;
1313 if (destinationPath == null) {
1314 destinationPath = this.main.destinationPath;
1315 }
1316 if (destinationPath != null && destinationPath != NONE) {
1317 if (File.separatorChar == '/') {
1318 this.parameters.put(Logger.OUTPUT, destinationPath);
1319 } else {
1320 this.parameters.put(Logger.OUTPUT, destinationPath.replace('/', File.separatorChar));
1321 }
1322 }
1323 }
1324 printTag(Logger.SOURCE, this.parameters, true, false);
1325 }
1326 }
1327
startLoggingSources()1328 public void startLoggingSources() {
1329 if ((this.tagBits & Logger.XML) != 0) {
1330 printTag(Logger.SOURCES, null, true, false);
1331 }
1332 }
1333
startLoggingTasks(int tasks)1334 public void startLoggingTasks(int tasks) {
1335 if ((this.tagBits & Logger.XML) != 0) {
1336 this.parameters.put(Logger.NUMBER_OF_TASKS, Integer.valueOf(tasks));
1337 printTag(Logger.TASKS, this.parameters, true, false);
1338 }
1339 }
1340 }
1341
1342 /**
1343 * Resource bundle factory to share bundles for the same locale
1344 */
1345 public static class ResourceBundleFactory {
1346 private static HashMap<Locale, ResourceBundle> Cache = new HashMap<>();
getBundle(Locale locale)1347 public static synchronized ResourceBundle getBundle(Locale locale) {
1348 ResourceBundle bundle = Cache.get(locale);
1349 if (bundle == null) {
1350 bundle = ResourceBundle.getBundle(Main.bundleName, locale);
1351 Cache.put(locale, bundle);
1352 }
1353 return bundle;
1354 }
1355 }
1356
1357 // used with -annotationpath to declare that annotations should be read from the classpath:
1358 private static final String ANNOTATION_SOURCE_CLASSPATH = "CLASSPATH"; //$NON-NLS-1$
1359
1360 // javadoc analysis tuning
1361 boolean enableJavadocOn;
1362
1363 boolean warnJavadocOn;
1364 boolean warnAllJavadocOn;
1365
1366 public Compiler batchCompiler;
1367 /* Bundle containing messages */
1368 public ResourceBundle bundle;
1369 protected FileSystem.Classpath[] checkedClasspaths;
1370 // For single module mode
1371 protected IModule module;
1372 private String moduleVersion;
1373 // paths to external annotations:
1374 protected List<String> annotationPaths;
1375 protected boolean annotationsFromClasspath;
1376
1377 private List<String> addonExports = Collections.EMPTY_LIST;
1378 private List<String> addonReads = Collections.EMPTY_LIST;
1379 public Set<String> rootModules = Collections.EMPTY_SET;
1380 public Set<String> limitedModules;
1381
1382 public Locale compilerLocale;
1383 public CompilerOptions compilerOptions; // read-only
1384 public CompilationProgress progress;
1385 public String destinationPath;
1386 public String[] destinationPaths;
1387 // destination path for compilation units that get no more specific
1388 // one (through directory arguments or various classpath options);
1389 // coding is:
1390 // == null: unspecified, write class files close to their respective
1391 // source files;
1392 // == Main.NONE: absorbent element, do not output class files;
1393 // else: use as the path of the directory into which class files must
1394 // be written.
1395 protected boolean enablePreview;
1396 protected String releaseVersion;
1397 private boolean didSpecifySource;
1398 private boolean didSpecifyTarget;
1399 public String[] encodings;
1400 public int exportedClassFilesCounter;
1401 public String[] filenames;
1402 public String[] modNames;
1403 public String[] classNames;
1404 // overrides of destinationPath on a directory argument basis
1405 public int globalErrorsCount;
1406 public int globalProblemsCount;
1407 public int globalTasksCount;
1408 public int globalWarningsCount;
1409 public int globalInfoCount;
1410
1411 private File javaHomeCache;
1412
1413 private boolean javaHomeChecked = false;
1414 private boolean primaryNullAnnotationsSeen = false;
1415 public long lineCount0;
1416
1417 public String log;
1418
1419 public Logger logger;
1420 public int maxProblems;
1421 public Map<String, String> options;
1422 protected long complianceLevel;
1423 public char[][] ignoreOptionalProblemsFromFolders;
1424 protected PrintWriter out;
1425 public boolean proceed = true;
1426 public boolean proceedOnError = false;
1427 public boolean failOnWarning = false;
1428 public boolean produceRefInfo = false;
1429 public int currentRepetition, maxRepetition;
1430 public boolean showProgress = false;
1431 public long startTime;
1432 public ArrayList<String> pendingErrors;
1433 public boolean systemExitWhenFinished = true;
1434
1435 public static final int TIMING_DISABLED = 0;
1436 public static final int TIMING_ENABLED = 1;
1437 public static final int TIMING_DETAILED = 2;
1438
1439 public int timing = TIMING_DISABLED;
1440 public CompilerStats[] compilerStats;
1441 public boolean verbose = false;
1442 private String[] expandedCommandLine;
1443
1444 private PrintWriter err;
1445
1446 protected ArrayList<CategorizedProblem> extraProblems;
1447
1448 public final static String bundleName = "org.eclipse.jdt.internal.compiler.batch.messages"; //$NON-NLS-1$
1449 // two uses: recognize 'none' in options; code the singleton none
1450 // for the '-d none' option (wherever it may be found)
1451 public static final int DEFAULT_SIZE_CLASSPATH = 4;
1452
1453 public static final String NONE = "none"; //$NON-NLS-1$
1454
1455 /**
1456 * @deprecated - use {@link BatchCompiler#compile(String, PrintWriter, PrintWriter, CompilationProgress)} instead
1457 * e.g. BatchCompiler.compile(commandLine, new PrintWriter(System.out), new PrintWriter(System.err), null);
1458 */
compile(String commandLine)1459 public static boolean compile(String commandLine) {
1460 return new Main(new PrintWriter(System.out), new PrintWriter(System.err), false /* systemExit */, null /* options */, null /* progress */).compile(tokenize(commandLine));
1461 }
1462
1463 /**
1464 * @deprecated - use {@link BatchCompiler#compile(String, PrintWriter, PrintWriter, CompilationProgress)} instead
1465 * e.g. BatchCompiler.compile(commandLine, outWriter, errWriter, null);
1466 */
compile(String commandLine, PrintWriter outWriter, PrintWriter errWriter)1467 public static boolean compile(String commandLine, PrintWriter outWriter, PrintWriter errWriter) {
1468 return new Main(outWriter, errWriter, false /* systemExit */, null /* options */, null /* progress */).compile(tokenize(commandLine));
1469 }
1470
1471 /*
1472 * Internal API for public API BatchCompiler#compile(String[], PrintWriter, PrintWriter, CompilationProgress)
1473 */
compile(String[] commandLineArguments, PrintWriter outWriter, PrintWriter errWriter, CompilationProgress progress)1474 public static boolean compile(String[] commandLineArguments, PrintWriter outWriter, PrintWriter errWriter, CompilationProgress progress) {
1475 return new Main(outWriter, errWriter, false /* systemExit */, null /* options */, progress).compile(commandLineArguments);
1476 }
getLibrariesFiles(File[] files)1477 public static File[][] getLibrariesFiles(File[] files) {
1478 FilenameFilter filter = new FilenameFilter() {
1479 @Override
1480 public boolean accept(File dir, String name) {
1481 return Util.archiveFormat(name) > -1;
1482 }
1483 };
1484 final int filesLength = files.length;
1485 File[][] result = new File[filesLength][];
1486 for (int i = 0; i < filesLength; i++) {
1487 File currentFile = files[i];
1488 if (currentFile.exists() && currentFile.isDirectory()) {
1489 result[i] = currentFile.listFiles(filter);
1490 }
1491 }
1492 return result;
1493 }
1494
main(String[] argv)1495 public static void main(String[] argv) {
1496 new Main(new PrintWriter(System.out), new PrintWriter(System.err), true/*systemExit*/, null/*options*/, null/*progress*/).compile(argv);
1497 }
1498
tokenize(String commandLine)1499 public static String[] tokenize(String commandLine) {
1500
1501 int count = 0;
1502 String[] arguments = new String[10];
1503 StringTokenizer tokenizer = new StringTokenizer(commandLine, " \"", true); //$NON-NLS-1$
1504 String token = Util.EMPTY_STRING;
1505 boolean insideQuotes = false;
1506 boolean startNewToken = true;
1507
1508 // take care to quotes on the command line
1509 // 'xxx "aaa bbb";ccc yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
1510 // 'xxx "aaa bbb;ccc" yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
1511 // 'xxx "aaa bbb";"ccc" yyy' ---> {"xxx", "aaa bbb;ccc", "yyy" }
1512 // 'xxx/"aaa bbb";"ccc" yyy' ---> {"xxx/aaa bbb;ccc", "yyy" }
1513 while (tokenizer.hasMoreTokens()) {
1514 token = tokenizer.nextToken();
1515
1516 if (token.equals(" ")) { //$NON-NLS-1$
1517 if (insideQuotes) {
1518 arguments[count - 1] += token;
1519 startNewToken = false;
1520 } else {
1521 startNewToken = true;
1522 }
1523 } else if (token.equals("\"")) { //$NON-NLS-1$
1524 if (!insideQuotes && startNewToken) {
1525 if (count == arguments.length)
1526 System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
1527 arguments[count++] = Util.EMPTY_STRING;
1528 }
1529 insideQuotes = !insideQuotes;
1530 startNewToken = false;
1531 } else {
1532 if (insideQuotes) {
1533 arguments[count - 1] += token;
1534 } else {
1535 if (token.length() > 0 && !startNewToken) {
1536 arguments[count - 1] += token;
1537 } else {
1538 if (count == arguments.length)
1539 System.arraycopy(arguments, 0, (arguments = new String[count * 2]), 0, count);
1540 String trimmedToken = token.trim();
1541 if (trimmedToken.length() != 0) {
1542 arguments[count++] = trimmedToken;
1543 }
1544 }
1545 }
1546 startNewToken = false;
1547 }
1548 }
1549 System.arraycopy(arguments, 0, arguments = new String[count], 0, count);
1550 return arguments;
1551 }
1552
1553 /**
1554 * @deprecated - use {@link #Main(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead
1555 * e.g. Main(outWriter, errWriter, systemExitWhenFinished, null, null)
1556 */
Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished)1557 public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished) {
1558 this(outWriter, errWriter, systemExitWhenFinished, null /* options */, null /* progress */);
1559 }
1560
1561 /**
1562 * @deprecated - use {@link #Main(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead
1563 * e.g. Main(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions, null)
1564 */
Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map<String, String> customDefaultOptions)1565 public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map<String, String> customDefaultOptions) {
1566 this(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions, null /* progress */);
1567 }
1568
Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map<String, String> customDefaultOptions, CompilationProgress compilationProgress)1569 public Main(PrintWriter outWriter, PrintWriter errWriter, boolean systemExitWhenFinished, Map<String, String> customDefaultOptions, CompilationProgress compilationProgress) {
1570 this.initialize(outWriter, errWriter, systemExitWhenFinished, customDefaultOptions, compilationProgress);
1571 this.relocalize();
1572 }
1573
addExtraProblems(CategorizedProblem problem)1574 public void addExtraProblems(CategorizedProblem problem) {
1575 if (this.extraProblems == null) {
1576 this.extraProblems = new ArrayList<>();
1577 }
1578 this.extraProblems.add(problem);
1579 }
addNewEntry(ArrayList<FileSystem.Classpath> paths, String currentClasspathName, ArrayList<String> currentRuleSpecs, String customEncoding, String destPath, boolean isSourceOnly, boolean rejectDestinationPathOnJars)1580 protected void addNewEntry(ArrayList<FileSystem.Classpath> paths, String currentClasspathName,
1581 ArrayList<String> currentRuleSpecs, String customEncoding,
1582 String destPath, boolean isSourceOnly,
1583 boolean rejectDestinationPathOnJars) {
1584
1585 int rulesSpecsSize = currentRuleSpecs.size();
1586 AccessRuleSet accessRuleSet = null;
1587 if (rulesSpecsSize != 0) {
1588 AccessRule[] accessRules = new AccessRule[currentRuleSpecs.size()];
1589 boolean rulesOK = true;
1590 Iterator<String> i = currentRuleSpecs.iterator();
1591 int j = 0;
1592 while (i.hasNext()) {
1593 String ruleSpec = i.next();
1594 char key = ruleSpec.charAt(0);
1595 String pattern = ruleSpec.substring(1);
1596 if (pattern.length() > 0) {
1597 switch (key) {
1598 case '+':
1599 accessRules[j++] = new AccessRule(pattern
1600 .toCharArray(), 0);
1601 break;
1602 case '~':
1603 accessRules[j++] = new AccessRule(pattern
1604 .toCharArray(),
1605 IProblem.DiscouragedReference);
1606 break;
1607 case '-':
1608 accessRules[j++] = new AccessRule(pattern
1609 .toCharArray(),
1610 IProblem.ForbiddenReference);
1611 break;
1612 case '?':
1613 accessRules[j++] = new AccessRule(pattern
1614 .toCharArray(),
1615 IProblem.ForbiddenReference, true/*keep looking for accessible type*/);
1616 break;
1617 default:
1618 rulesOK = false;
1619 }
1620 } else {
1621 rulesOK = false;
1622 }
1623 }
1624 if (rulesOK) {
1625 accessRuleSet = new AccessRuleSet(accessRules, AccessRestriction.COMMAND_LINE, currentClasspathName);
1626 } else {
1627 if (currentClasspathName.length() != 0) {
1628 // we go on anyway
1629 addPendingErrors(this.bind("configure.incorrectClasspath", currentClasspathName));//$NON-NLS-1$
1630 }
1631 return;
1632 }
1633 }
1634 if (NONE.equals(destPath)) {
1635 destPath = NONE; // keep == comparison valid
1636 }
1637
1638 if (rejectDestinationPathOnJars && destPath != null &&
1639 Util.archiveFormat(currentClasspathName) > -1) {
1640 throw new IllegalArgumentException(
1641 this.bind("configure.unexpectedDestinationPathEntryFile", //$NON-NLS-1$
1642 currentClasspathName));
1643 }
1644 FileSystem.Classpath currentClasspath = FileSystem.getClasspath(
1645 currentClasspathName,
1646 customEncoding,
1647 isSourceOnly,
1648 accessRuleSet,
1649 destPath,
1650 this.options,
1651 this.releaseVersion);
1652 if (currentClasspath != null) {
1653 paths.add(currentClasspath);
1654 } else if (currentClasspathName.length() != 0) {
1655 // we go on anyway
1656 addPendingErrors(this.bind("configure.incorrectClasspath", currentClasspathName));//$NON-NLS-1$
1657 }
1658 }
addPendingErrors(String message)1659 void addPendingErrors(String message) {
1660 if (this.pendingErrors == null) {
1661 this.pendingErrors = new ArrayList<>();
1662 }
1663 this.pendingErrors.add(message);
1664 }
1665 /*
1666 * Lookup the message with the given ID in this catalog
1667 */
bind(String id)1668 public String bind(String id) {
1669 return bind(id, (String[]) null);
1670 }
1671 /*
1672 * Lookup the message with the given ID in this catalog and bind its
1673 * substitution locations with the given string.
1674 */
bind(String id, String binding)1675 public String bind(String id, String binding) {
1676 return bind(id, new String[] { binding });
1677 }
1678
1679 /*
1680 * Lookup the message with the given ID in this catalog and bind its
1681 * substitution locations with the given strings.
1682 */
bind(String id, String binding1, String binding2)1683 public String bind(String id, String binding1, String binding2) {
1684 return bind(id, new String[] { binding1, binding2 });
1685 }
1686
1687 /*
1688 * Lookup the message with the given ID in this catalog and bind its
1689 * substitution locations with the given string values.
1690 */
bind(String id, String[] arguments)1691 public String bind(String id, String[] arguments) {
1692 if (id == null)
1693 return "No message available"; //$NON-NLS-1$
1694 String message = null;
1695 try {
1696 message = this.bundle.getString(id);
1697 } catch (MissingResourceException e) {
1698 // If we got an exception looking for the message, fail gracefully by just returning
1699 // the id we were looking for. In most cases this is semi-informative so is not too bad.
1700 return "Missing message: " + id + " in: " + Main.bundleName; //$NON-NLS-2$ //$NON-NLS-1$
1701 }
1702 return MessageFormat.format(message, (Object[]) arguments);
1703 }
1704 /**
1705 * Return true if and only if the running VM supports the given minimal version.
1706 *
1707 * <p>This only checks the major version, since the minor version is always 0 (at least for the useful cases).</p>
1708 * <p>The given minimalSupportedVersion is one of the constants:</p>
1709 * <ul>
1710 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_1</code></li>
1711 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_2</code></li>
1712 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_3</code></li>
1713 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_4</code></li>
1714 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_5</code></li>
1715 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_6</code></li>
1716 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_7</code></li>
1717 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK1_8</code></li>
1718 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK9</code></li>
1719 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK10</code></li>
1720 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK11</code></li>
1721 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK12</code></li>
1722 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK13</code></li>
1723 * <li><code>org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.JDK14</code></li>
1724 *
1725 * </ul>
1726 * @param minimalSupportedVersion the given minimal version
1727 * @return true if and only if the running VM supports the given minimal version, false otherwise
1728 */
checkVMVersion(long minimalSupportedVersion)1729 private boolean checkVMVersion(long minimalSupportedVersion) {
1730 // the format of this property is supposed to be xx.x where x are digits.
1731 String classFileVersion = System.getProperty("java.class.version"); //$NON-NLS-1$
1732 if (classFileVersion == null) {
1733 // by default we don't support a class file version we cannot recognize
1734 return false;
1735 }
1736 int index = classFileVersion.indexOf('.');
1737 if (index == -1) {
1738 // by default we don't support a class file version we cannot recognize
1739 return false;
1740 }
1741 int majorVersion;
1742 try {
1743 majorVersion = Integer.parseInt(classFileVersion.substring(0, index));
1744 } catch (NumberFormatException e) {
1745 // by default we don't support a class file version we cannot recognize
1746 return false;
1747 }
1748 return ClassFileConstants.getComplianceLevelForJavaVersion(majorVersion) >=minimalSupportedVersion;
1749 }
1750 /*
1751 * Low-level API performing the actual compilation
1752 */
compile(String[] argv)1753 public boolean compile(String[] argv) {
1754 // decode command line arguments
1755 try {
1756 configure(argv);
1757 if (this.progress != null)
1758 this.progress.begin(this.filenames == null ? 0 : this.filenames.length * this.maxRepetition);
1759 if (this.proceed) {
1760 // if (this.verbose) {
1761 // System.out.println(new CompilerOptions(this.options));
1762 // }
1763 if (this.showProgress) this.logger.compiling();
1764 for (this.currentRepetition = 0; this.currentRepetition < this.maxRepetition; this.currentRepetition++) {
1765 this.globalProblemsCount = 0;
1766 this.globalErrorsCount = 0;
1767 this.globalWarningsCount = 0;
1768 this.globalInfoCount = 0;
1769 this.globalTasksCount = 0;
1770 this.exportedClassFilesCounter = 0;
1771
1772 if (this.maxRepetition > 1) {
1773 this.logger.flush();
1774 this.logger.logRepetition(this.currentRepetition, this.maxRepetition);
1775 }
1776 // request compilation
1777 performCompilation();
1778 }
1779 if (this.compilerStats != null) {
1780 this.logger.logAverage();
1781 }
1782 if (this.showProgress) this.logger.printNewLine();
1783 }
1784 if (this.systemExitWhenFinished) {
1785 this.logger.flush();
1786 this.logger.close();
1787 if (this.failOnWarning && this.globalWarningsCount > 0) {
1788 System.exit(-1);
1789 }
1790 System.exit(this.globalErrorsCount > 0 ? -1 : 0);
1791 }
1792 } catch (Exception e) { // internal compiler failure
1793 this.logger.logException(e);
1794 if (this.systemExitWhenFinished) {
1795 this.logger.flush();
1796 this.logger.close();
1797 System.exit(-1);
1798 }
1799 return false;
1800 } finally {
1801 this.logger.flush();
1802 this.logger.close();
1803 if (this.progress != null)
1804 this.progress.done();
1805 }
1806 if (this.progress == null || !this.progress.isCanceled()) {
1807 if (this.failOnWarning && (this.globalWarningsCount > 0))
1808 return false;
1809 if (this.globalErrorsCount == 0)
1810 return true;
1811 }
1812
1813 return false;
1814 }
1815
1816 /*
1817 Decode the command line arguments
1818 */
configure(String[] argv)1819 public void configure(String[] argv) {
1820
1821 if ((argv == null) || (argv.length == 0)) {
1822 printUsage();
1823 return;
1824 }
1825
1826 final int INSIDE_CLASSPATH_start = 1;
1827 final int INSIDE_DESTINATION_PATH = 3;
1828 final int INSIDE_TARGET = 4;
1829 final int INSIDE_LOG = 5;
1830 final int INSIDE_REPETITION = 6;
1831 final int INSIDE_SOURCE = 7;
1832 final int INSIDE_DEFAULT_ENCODING = 8;
1833 final int INSIDE_BOOTCLASSPATH_start = 9;
1834 final int INSIDE_MAX_PROBLEMS = 11;
1835 final int INSIDE_EXT_DIRS = 12;
1836 final int INSIDE_SOURCE_PATH_start = 13;
1837 final int INSIDE_ENDORSED_DIRS = 15;
1838 final int INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH = 16;
1839 final int INSIDE_PROCESSOR_PATH_start = 17;
1840 final int INSIDE_PROCESSOR_start = 18;
1841 final int INSIDE_S_start = 19;
1842 final int INSIDE_CLASS_NAMES = 20;
1843 final int INSIDE_WARNINGS_PROPERTIES = 21;
1844 final int INSIDE_ANNOTATIONPATH_start = 22;
1845 final int INSIDE_MODULEPATH_start = 23;
1846 final int INSIDE_MODULESOURCEPATH_start = 24;
1847 final int INSIDE_ADD_EXPORTS = 25;
1848 final int INSIDE_ADD_READS = 26;
1849 final int INSIDE_SYSTEM = 27;
1850 final int INSIDE_PROCESSOR_MODULE_PATH_start = 28;
1851 final int INSIDE_ADD_MODULES = 29;
1852 final int INSIDE_RELEASE = 30;
1853 final int INSIDE_LIMIT_MODULES = 31;
1854 final int INSIDE_MODULE_VERSION = 32;
1855
1856 final int DEFAULT = 0;
1857 ArrayList<String> bootclasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
1858 String sourcepathClasspathArg = null;
1859 String modulepathArg = null;
1860 String moduleSourcepathArg = null;
1861 ArrayList<String> sourcepathClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
1862 ArrayList<String> classpaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
1863 ArrayList<String> extdirsClasspaths = null;
1864 ArrayList<String> endorsedDirClasspaths = null;
1865 this.annotationPaths = null;
1866 this.annotationsFromClasspath = false;
1867
1868 int index = -1;
1869 int filesCount = 0;
1870 int classCount = 0;
1871 int argCount = argv.length;
1872 int mode = DEFAULT;
1873 this.maxRepetition = 0;
1874 boolean printUsageRequired = false;
1875 String usageSection = null;
1876 boolean printVersionRequired = false;
1877
1878 boolean didSpecifyDeprecation = false;
1879 boolean didSpecifyCompliance = false;
1880 boolean didSpecifyDisabledAnnotationProcessing = false;
1881
1882 String customEncoding = null;
1883 String customDestinationPath = null;
1884 String currentSourceDirectory = null;
1885 String currentArg = Util.EMPTY_STRING;
1886 String moduleName = null;
1887
1888 Set<String> specifiedEncodings = null;
1889
1890 // expand the command line if necessary
1891 boolean needExpansion = false;
1892 loop: for (int i = 0; i < argCount; i++) {
1893 if (argv[i].startsWith("@")) { //$NON-NLS-1$
1894 needExpansion = true;
1895 break loop;
1896 }
1897 }
1898
1899 String[] newCommandLineArgs = null;
1900 if (needExpansion) {
1901 newCommandLineArgs = new String[argCount];
1902 index = 0;
1903 for (int i = 0; i < argCount; i++) {
1904 String[] newArgs = null;
1905 String arg = argv[i].trim();
1906 if (arg.startsWith("@")) { //$NON-NLS-1$
1907 try {
1908 LineNumberReader reader = new LineNumberReader(new StringReader(new String(Util.getFileCharContent(new File(arg.substring(1)), null))));
1909 StringBuffer buffer = new StringBuffer();
1910 String line;
1911 while((line = reader.readLine()) != null) {
1912 line = line.trim();
1913 if (!line.startsWith("#")) { //$NON-NLS-1$
1914 buffer.append(line).append(" "); //$NON-NLS-1$
1915 }
1916 }
1917 newArgs = tokenize(buffer.toString());
1918 } catch(IOException e) {
1919 throw new IllegalArgumentException(
1920 this.bind("configure.invalidexpansionargumentname", arg)); //$NON-NLS-1$
1921 }
1922 }
1923 if (newArgs != null) {
1924 int newCommandLineArgsLength = newCommandLineArgs.length;
1925 int newArgsLength = newArgs.length;
1926 System.arraycopy(newCommandLineArgs, 0, (newCommandLineArgs = new String[newCommandLineArgsLength + newArgsLength - 1]), 0, index);
1927 System.arraycopy(newArgs, 0, newCommandLineArgs, index, newArgsLength);
1928 index += newArgsLength;
1929 } else {
1930 newCommandLineArgs[index++] = arg;
1931 }
1932 }
1933 index = -1;
1934 } else {
1935 newCommandLineArgs = argv;
1936 for (int i = 0; i < argCount; i++) {
1937 newCommandLineArgs[i] = newCommandLineArgs[i].trim();
1938 }
1939 }
1940 argCount = newCommandLineArgs.length;
1941 this.expandedCommandLine = newCommandLineArgs;
1942 while (++index < argCount) {
1943
1944 if (customEncoding != null) {
1945 throw new IllegalArgumentException(
1946 this.bind("configure.unexpectedCustomEncoding", currentArg, customEncoding)); //$NON-NLS-1$
1947 }
1948
1949 currentArg = newCommandLineArgs[index];
1950
1951 switch(mode) {
1952 case DEFAULT :
1953 if (currentArg.startsWith("-nowarn")) { //$NON-NLS-1$
1954 switch (currentArg.length()) {
1955 case 7:
1956 disableAll(ProblemSeverities.Warning);
1957 break;
1958 case 8:
1959 throw new IllegalArgumentException(this.bind(
1960 "configure.invalidNowarnOption", currentArg)); //$NON-NLS-1$
1961 default:
1962 int foldersStart = currentArg.indexOf('[') + 1;
1963 int foldersEnd = currentArg.lastIndexOf(']');
1964 if (foldersStart <= 8 || foldersEnd == -1 || foldersStart > foldersEnd
1965 || foldersEnd < currentArg.length() - 1) {
1966 throw new IllegalArgumentException(this.bind(
1967 "configure.invalidNowarnOption", currentArg)); //$NON-NLS-1$
1968 }
1969 String folders = currentArg.substring(foldersStart, foldersEnd);
1970 if (folders.length() > 0) {
1971 char[][] currentFolders = decodeIgnoreOptionalProblemsFromFolders(folders);
1972 if (this.ignoreOptionalProblemsFromFolders != null) {
1973 int length = this.ignoreOptionalProblemsFromFolders.length + currentFolders.length;
1974 char[][] tempFolders = new char[length][];
1975 System.arraycopy(this.ignoreOptionalProblemsFromFolders, 0, tempFolders, 0, this.ignoreOptionalProblemsFromFolders.length);
1976 System.arraycopy(currentFolders, 0, tempFolders, this.ignoreOptionalProblemsFromFolders.length, currentFolders.length);
1977 this.ignoreOptionalProblemsFromFolders = tempFolders;
1978 } else {
1979 this.ignoreOptionalProblemsFromFolders = currentFolders;
1980 }
1981 } else {
1982 throw new IllegalArgumentException(this.bind(
1983 "configure.invalidNowarnOption", currentArg)); //$NON-NLS-1$
1984 }
1985 }
1986 mode = DEFAULT;
1987 continue;
1988 }
1989 if (currentArg.startsWith("[")) { //$NON-NLS-1$
1990 throw new IllegalArgumentException(
1991 this.bind("configure.unexpectedBracket", //$NON-NLS-1$
1992 currentArg));
1993 }
1994
1995 if (currentArg.endsWith("]")) { //$NON-NLS-1$
1996 // look for encoding specification
1997 int encodingStart = currentArg.indexOf('[') + 1;
1998 if (encodingStart <= 1) {
1999 throw new IllegalArgumentException(
2000 this.bind("configure.unexpectedBracket", currentArg)); //$NON-NLS-1$
2001 }
2002 int encodingEnd = currentArg.length() - 1;
2003 if (encodingStart >= 1) {
2004 if (encodingStart < encodingEnd) {
2005 customEncoding = currentArg.substring(encodingStart, encodingEnd);
2006 try { // ensure encoding is supported
2007 new InputStreamReader(new ByteArrayInputStream(new byte[0]), customEncoding);
2008 } catch (UnsupportedEncodingException e) {
2009 throw new IllegalArgumentException(
2010 this.bind("configure.unsupportedEncoding", customEncoding), e); //$NON-NLS-1$
2011 }
2012 }
2013 currentArg = currentArg.substring(0, encodingStart - 1);
2014 }
2015 }
2016
2017 if (currentArg.endsWith(SuffixConstants.SUFFIX_STRING_java)) {
2018 if (moduleName == null) {
2019 // If the module-info.java was supplied via command line, that will be the
2020 // de facto module for the other source files supplied via command line.
2021 // TODO: This needs revisit in case a source file specified in command line is
2022 // part of a --module-source-path
2023 IModule mod = extractModuleDesc(currentArg);
2024 if (mod != null) {
2025 moduleName = new String(mod.name());
2026 this.module = mod;
2027 }
2028 }
2029 if (this.filenames == null) {
2030 this.filenames = new String[argCount - index];
2031 this.encodings = new String[argCount - index];
2032 this.modNames = new String[argCount - index];
2033 this.destinationPaths = new String[argCount - index];
2034 } else if (filesCount == this.filenames.length) {
2035 int length = this.filenames.length;
2036 System.arraycopy(
2037 this.filenames,
2038 0,
2039 (this.filenames = new String[length + argCount - index]),
2040 0,
2041 length);
2042 System.arraycopy(
2043 this.encodings,
2044 0,
2045 (this.encodings = new String[length + argCount - index]),
2046 0,
2047 length);
2048 System.arraycopy(
2049 this.destinationPaths,
2050 0,
2051 (this.destinationPaths = new String[length + argCount - index]),
2052 0,
2053 length);
2054 System.arraycopy(
2055 this.modNames,
2056 0,
2057 (this.modNames = new String[length + argCount - index]),
2058 0,
2059 length);
2060 }
2061 this.filenames[filesCount] = currentArg;
2062 this.modNames[filesCount] = moduleName;
2063 this.encodings[filesCount++] = customEncoding;
2064 // destination path cannot be specified upon an individual file
2065 customEncoding = null;
2066 mode = DEFAULT;
2067 continue;
2068 }
2069 if (currentArg.equals("-log")) { //$NON-NLS-1$
2070 if (this.log != null)
2071 throw new IllegalArgumentException(
2072 this.bind("configure.duplicateLog", currentArg)); //$NON-NLS-1$
2073 mode = INSIDE_LOG;
2074 continue;
2075 }
2076 if (currentArg.equals("-repeat")) { //$NON-NLS-1$
2077 if (this.maxRepetition > 0)
2078 throw new IllegalArgumentException(
2079 this.bind("configure.duplicateRepeat", currentArg)); //$NON-NLS-1$
2080 mode = INSIDE_REPETITION;
2081 continue;
2082 }
2083 if (currentArg.equals("-maxProblems")) { //$NON-NLS-1$
2084 if (this.maxProblems > 0)
2085 throw new IllegalArgumentException(
2086 this.bind("configure.duplicateMaxProblems", currentArg)); //$NON-NLS-1$
2087 mode = INSIDE_MAX_PROBLEMS;
2088 continue;
2089 }
2090 if (currentArg.equals("--release")) { //$NON-NLS-1$
2091 mode = INSIDE_RELEASE;
2092 continue;
2093 }
2094 if (currentArg.equals("-source")) { //$NON-NLS-1$
2095 mode = INSIDE_SOURCE;
2096 continue;
2097 }
2098 if (currentArg.equals("-encoding")) { //$NON-NLS-1$
2099 mode = INSIDE_DEFAULT_ENCODING;
2100 continue;
2101 }
2102 if (currentArg.startsWith("-")) { //$NON-NLS-1$
2103 String version = optionStringToVersion(currentArg.substring(1));
2104 if (version != null) {
2105 if (didSpecifyCompliance) {
2106 throw new IllegalArgumentException(
2107 this.bind("configure.duplicateCompliance", currentArg));//$NON-NLS-1$
2108 }
2109 didSpecifyCompliance = true;
2110 this.options.put(CompilerOptions.OPTION_Compliance, version);
2111 mode = DEFAULT;
2112 continue;
2113 }
2114 }
2115 if (currentArg.equals("-d")) { //$NON-NLS-1$
2116 if (this.destinationPath != null) {
2117 StringBuffer errorMessage = new StringBuffer();
2118 errorMessage.append(currentArg);
2119 if ((index + 1) < argCount) {
2120 errorMessage.append(' ');
2121 errorMessage.append(newCommandLineArgs[index + 1]);
2122 }
2123 throw new IllegalArgumentException(
2124 this.bind("configure.duplicateOutputPath", errorMessage.toString())); //$NON-NLS-1$
2125 }
2126 mode = INSIDE_DESTINATION_PATH;
2127 continue;
2128 }
2129 if (currentArg.equals("-classpath") //$NON-NLS-1$
2130 || currentArg.equals("-cp")) { //$NON-NLS-1$
2131 mode = INSIDE_CLASSPATH_start;
2132 continue;
2133 }
2134 if (currentArg.equals("-bootclasspath")) {//$NON-NLS-1$
2135 if (bootclasspaths.size() > 0) {
2136 StringBuffer errorMessage = new StringBuffer();
2137 errorMessage.append(currentArg);
2138 if ((index + 1) < argCount) {
2139 errorMessage.append(' ');
2140 errorMessage.append(newCommandLineArgs[index + 1]);
2141 }
2142 throw new IllegalArgumentException(
2143 this.bind("configure.duplicateBootClasspath", errorMessage.toString())); //$NON-NLS-1$
2144 }
2145 mode = INSIDE_BOOTCLASSPATH_start;
2146 continue;
2147 }
2148 if (currentArg.equals("--enable-preview")) { //$NON-NLS-1$
2149 this.enablePreview = true;
2150 mode = DEFAULT;
2151 continue;
2152 }
2153 if (currentArg.equals("--system")) { //$NON-NLS-1$
2154 mode = INSIDE_SYSTEM;
2155 continue;
2156 }
2157 if (currentArg.equals("--module-path") || currentArg.equals("-p") || currentArg.equals("--processor-module-path")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
2158 mode = INSIDE_MODULEPATH_start;
2159 continue;
2160 }
2161 if (currentArg.equals("--module-source-path")) { //$NON-NLS-1$
2162 if (sourcepathClasspathArg != null) {
2163 throw new IllegalArgumentException(this.bind("configure.OneOfModuleOrSourcePath")); //$NON-NLS-1$
2164 }
2165 mode = INSIDE_MODULESOURCEPATH_start;
2166 continue;
2167 }
2168 if (currentArg.equals("--add-exports")) { //$NON-NLS-1$
2169 mode = INSIDE_ADD_EXPORTS;
2170 continue;
2171 }
2172 if (currentArg.equals("--add-reads")) { //$NON-NLS-1$
2173 mode = INSIDE_ADD_READS;
2174 continue;
2175 }
2176 if (currentArg.equals("--add-modules")) { //$NON-NLS-1$
2177 mode = INSIDE_ADD_MODULES;
2178 continue;
2179 }
2180 if (currentArg.equals("--limit-modules")) { //$NON-NLS-1$
2181 mode = INSIDE_LIMIT_MODULES;
2182 continue;
2183 }
2184 if (currentArg.equals("--module-version")) { //$NON-NLS-1$
2185 mode = INSIDE_MODULE_VERSION;
2186 continue;
2187 }
2188 if (currentArg.equals("-sourcepath")) {//$NON-NLS-1$
2189 if (sourcepathClasspathArg != null) {
2190 StringBuffer errorMessage = new StringBuffer();
2191 errorMessage.append(currentArg);
2192 if ((index + 1) < argCount) {
2193 errorMessage.append(' ');
2194 errorMessage.append(newCommandLineArgs[index + 1]);
2195 }
2196 throw new IllegalArgumentException(
2197 this.bind("configure.duplicateSourcepath", errorMessage.toString())); //$NON-NLS-1$
2198 }
2199 if (moduleSourcepathArg != null) {
2200 throw new IllegalArgumentException(this.bind("configure.OneOfModuleOrSourcePath")); //$NON-NLS-1$
2201 }
2202 mode = INSIDE_SOURCE_PATH_start;
2203 continue;
2204 }
2205 if (currentArg.equals("-extdirs")) {//$NON-NLS-1$
2206 if (extdirsClasspaths != null) {
2207 StringBuffer errorMessage = new StringBuffer();
2208 errorMessage.append(currentArg);
2209 if ((index + 1) < argCount) {
2210 errorMessage.append(' ');
2211 errorMessage.append(newCommandLineArgs[index + 1]);
2212 }
2213 throw new IllegalArgumentException(
2214 this.bind("configure.duplicateExtDirs", errorMessage.toString())); //$NON-NLS-1$
2215 }
2216 mode = INSIDE_EXT_DIRS;
2217 continue;
2218 }
2219 if (currentArg.equals("-endorseddirs")) { //$NON-NLS-1$
2220 if (endorsedDirClasspaths != null) {
2221 StringBuffer errorMessage = new StringBuffer();
2222 errorMessage.append(currentArg);
2223 if ((index + 1) < argCount) {
2224 errorMessage.append(' ');
2225 errorMessage.append(newCommandLineArgs[index + 1]);
2226 }
2227 throw new IllegalArgumentException(
2228 this.bind("configure.duplicateEndorsedDirs", errorMessage.toString())); //$NON-NLS-1$
2229 }
2230 mode = INSIDE_ENDORSED_DIRS;
2231 continue;
2232 }
2233 if (currentArg.equals("-progress")) { //$NON-NLS-1$
2234 mode = DEFAULT;
2235 this.showProgress = true;
2236 continue;
2237 }
2238 if (currentArg.startsWith("-proceedOnError")) { //$NON-NLS-1$
2239 mode = DEFAULT;
2240 int length = currentArg.length();
2241 if (length > 15) {
2242 if (currentArg.equals("-proceedOnError:Fatal")) { //$NON-NLS-1$
2243 this.options.put(CompilerOptions.OPTION_FatalOptionalError, CompilerOptions.ENABLED);
2244 } else {
2245 throw new IllegalArgumentException(
2246 this.bind("configure.invalidWarningConfiguration", currentArg)); //$NON-NLS-1$
2247 }
2248 } else {
2249 this.options.put(CompilerOptions.OPTION_FatalOptionalError, CompilerOptions.DISABLED);
2250 }
2251 this.proceedOnError = true;
2252 continue;
2253 }
2254 if (currentArg.equals("-failOnWarning")) { //$NON-NLS-1$
2255 mode = DEFAULT;
2256 this.failOnWarning = true;
2257 continue;
2258 }
2259 if (currentArg.equals("-time")) { //$NON-NLS-1$
2260 mode = DEFAULT;
2261 this.timing = TIMING_ENABLED;
2262 continue;
2263 }
2264 if (currentArg.equals("-time:detail")) { //$NON-NLS-1$
2265 mode = DEFAULT;
2266 this.timing = TIMING_ENABLED|TIMING_DETAILED;
2267 continue;
2268 }
2269 if (currentArg.equals("-version") //$NON-NLS-1$
2270 || currentArg.equals("-v")) { //$NON-NLS-1$
2271 this.logger.logVersion(true);
2272 this.proceed = false;
2273 return;
2274 }
2275 if (currentArg.equals("-showversion")) { //$NON-NLS-1$
2276 printVersionRequired = true;
2277 mode = DEFAULT;
2278 continue;
2279 }
2280 if ("-deprecation".equals(currentArg)) { //$NON-NLS-1$
2281 didSpecifyDeprecation = true;
2282 this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
2283 mode = DEFAULT;
2284 continue;
2285 }
2286 if (currentArg.equals("-help") || currentArg.equals("-?")) { //$NON-NLS-1$ //$NON-NLS-2$
2287 printUsageRequired = true;
2288 mode = DEFAULT;
2289 continue;
2290 }
2291 if (currentArg.equals("-help:warn") || //$NON-NLS-1$
2292 currentArg.equals("-?:warn")) { //$NON-NLS-1$
2293 printUsageRequired = true;
2294 usageSection = "misc.usage.warn"; //$NON-NLS-1$
2295 continue;
2296 }
2297 if (currentArg.equals("-noExit")) { //$NON-NLS-1$
2298 this.systemExitWhenFinished = false;
2299 mode = DEFAULT;
2300 continue;
2301 }
2302 if (currentArg.equals("-verbose")) { //$NON-NLS-1$
2303 this.verbose = true;
2304 mode = DEFAULT;
2305 continue;
2306 }
2307 if (currentArg.equals("-referenceInfo")) { //$NON-NLS-1$
2308 this.produceRefInfo = true;
2309 mode = DEFAULT;
2310 continue;
2311 }
2312 if (currentArg.equals("-inlineJSR")) { //$NON-NLS-1$
2313 mode = DEFAULT;
2314 this.options.put(
2315 CompilerOptions.OPTION_InlineJsr,
2316 CompilerOptions.ENABLED);
2317 continue;
2318 }
2319 if (currentArg.equals("-parameters")) { //$NON-NLS-1$
2320 mode = DEFAULT;
2321 this.options.put(
2322 CompilerOptions.OPTION_MethodParametersAttribute,
2323 CompilerOptions.GENERATE);
2324 continue;
2325 }
2326 if (currentArg.equals("-genericsignature")) { //$NON-NLS-1$
2327 mode = DEFAULT;
2328 this.options.put(
2329 CompilerOptions.OPTION_LambdaGenericSignature,
2330 CompilerOptions.GENERATE);
2331 continue;
2332 }
2333 if (currentArg.startsWith("-g")) { //$NON-NLS-1$
2334 mode = DEFAULT;
2335 String debugOption = currentArg;
2336 int length = currentArg.length();
2337 if (length == 2) {
2338 this.options.put(
2339 CompilerOptions.OPTION_LocalVariableAttribute,
2340 CompilerOptions.GENERATE);
2341 this.options.put(
2342 CompilerOptions.OPTION_LineNumberAttribute,
2343 CompilerOptions.GENERATE);
2344 this.options.put(
2345 CompilerOptions.OPTION_SourceFileAttribute,
2346 CompilerOptions.GENERATE);
2347 continue;
2348 }
2349 if (length > 3) {
2350 this.options.put(
2351 CompilerOptions.OPTION_LocalVariableAttribute,
2352 CompilerOptions.DO_NOT_GENERATE);
2353 this.options.put(
2354 CompilerOptions.OPTION_LineNumberAttribute,
2355 CompilerOptions.DO_NOT_GENERATE);
2356 this.options.put(
2357 CompilerOptions.OPTION_SourceFileAttribute,
2358 CompilerOptions.DO_NOT_GENERATE);
2359 if (length == 7 && debugOption.equals("-g:" + NONE)) //$NON-NLS-1$
2360 continue;
2361 StringTokenizer tokenizer =
2362 new StringTokenizer(debugOption.substring(3, debugOption.length()), ","); //$NON-NLS-1$
2363 while (tokenizer.hasMoreTokens()) {
2364 String token = tokenizer.nextToken();
2365 if (token.equals("vars")) { //$NON-NLS-1$
2366 this.options.put(
2367 CompilerOptions.OPTION_LocalVariableAttribute,
2368 CompilerOptions.GENERATE);
2369 } else if (token.equals("lines")) { //$NON-NLS-1$
2370 this.options.put(
2371 CompilerOptions.OPTION_LineNumberAttribute,
2372 CompilerOptions.GENERATE);
2373 } else if (token.equals("source")) { //$NON-NLS-1$
2374 this.options.put(
2375 CompilerOptions.OPTION_SourceFileAttribute,
2376 CompilerOptions.GENERATE);
2377 } else {
2378 throw new IllegalArgumentException(
2379 this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
2380 }
2381 }
2382 continue;
2383 }
2384 throw new IllegalArgumentException(
2385 this.bind("configure.invalidDebugOption", debugOption)); //$NON-NLS-1$
2386 }
2387 if (currentArg.startsWith("-info")) { //$NON-NLS-1$
2388 mode = DEFAULT;
2389 String infoOption = currentArg;
2390 int length = currentArg.length();
2391 if (length == 10 && infoOption.equals("-info:" + NONE)) { //$NON-NLS-1$
2392 disableAll(ProblemSeverities.Info);
2393 continue;
2394 }
2395 if (length <= 6) {
2396 throw new IllegalArgumentException(
2397 this.bind("configure.invalidInfoConfiguration", infoOption)); //$NON-NLS-1$
2398 }
2399 int infoTokenStart;
2400 boolean isEnabling;
2401 switch (infoOption.charAt(6)) {
2402 case '+' :
2403 infoTokenStart = 7;
2404 isEnabling = true;
2405 break;
2406 case '-' :
2407 infoTokenStart = 7;
2408 isEnabling = false; // specified warnings are disabled
2409 break;
2410 default:
2411 disableAll(ProblemSeverities.Info);
2412 infoTokenStart = 6;
2413 isEnabling = true;
2414 }
2415
2416 StringTokenizer tokenizer =
2417 new StringTokenizer(infoOption.substring(infoTokenStart, infoOption.length()), ","); //$NON-NLS-1$
2418 int tokenCounter = 0;
2419
2420 while (tokenizer.hasMoreTokens()) {
2421 String token = tokenizer.nextToken();
2422 tokenCounter++;
2423 switch(token.charAt(0)) {
2424 case '+' :
2425 isEnabling = true;
2426 token = token.substring(1);
2427 break;
2428 case '-' :
2429 isEnabling = false;
2430 token = token.substring(1);
2431 }
2432 handleInfoToken(token, isEnabling);
2433 }
2434 if (tokenCounter == 0) {
2435 throw new IllegalArgumentException(
2436 this.bind("configure.invalidInfoOption", currentArg)); //$NON-NLS-1$
2437 }
2438 continue;
2439 }
2440 if (currentArg.startsWith("-warn")) { //$NON-NLS-1$
2441 mode = DEFAULT;
2442 String warningOption = currentArg;
2443 int length = currentArg.length();
2444 if (length == 10 && warningOption.equals("-warn:" + NONE)) { //$NON-NLS-1$
2445 disableAll(ProblemSeverities.Warning);
2446 continue;
2447 }
2448 if (length <= 6) {
2449 throw new IllegalArgumentException(
2450 this.bind("configure.invalidWarningConfiguration", warningOption)); //$NON-NLS-1$
2451 }
2452 int warnTokenStart;
2453 boolean isEnabling;
2454 switch (warningOption.charAt(6)) {
2455 case '+' :
2456 warnTokenStart = 7;
2457 isEnabling = true;
2458 break;
2459 case '-' :
2460 warnTokenStart = 7;
2461 isEnabling = false; // specified warnings are disabled
2462 break;
2463 default:
2464 disableAll(ProblemSeverities.Warning);
2465 warnTokenStart = 6;
2466 isEnabling = true;
2467 }
2468
2469 StringTokenizer tokenizer =
2470 new StringTokenizer(warningOption.substring(warnTokenStart, warningOption.length()), ","); //$NON-NLS-1$
2471 int tokenCounter = 0;
2472
2473 if (didSpecifyDeprecation) { // deprecation could have also been set through -deprecation option
2474 this.options.put(CompilerOptions.OPTION_ReportDeprecation, CompilerOptions.WARNING);
2475 }
2476
2477 while (tokenizer.hasMoreTokens()) {
2478 String token = tokenizer.nextToken();
2479 tokenCounter++;
2480 switch(token.charAt(0)) {
2481 case '+' :
2482 isEnabling = true;
2483 token = token.substring(1);
2484 break;
2485 case '-' :
2486 isEnabling = false;
2487 token = token.substring(1);
2488 }
2489 handleWarningToken(token, isEnabling);
2490 }
2491 if (tokenCounter == 0) {
2492 throw new IllegalArgumentException(
2493 this.bind("configure.invalidWarningOption", currentArg)); //$NON-NLS-1$
2494 }
2495 continue;
2496 }
2497 if (currentArg.startsWith("-err")) { //$NON-NLS-1$
2498 mode = DEFAULT;
2499 String errorOption = currentArg;
2500 int length = currentArg.length();
2501 if (length <= 5) {
2502 throw new IllegalArgumentException(
2503 this.bind("configure.invalidErrorConfiguration", errorOption)); //$NON-NLS-1$
2504 }
2505 int errorTokenStart;
2506 boolean isEnabling;
2507 switch (errorOption.charAt(5)) {
2508 case '+' :
2509 errorTokenStart = 6;
2510 isEnabling = true;
2511 break;
2512 case '-' :
2513 errorTokenStart = 6;
2514 isEnabling = false; // specified errors are disabled
2515 break;
2516 default:
2517 disableAll(ProblemSeverities.Error);
2518 errorTokenStart = 5;
2519 isEnabling = true;
2520 }
2521
2522 StringTokenizer tokenizer =
2523 new StringTokenizer(errorOption.substring(errorTokenStart, errorOption.length()), ","); //$NON-NLS-1$
2524 int tokenCounter = 0;
2525
2526 while (tokenizer.hasMoreTokens()) {
2527 String token = tokenizer.nextToken();
2528 tokenCounter++;
2529 switch(token.charAt(0)) {
2530 case '+' :
2531 isEnabling = true;
2532 token = token.substring(1);
2533 break;
2534 case '-' :
2535 isEnabling = false;
2536 token = token.substring(1);
2537 break;
2538 }
2539 handleErrorToken(token, isEnabling);
2540 }
2541 if (tokenCounter == 0) {
2542 throw new IllegalArgumentException(
2543 this.bind("configure.invalidErrorOption", currentArg)); //$NON-NLS-1$
2544 }
2545 continue;
2546 }
2547 if (currentArg.equals("-target")) { //$NON-NLS-1$
2548 mode = INSIDE_TARGET;
2549 continue;
2550 }
2551 if (currentArg.equals("-preserveAllLocals")) { //$NON-NLS-1$
2552 this.options.put(
2553 CompilerOptions.OPTION_PreserveUnusedLocal,
2554 CompilerOptions.PRESERVE);
2555 mode = DEFAULT;
2556 continue;
2557 }
2558 if (currentArg.equals("-enableJavadoc")) {//$NON-NLS-1$
2559 mode = DEFAULT;
2560 this.enableJavadocOn = true;
2561 continue;
2562 }
2563 if (currentArg.equals("-Xemacs")) { //$NON-NLS-1$
2564 mode = DEFAULT;
2565 this.logger.setEmacs();
2566 continue;
2567 }
2568 // annotation processing
2569 if (currentArg.startsWith("-A")) { //$NON-NLS-1$
2570 mode = DEFAULT;
2571 continue;
2572 }
2573 if (currentArg.equals("-processorpath")) { //$NON-NLS-1$
2574 mode = INSIDE_PROCESSOR_PATH_start;
2575 continue;
2576 }
2577 if (currentArg.equals("-processor")) { //$NON-NLS-1$
2578 mode = INSIDE_PROCESSOR_start;
2579 continue;
2580 }
2581 if (currentArg.equals("--processor-module-path")) { //$NON-NLS-1$
2582 mode = INSIDE_PROCESSOR_MODULE_PATH_start;
2583 continue;
2584 }
2585 if (currentArg.equals("-proc:only")) { //$NON-NLS-1$
2586 this.options.put(
2587 CompilerOptions.OPTION_GenerateClassFiles,
2588 CompilerOptions.DISABLED);
2589 mode = DEFAULT;
2590 continue;
2591 }
2592 if (currentArg.equals("-proc:none")) { //$NON-NLS-1$
2593 didSpecifyDisabledAnnotationProcessing = true;
2594 this.options.put(
2595 CompilerOptions.OPTION_Process_Annotations,
2596 CompilerOptions.DISABLED);
2597 mode = DEFAULT;
2598 continue;
2599 }
2600 if (currentArg.equals("-s")) { //$NON-NLS-1$
2601 mode = INSIDE_S_start;
2602 continue;
2603 }
2604 if (currentArg.equals("-XprintProcessorInfo") //$NON-NLS-1$
2605 || currentArg.equals("-XprintRounds")) { //$NON-NLS-1$
2606 mode = DEFAULT;
2607 continue;
2608 }
2609 // tolerated javac options - quietly filtered out
2610 if (currentArg.startsWith("-X")) { //$NON-NLS-1$
2611 mode = DEFAULT;
2612 continue;
2613 }
2614 if (currentArg.startsWith("-J")) { //$NON-NLS-1$
2615 mode = DEFAULT;
2616 continue;
2617 }
2618 if (currentArg.equals("-O")) { //$NON-NLS-1$
2619 mode = DEFAULT;
2620 continue;
2621 }
2622 if (currentArg.equals("-classNames")) { //$NON-NLS-1$
2623 mode = INSIDE_CLASS_NAMES;
2624 continue;
2625 }
2626 if (currentArg.equals("-properties")) { //$NON-NLS-1$
2627 mode = INSIDE_WARNINGS_PROPERTIES;
2628 continue;
2629 }
2630 if (currentArg.equals("-missingNullDefault")) { //$NON-NLS-1$
2631 this.options.put(CompilerOptions.OPTION_ReportMissingNonNullByDefaultAnnotation, CompilerOptions.WARNING);
2632 continue;
2633 }
2634 if (currentArg.equals("-annotationpath")) { //$NON-NLS-1$
2635 mode = INSIDE_ANNOTATIONPATH_start;
2636 continue;
2637 }
2638 break;
2639 case INSIDE_TARGET :
2640 if (this.didSpecifyTarget) {
2641 throw new IllegalArgumentException(
2642 this.bind("configure.duplicateTarget", currentArg));//$NON-NLS-1$
2643 }
2644 if (this.releaseVersion != null) {
2645 throw new IllegalArgumentException(
2646 this.bind("configure.unsupportedWithRelease", "-target"));//$NON-NLS-1$ //$NON-NLS-2$
2647 }
2648 this.didSpecifyTarget = true;
2649 if (currentArg.equals("1.1")) { //$NON-NLS-1$
2650 this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
2651 } else if (currentArg.equals("1.2")) { //$NON-NLS-1$
2652 this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
2653 } else if (currentArg.equals("jsr14")) { //$NON-NLS-1$
2654 this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_JSR14);
2655 } else if (currentArg.equals("cldc1.1")) { //$NON-NLS-1$
2656 this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_CLDC1_1);
2657 this.options.put(CompilerOptions.OPTION_InlineJsr, CompilerOptions.ENABLED);
2658 } else {
2659 String version = optionStringToVersion(currentArg);
2660 if (version != null) {
2661 this.options.put(CompilerOptions.OPTION_TargetPlatform, version);
2662 } else {
2663 throw new IllegalArgumentException(this.bind("configure.targetJDK", currentArg)); //$NON-NLS-1$
2664 }
2665 }
2666 mode = DEFAULT;
2667 continue;
2668 case INSIDE_LOG :
2669 this.log = currentArg;
2670 mode = DEFAULT;
2671 continue;
2672 case INSIDE_REPETITION :
2673 try {
2674 this.maxRepetition = Integer.parseInt(currentArg);
2675 if (this.maxRepetition <= 0) {
2676 throw new IllegalArgumentException(this.bind("configure.repetition", currentArg)); //$NON-NLS-1$
2677 }
2678 } catch (NumberFormatException e) {
2679 throw new IllegalArgumentException(this.bind("configure.repetition", currentArg), e); //$NON-NLS-1$
2680 }
2681 mode = DEFAULT;
2682 continue;
2683 case INSIDE_MAX_PROBLEMS :
2684 try {
2685 this.maxProblems = Integer.parseInt(currentArg);
2686 if (this.maxProblems <= 0) {
2687 throw new IllegalArgumentException(this.bind("configure.maxProblems", currentArg)); //$NON-NLS-1$
2688 }
2689 this.options.put(CompilerOptions.OPTION_MaxProblemPerUnit, currentArg);
2690 } catch (NumberFormatException e) {
2691 throw new IllegalArgumentException(this.bind("configure.maxProblems", currentArg), e); //$NON-NLS-1$
2692 }
2693 mode = DEFAULT;
2694 continue;
2695 case INSIDE_RELEASE:
2696 // If release is < 9, the following are disallowed:
2697 // bootclasspath, -Xbootclasspath, -Xbootclasspath/a:, -Xbootclasspath/p:,
2698 // -endorseddirs, -Djava.endorsed.dirs, -extdirs, -Djava.ext.dirs
2699
2700 // If release >= 9, the following are disallowed
2701 // --system and --upgrade-module-path
2702
2703 // -source and -target are disallowed for any --release
2704 this.releaseVersion = currentArg;
2705 long releaseToJDKLevel = CompilerOptions.releaseToJDKLevel(currentArg);
2706 if (releaseToJDKLevel == 0) {
2707 throw new IllegalArgumentException(
2708 this.bind("configure.unsupportedReleaseVersion", currentArg)); //$NON-NLS-1$
2709 }
2710 // Let's treat it as regular compliance mode
2711 this.complianceLevel = releaseToJDKLevel;
2712 String versionAsString = CompilerOptions.versionFromJdkLevel(releaseToJDKLevel);
2713 this.options.put(CompilerOptions.OPTION_Compliance, versionAsString);
2714 this.options.put(CompilerOptions.OPTION_Source, versionAsString);
2715 this.options.put(CompilerOptions.OPTION_TargetPlatform, versionAsString);
2716 mode = DEFAULT;
2717 continue;
2718 case INSIDE_SOURCE :
2719 if (this.didSpecifySource) {
2720 throw new IllegalArgumentException(
2721 this.bind("configure.duplicateSource", currentArg));//$NON-NLS-1$
2722 }
2723 if (this.releaseVersion != null) {
2724 throw new IllegalArgumentException(
2725 this.bind("configure.unsupportedWithRelease", "-source"));//$NON-NLS-1$ //$NON-NLS-2$
2726 }
2727 this.didSpecifySource = true;
2728 String version = optionStringToVersion(currentArg);
2729 if (version != null) {
2730 this.options.put(CompilerOptions.OPTION_Source, version);
2731 } else {
2732 throw new IllegalArgumentException(this.bind("configure.source", currentArg)); //$NON-NLS-1$
2733 }
2734 mode = DEFAULT;
2735 continue;
2736 case INSIDE_DEFAULT_ENCODING :
2737 if (specifiedEncodings != null) {
2738 // check already defined encoding
2739 if (!specifiedEncodings.contains(currentArg)) {
2740 if (specifiedEncodings.size() > 1) {
2741 this.logger.logWarning(
2742 this.bind("configure.differentencodings", //$NON-NLS-1$
2743 currentArg,
2744 getAllEncodings(specifiedEncodings)));
2745 } else {
2746 this.logger.logWarning(
2747 this.bind("configure.differentencoding", //$NON-NLS-1$
2748 currentArg,
2749 getAllEncodings(specifiedEncodings)));
2750 }
2751 }
2752 } else {
2753 specifiedEncodings = new HashSet<>();
2754 }
2755 try { // ensure encoding is supported
2756 new InputStreamReader(new ByteArrayInputStream(new byte[0]), currentArg);
2757 } catch (UnsupportedEncodingException e) {
2758 throw new IllegalArgumentException(
2759 this.bind("configure.unsupportedEncoding", currentArg), e); //$NON-NLS-1$
2760 }
2761 specifiedEncodings.add(currentArg);
2762 this.options.put(CompilerOptions.OPTION_Encoding, currentArg);
2763 mode = DEFAULT;
2764 continue;
2765 case INSIDE_DESTINATION_PATH :
2766 setDestinationPath(currentArg.equals(NONE) ? NONE : currentArg);
2767 mode = DEFAULT;
2768 continue;
2769 case INSIDE_SYSTEM:
2770 mode = DEFAULT;
2771 setJavaHome(currentArg);
2772 continue;
2773 case INSIDE_MODULEPATH_start:
2774 mode = DEFAULT;
2775 String[] modulepaths = new String[1];
2776 index += processPaths(newCommandLineArgs, index, currentArg, modulepaths);
2777 modulepathArg = modulepaths[0];
2778 continue;
2779 case INSIDE_MODULESOURCEPATH_start:
2780 mode = DEFAULT;
2781 String[] moduleSourcepaths = new String[1];
2782 index += processPaths(newCommandLineArgs, index, currentArg, moduleSourcepaths);
2783 moduleSourcepathArg = moduleSourcepaths[0];
2784 continue;
2785 case INSIDE_ADD_EXPORTS:
2786 mode = DEFAULT;
2787 // TODO: better to validate the option before processing it further?
2788 if (this.addonExports == Collections.EMPTY_LIST) {
2789 this.addonExports = new ArrayList<>();
2790 }
2791 this.addonExports.add(currentArg);
2792 continue;
2793 case INSIDE_ADD_READS:
2794 mode = DEFAULT;
2795 if (this.addonReads == Collections.EMPTY_LIST) {
2796 this.addonReads = new ArrayList<>();
2797 }
2798 this.addonReads.add(currentArg);
2799 continue;
2800 case INSIDE_ADD_MODULES:
2801 mode = DEFAULT;
2802 if (this.rootModules == Collections.EMPTY_SET) {
2803 this.rootModules = new HashSet<>();
2804 }
2805 StringTokenizer tokenizer = new StringTokenizer(currentArg, ","); //$NON-NLS-1$
2806 while (tokenizer.hasMoreTokens()) {
2807 this.rootModules.add(tokenizer.nextToken().trim());
2808 }
2809 continue;
2810 case INSIDE_LIMIT_MODULES:
2811 mode = DEFAULT;
2812 tokenizer = new StringTokenizer(currentArg, ","); //$NON-NLS-1$
2813 while (tokenizer.hasMoreTokens()) {
2814 if (this.limitedModules == null) {
2815 this.limitedModules = new HashSet<>();
2816 }
2817 this.limitedModules.add(tokenizer.nextToken().trim());
2818 }
2819 continue;
2820 case INSIDE_MODULE_VERSION:
2821 mode = DEFAULT;
2822 this.moduleVersion = validateModuleVersion(currentArg);
2823 continue;
2824 case INSIDE_CLASSPATH_start:
2825 mode = DEFAULT;
2826 index += processPaths(newCommandLineArgs, index, currentArg, classpaths);
2827 continue;
2828 case INSIDE_BOOTCLASSPATH_start:
2829 mode = DEFAULT;
2830 index += processPaths(newCommandLineArgs, index, currentArg, bootclasspaths);
2831 continue;
2832 case INSIDE_SOURCE_PATH_start:
2833 mode = DEFAULT;
2834 String[] sourcePaths = new String[1];
2835 index += processPaths(newCommandLineArgs, index, currentArg, sourcePaths);
2836 sourcepathClasspathArg = sourcePaths[0];
2837 continue;
2838 case INSIDE_EXT_DIRS:
2839 if (currentArg.indexOf("[-d") != -1) { //$NON-NLS-1$
2840 throw new IllegalArgumentException(
2841 this.bind("configure.unexpectedDestinationPathEntry", //$NON-NLS-1$
2842 "-extdir")); //$NON-NLS-1$
2843 }
2844 tokenizer = new StringTokenizer(currentArg, File.pathSeparator, false);
2845 extdirsClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
2846 while (tokenizer.hasMoreTokens())
2847 extdirsClasspaths.add(tokenizer.nextToken());
2848 mode = DEFAULT;
2849 continue;
2850 case INSIDE_ENDORSED_DIRS:
2851 if (currentArg.indexOf("[-d") != -1) { //$NON-NLS-1$
2852 throw new IllegalArgumentException(
2853 this.bind("configure.unexpectedDestinationPathEntry", //$NON-NLS-1$
2854 "-endorseddirs")); //$NON-NLS-1$
2855 } tokenizer = new StringTokenizer(currentArg, File.pathSeparator, false);
2856 endorsedDirClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
2857 while (tokenizer.hasMoreTokens())
2858 endorsedDirClasspaths.add(tokenizer.nextToken());
2859 mode = DEFAULT;
2860 continue;
2861 case INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH:
2862 if (currentArg.endsWith("]")) { //$NON-NLS-1$
2863 customDestinationPath = currentArg.substring(0,
2864 currentArg.length() - 1);
2865 } else {
2866 throw new IllegalArgumentException(
2867 this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$
2868 "[-d " + currentArg)); //$NON-NLS-1$
2869 }
2870 break;
2871 case INSIDE_PROCESSOR_PATH_start :
2872 // nothing to do here. This is consumed again by the AnnotationProcessorManager
2873 mode = DEFAULT;
2874 continue;
2875 case INSIDE_PROCESSOR_start :
2876 // nothing to do here. This is consumed again by the AnnotationProcessorManager
2877 mode = DEFAULT;
2878 continue;
2879 case INSIDE_PROCESSOR_MODULE_PATH_start :
2880 mode = DEFAULT;
2881 continue;
2882 case INSIDE_S_start :
2883 // nothing to do here. This is consumed again by the AnnotationProcessorManager
2884 mode = DEFAULT;
2885 continue;
2886 case INSIDE_CLASS_NAMES :
2887 tokenizer = new StringTokenizer(currentArg, ","); //$NON-NLS-1$
2888 if (this.classNames == null) {
2889 this.classNames = new String[DEFAULT_SIZE_CLASSPATH];
2890 }
2891 while (tokenizer.hasMoreTokens()) {
2892 if (this.classNames.length == classCount) {
2893 // resize
2894 System.arraycopy(
2895 this.classNames,
2896 0,
2897 (this.classNames = new String[classCount * 2]),
2898 0,
2899 classCount);
2900 }
2901 this.classNames[classCount++] = tokenizer.nextToken();
2902 }
2903 mode = DEFAULT;
2904 continue;
2905 case INSIDE_WARNINGS_PROPERTIES :
2906 initializeWarnings(currentArg);
2907 mode = DEFAULT;
2908 continue;
2909 case INSIDE_ANNOTATIONPATH_start:
2910 mode = DEFAULT;
2911 if (currentArg.isEmpty() || currentArg.charAt(0) == '-')
2912 throw new IllegalArgumentException(this.bind("configure.missingAnnotationPath", currentArg)); //$NON-NLS-1$
2913 if (ANNOTATION_SOURCE_CLASSPATH.equals(currentArg)) {
2914 this.annotationsFromClasspath = true;
2915 } else {
2916 if (this.annotationPaths == null)
2917 this.annotationPaths = new ArrayList<String>();
2918 StringTokenizer tokens = new StringTokenizer(currentArg, File.pathSeparator);
2919 while (tokens.hasMoreTokens())
2920 this.annotationPaths.add(tokens.nextToken());
2921 }
2922 continue;
2923 }
2924
2925 // default is input directory, if no custom destination path exists
2926 if (customDestinationPath == null) {
2927 if (File.separatorChar != '/') {
2928 currentArg = currentArg.replace('/', File.separatorChar);
2929 }
2930 if (currentArg.endsWith("[-d")) { //$NON-NLS-1$
2931 currentSourceDirectory = currentArg.substring(0,
2932 currentArg.length() - 3);
2933 mode = INSIDE_SOURCE_DIRECTORY_DESTINATION_PATH;
2934 continue;
2935 }
2936 currentSourceDirectory = currentArg;
2937 }
2938 File dir = new File(currentSourceDirectory);
2939 if (!dir.isDirectory()) {
2940 throw new IllegalArgumentException(
2941 this.bind("configure.unrecognizedOption", currentSourceDirectory)); //$NON-NLS-1$
2942 }
2943 String[] result = FileFinder.find(dir, SuffixConstants.SUFFIX_STRING_java);
2944 if (NONE.equals(customDestinationPath)) {
2945 customDestinationPath = NONE; // ensure == comparison
2946 }
2947 if (this.filenames != null) {
2948 // some source files were specified explicitly
2949 int length = result.length;
2950 System.arraycopy(
2951 this.filenames,
2952 0,
2953 (this.filenames = new String[length + filesCount]),
2954 0,
2955 filesCount);
2956 System.arraycopy(
2957 this.encodings,
2958 0,
2959 (this.encodings = new String[length + filesCount]),
2960 0,
2961 filesCount);
2962 System.arraycopy(
2963 this.destinationPaths,
2964 0,
2965 (this.destinationPaths = new String[length + filesCount]),
2966 0,
2967 filesCount);
2968 System.arraycopy(
2969 this.modNames,
2970 0,
2971 (this.modNames = new String[length + filesCount]),
2972 0,
2973 filesCount);
2974 System.arraycopy(result, 0, this.filenames, filesCount, length);
2975 for (int i = 0; i < length; i++) {
2976 this.encodings[filesCount + i] = customEncoding;
2977 this.destinationPaths[filesCount + i] = customDestinationPath;
2978 this.modNames[filesCount + i] = moduleName;
2979 }
2980 filesCount += length;
2981 customEncoding = null;
2982 customDestinationPath = null;
2983 currentSourceDirectory = null;
2984 } else {
2985 this.filenames = result;
2986 filesCount = this.filenames.length;
2987 this.encodings = new String[filesCount];
2988 this.destinationPaths = new String[filesCount];
2989 this.modNames = new String[filesCount];
2990 for (int i = 0; i < filesCount; i++) {
2991 this.encodings[i] = customEncoding;
2992 this.destinationPaths[i] = customDestinationPath;
2993 }
2994 customEncoding = null;
2995 customDestinationPath = null;
2996 currentSourceDirectory = null;
2997 }
2998 mode = DEFAULT;
2999 continue;
3000 }
3001 if (this.enablePreview) {
3002 this.options.put(
3003 CompilerOptions.OPTION_EnablePreviews,
3004 CompilerOptions.ENABLED);
3005 }
3006
3007 // set DocCommentSupport, with appropriate side effects on defaults if
3008 // javadoc is not enabled
3009 if (this.enableJavadocOn) {
3010 this.options.put(
3011 CompilerOptions.OPTION_DocCommentSupport,
3012 CompilerOptions.ENABLED);
3013 } else if (this.warnJavadocOn || this.warnAllJavadocOn) {
3014 this.options.put(
3015 CompilerOptions.OPTION_DocCommentSupport,
3016 CompilerOptions.ENABLED);
3017 // override defaults: references that are embedded in javadoc are ignored
3018 // from the perspective of parameters and thrown exceptions usage
3019 this.options.put(
3020 CompilerOptions.OPTION_ReportUnusedParameterIncludeDocCommentReference,
3021 CompilerOptions.DISABLED);
3022 this.options.put(
3023 CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionIncludeDocCommentReference,
3024 CompilerOptions.DISABLED);
3025 }
3026 // configure warnings for javadoc contents
3027 if (this.warnJavadocOn) {
3028 this.options.put(
3029 CompilerOptions.OPTION_ReportInvalidJavadocTags,
3030 CompilerOptions.ENABLED);
3031 this.options.put(
3032 CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
3033 CompilerOptions.ENABLED);
3034 this.options.put(
3035 CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
3036 CompilerOptions.ENABLED);
3037 this.options.put(
3038 CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
3039 CompilerOptions.PRIVATE);
3040 }
3041 if (printUsageRequired || (filesCount == 0 && classCount == 0)) {
3042 if (usageSection == null) {
3043 printUsage(); // default
3044 } else {
3045 printUsage(usageSection);
3046 }
3047 this.proceed = false;
3048 return;
3049 }
3050
3051 if (this.log != null) {
3052 this.logger.setLog(this.log);
3053 } else {
3054 this.showProgress = false;
3055 }
3056 this.logger.logVersion(printVersionRequired);
3057
3058 validateOptions(didSpecifyCompliance);
3059
3060 // Enable annotation processing by default in batch mode when compliance is at least 1.6
3061 // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=185768
3062 if (!didSpecifyDisabledAnnotationProcessing
3063 && CompilerOptions.versionToJdkLevel(this.options.get(CompilerOptions.OPTION_Compliance)) >= ClassFileConstants.JDK1_6) {
3064 this.options.put(CompilerOptions.OPTION_Process_Annotations, CompilerOptions.ENABLED);
3065 }
3066
3067 this.logger.logCommandLineArguments(newCommandLineArgs);
3068 this.logger.logOptions(this.options);
3069
3070 if (this.maxRepetition == 0) {
3071 this.maxRepetition = 1;
3072 }
3073 if (this.maxRepetition >= 3 && (this.timing & TIMING_ENABLED) != 0) {
3074 this.compilerStats = new CompilerStats[this.maxRepetition];
3075 }
3076
3077 if (filesCount != 0) {
3078 System.arraycopy(
3079 this.filenames,
3080 0,
3081 (this.filenames = new String[filesCount]),
3082 0,
3083 filesCount);
3084 }
3085
3086 if (classCount != 0) {
3087 System.arraycopy(
3088 this.classNames,
3089 0,
3090 (this.classNames = new String[classCount]),
3091 0,
3092 classCount);
3093 }
3094
3095 setPaths(bootclasspaths,
3096 sourcepathClasspathArg,
3097 sourcepathClasspaths,
3098 classpaths,
3099 modulepathArg,
3100 moduleSourcepathArg,
3101 extdirsClasspaths,
3102 endorsedDirClasspaths,
3103 customEncoding);
3104
3105 if (specifiedEncodings != null && specifiedEncodings.size() > 1) {
3106 this.logger.logWarning(this.bind("configure.multipleencodings", //$NON-NLS-1$
3107 this.options.get(CompilerOptions.OPTION_Encoding),
3108 getAllEncodings(specifiedEncodings)));
3109 }
3110 if (this.pendingErrors != null) {
3111 for (Iterator<String> iterator = this.pendingErrors.iterator(); iterator.hasNext(); ) {
3112 String message = iterator.next();
3113 this.logger.logPendingError(message);
3114 }
3115 this.pendingErrors = null;
3116 }
3117 }
3118 /** Translates any supported standarde version starting at 1.3 up-to latest into the corresponding constant from CompilerOptions */
3119 @SuppressWarnings("nls")
optionStringToVersion(String currentArg)3120 private String optionStringToVersion(String currentArg) {
3121 switch (currentArg) {
3122 case "1.3": return CompilerOptions.VERSION_1_3;
3123 case "1.4": return CompilerOptions.VERSION_1_4;
3124 case "1.5":
3125 case "5":
3126 case "5.0":
3127 return CompilerOptions.VERSION_1_5;
3128 case "1.6":
3129 case "6":
3130 case "6.0":
3131 return CompilerOptions.VERSION_1_6;
3132 case "1.7":
3133 case "7":
3134 case "7.0":
3135 return CompilerOptions.VERSION_1_7;
3136 case "1.8":
3137 case "8":
3138 case "8.0":
3139 return CompilerOptions.VERSION_1_8;
3140 case "1.9":
3141 case "9":
3142 case "9.0":
3143 return CompilerOptions.VERSION_9;
3144 case "10":
3145 case "10.0":
3146 return CompilerOptions.VERSION_10;
3147 case "11":
3148 case "11.0":
3149 return CompilerOptions.VERSION_11;
3150 case "12":
3151 case "12.0":
3152 return CompilerOptions.VERSION_12;
3153 case "13":
3154 case "13.0":
3155 return CompilerOptions.VERSION_13;
3156 case "14":
3157 case "14.0":
3158 return CompilerOptions.VERSION_14;
3159 default:
3160 return null;
3161 }
3162 }
validateModuleVersion(String versionString)3163 private String validateModuleVersion(String versionString) {
3164 try {
3165 Class<?> versionClass = Class.forName("java.lang.module.ModuleDescriptor$Version"); //$NON-NLS-1$
3166 Method method = versionClass.getMethod("parse", String.class); //$NON-NLS-1$
3167 try {
3168 method.invoke(null, versionString);
3169 } catch (InvocationTargetException e) {
3170 if (e.getCause() instanceof IllegalArgumentException)
3171 throw (IllegalArgumentException) e.getCause();
3172 }
3173 } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalAccessException e) {
3174 this.logger.logWarning(this.bind("configure.no.ModuleDescriptorVersionparse")); //$NON-NLS-1$
3175 }
3176 return versionString;
3177 }
3178
getNewParser()3179 private Parser getNewParser() {
3180 return new Parser(new ProblemReporter(getHandlingPolicy(),
3181 new CompilerOptions(this.options), getProblemFactory()), false);
3182 }
extractModuleDesc(String fileName)3183 private IModule extractModuleDesc(String fileName) {
3184 IModule mod = null;
3185 // this.options may not be completely populated yet, and definitely not
3186 // validated. Make sure the source level is set for the parser
3187 Map<String,String> opts = new HashMap<String, String>(this.options);
3188 opts.put(CompilerOptions.OPTION_Source, this.options.get(CompilerOptions.OPTION_Compliance));
3189 Parser parser = new Parser(new ProblemReporter(getHandlingPolicy(),
3190 new CompilerOptions(opts), getProblemFactory()), false);
3191 if (fileName.toLowerCase().endsWith(IModule.MODULE_INFO_JAVA)) {
3192
3193 ICompilationUnit cu = new CompilationUnit(null, fileName, null);
3194 CompilationResult compilationResult = new CompilationResult(cu, 0, 1, 10);
3195 CompilationUnitDeclaration unit = parser.parse(cu, compilationResult);
3196 if (unit.isModuleInfo() && unit.moduleDeclaration != null) {
3197 mod = new BasicModule(unit.moduleDeclaration, null);
3198 }
3199 } else if (fileName.toLowerCase().endsWith(IModule.MODULE_INFO_CLASS)) {
3200 try {
3201 ClassFileReader reader = ClassFileReader.read(fileName); // Check the absolute path?
3202 mod = reader.getModuleDeclaration();
3203 } catch (ClassFormatException | IOException e) {
3204 e.printStackTrace();
3205 throw new IllegalArgumentException(
3206 this.bind("configure.invalidModuleDescriptor", fileName)); //$NON-NLS-1$
3207 }
3208 }
3209 return mod;
3210 }
3211
decodeIgnoreOptionalProblemsFromFolders(String folders)3212 private static char[][] decodeIgnoreOptionalProblemsFromFolders(String folders) {
3213 StringTokenizer tokenizer = new StringTokenizer(folders, File.pathSeparator);
3214 char[][] result = new char[2 * tokenizer.countTokens()][];
3215 int count = 0;
3216 while (tokenizer.hasMoreTokens()) {
3217 String fileName = tokenizer.nextToken();
3218 // relative folder names are created relative to the current user dir
3219 File file = new File(fileName);
3220 if (file.exists()) {
3221 String absolutePath = file.getAbsolutePath();
3222 result[count++] = absolutePath.toCharArray();
3223 // if the file exists, we should try to use its canonical path
3224 try {
3225 String canonicalPath = file.getCanonicalPath();
3226 if (!absolutePath.equals(canonicalPath)) {
3227 result[count++] = canonicalPath.toCharArray();
3228 }
3229 } catch (IOException e) {
3230 // ignore
3231 }
3232 } else {
3233 // if the file does not exist, use the name that was specified
3234 result[count++] = fileName.toCharArray();
3235 }
3236 }
3237 if (count < result.length) {
3238 char[][] shortened = new char[count][];
3239 System.arraycopy(result, 0, shortened, 0, count);
3240 result = shortened;
3241 }
3242 return result;
3243 }
3244
getAllEncodings(Set<String> encodings)3245 private static String getAllEncodings(Set<String> encodings) {
3246 int size = encodings.size();
3247 String[] allEncodings = new String[size];
3248 encodings.toArray(allEncodings);
3249 Arrays.sort(allEncodings);
3250 StringBuffer buffer = new StringBuffer();
3251 for (int i = 0; i < size; i++) {
3252 if (i > 0) {
3253 buffer.append(", "); //$NON-NLS-1$
3254 }
3255 buffer.append(allEncodings[i]);
3256 }
3257 return String.valueOf(buffer);
3258 }
3259 @SuppressWarnings("rawtypes")
initializeWarnings(String propertiesFile)3260 private void initializeWarnings(String propertiesFile) {
3261 File file = new File(propertiesFile);
3262 if (!file.exists()) {
3263 throw new IllegalArgumentException(this.bind("configure.missingwarningspropertiesfile", propertiesFile)); //$NON-NLS-1$
3264 }
3265 BufferedInputStream stream = null;
3266 Properties properties = null;
3267 try {
3268 stream = new BufferedInputStream(new FileInputStream(propertiesFile));
3269 properties = new Properties();
3270 properties.load(stream);
3271 } catch(IOException e) {
3272 e.printStackTrace();
3273 throw new IllegalArgumentException(this.bind("configure.ioexceptionwarningspropertiesfile", propertiesFile)); //$NON-NLS-1$
3274 } finally {
3275 if (stream != null) {
3276 try {
3277 stream.close();
3278 } catch(IOException e) {
3279 // ignore
3280 }
3281 }
3282 }
3283 for(Iterator iterator = properties.entrySet().iterator(); iterator.hasNext(); ) {
3284 Map.Entry entry = (Map.Entry) iterator.next();
3285 final String key = entry.getKey().toString();
3286 if (key.startsWith("org.eclipse.jdt.core.compiler.")) { //$NON-NLS-1$
3287 this.options.put(key, entry.getValue().toString());
3288 }
3289 }
3290 // when using a properties file mimic relevant defaults from JavaCorePreferenceInitializer:
3291 if (!properties.containsKey(CompilerOptions.OPTION_LocalVariableAttribute)) {
3292 this.options.put(CompilerOptions.OPTION_LocalVariableAttribute, CompilerOptions.GENERATE);
3293 }
3294 if (!properties.containsKey(CompilerOptions.OPTION_PreserveUnusedLocal)) {
3295 this.options.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.PRESERVE);
3296 }
3297 if (!properties.containsKey(CompilerOptions.OPTION_DocCommentSupport)) {
3298 this.options.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.ENABLED);
3299 }
3300 if (!properties.containsKey(CompilerOptions.OPTION_ReportForbiddenReference)) {
3301 this.options.put(CompilerOptions.OPTION_ReportForbiddenReference, CompilerOptions.ERROR);
3302 }
3303 }
enableAll(int severity)3304 protected void enableAll(int severity) {
3305 String newValue = null;
3306 switch(severity) {
3307 case ProblemSeverities.Error :
3308 newValue = CompilerOptions.ERROR;
3309 break;
3310 case ProblemSeverities.Warning :
3311 newValue = CompilerOptions.WARNING;
3312 break;
3313 }
3314 Map.Entry<String, String>[] entries = this.options.entrySet().toArray(new Map.Entry[this.options.size()]);
3315 for (int i = 0, max = entries.length; i < max; i++) {
3316 Map.Entry<String, String> entry = entries[i];
3317 if (entry.getValue().equals(CompilerOptions.IGNORE)) {
3318 this.options.put(entry.getKey(), newValue);
3319 }
3320 }
3321 this.options.put(CompilerOptions.OPTION_TaskTags, Util.EMPTY_STRING);
3322 if (newValue != null) {
3323 this.options.remove(newValue);
3324 }
3325 }
disableAll(int severity)3326 protected void disableAll(int severity) {
3327 String checkedValue = null;
3328 switch(severity) {
3329 case ProblemSeverities.Error :
3330 checkedValue = CompilerOptions.ERROR;
3331 break;
3332 case ProblemSeverities.Warning :
3333 checkedValue = CompilerOptions.WARNING;
3334 break;
3335 case ProblemSeverities.Info :
3336 checkedValue = CompilerOptions.INFO;
3337 break;
3338 }
3339 Set<Entry<String, String>> entrySet = this.options.entrySet();
3340 for (Entry<String, String> entry : entrySet) {
3341 if (entry.getValue().equals(checkedValue)) {
3342 this.options.put(entry.getKey(), CompilerOptions.IGNORE);
3343 }
3344 }
3345 if (checkedValue != null) {
3346 this.options.put(checkedValue, CompilerOptions.IGNORE);
3347 }
3348 if (severity == ProblemSeverities.Warning) {
3349 disableAll(ProblemSeverities.Info);
3350 }
3351 }
extractDestinationPathFromSourceFile(CompilationResult result)3352 public String extractDestinationPathFromSourceFile(CompilationResult result) {
3353 ICompilationUnit compilationUnit = result.compilationUnit;
3354 if (compilationUnit != null) {
3355 char[] fileName = compilationUnit.getFileName();
3356 int lastIndex = CharOperation.lastIndexOf(java.io.File.separatorChar, fileName);
3357 if (lastIndex != -1) {
3358 final String outputPathName = new String(fileName, 0, lastIndex);
3359 final File output = new File(outputPathName);
3360 if (output.exists() && output.isDirectory()) {
3361 return outputPathName;
3362 }
3363 }
3364 }
3365 return System.getProperty("user.dir"); //$NON-NLS-1$
3366 }
3367 /*
3368 * Answer the component to which will be handed back compilation results from the compiler
3369 */
getBatchRequestor()3370 public ICompilerRequestor getBatchRequestor() {
3371 return new BatchCompilerRequestor(this);
3372 }
3373 /*
3374 * Build the set of compilation source units
3375 */
getCompilationUnits()3376 public CompilationUnit[] getCompilationUnits() {
3377 int fileCount = this.filenames.length;
3378 CompilationUnit[] units = new CompilationUnit[fileCount];
3379 HashtableOfObject knownFileNames = new HashtableOfObject(fileCount);
3380
3381 String defaultEncoding = this.options.get(CompilerOptions.OPTION_Encoding);
3382 if (Util.EMPTY_STRING.equals(defaultEncoding))
3383 defaultEncoding = null;
3384
3385 for (int round = 0; round < 2; round++) {
3386 for (int i = 0; i < fileCount; i++) {
3387 char[] charName = this.filenames[i].toCharArray();
3388 boolean isModuleInfo = CharOperation.endsWith(charName, TypeConstants.MODULE_INFO_FILE_NAME);
3389 if (isModuleInfo == (round==0)) { // 1st round: modules, 2nd round others (to ensure populating pathToModCU well in time)
3390 if (knownFileNames.get(charName) != null)
3391 throw new IllegalArgumentException(this.bind("unit.more", this.filenames[i])); //$NON-NLS-1$
3392 knownFileNames.put(charName, charName);
3393 File file = new File(this.filenames[i]);
3394 if (!file.exists())
3395 throw new IllegalArgumentException(this.bind("unit.missing", this.filenames[i])); //$NON-NLS-1$
3396 String encoding = this.encodings[i];
3397 if (encoding == null)
3398 encoding = defaultEncoding;
3399 String fileName;
3400 try {
3401 fileName = file.getCanonicalPath();
3402 } catch (IOException e) {
3403 // if we got exception during canonicalization, fall back to the name that was specified
3404 fileName = this.filenames[i];
3405 }
3406 units[i] = new CompilationUnit(null, fileName, encoding, this.destinationPaths[i],
3407 shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName.toCharArray()),
3408 this.modNames[i]);
3409 }
3410 }
3411 }
3412 return units;
3413 }
3414
3415 /*
3416 * Low-level API performing the actual compilation
3417 */
getHandlingPolicy()3418 public IErrorHandlingPolicy getHandlingPolicy() {
3419
3420 // passes the initial set of files to the batch oracle (to avoid finding more than once the same units when case insensitive match)
3421 return new IErrorHandlingPolicy() {
3422 @Override
3423 public boolean proceedOnErrors() {
3424 return Main.this.proceedOnError; // stop if there are some errors
3425 }
3426 @Override
3427 public boolean stopOnFirstError() {
3428 return false;
3429 }
3430 @Override
3431 public boolean ignoreAllErrors() {
3432 return false;
3433 }
3434 };
3435 }
3436 private void setJavaHome(String javaHome) {
3437 File release = new File(javaHome, "release"); //$NON-NLS-1$
3438 Properties prop = new Properties();
3439 try {
3440 prop.load(new FileReader(release));
3441 String ver = prop.getProperty("JAVA_VERSION"); //$NON-NLS-1$
3442 if (ver != null)
3443 ver = ver.replace("\"", ""); //$NON-NLS-1$//$NON-NLS-2$
3444 this.javaHomeCache = new File(javaHome);
3445 this.javaHomeChecked = true;
3446 } catch (IOException e) {
3447 throw new IllegalArgumentException(this.bind("configure.invalidSystem", javaHome)); //$NON-NLS-1$
3448 }
3449 }
3450 /*
3451 * External API
3452 */
3453 public File getJavaHome() {
3454 if (!this.javaHomeChecked) {
3455 this.javaHomeChecked = true;
3456 this.javaHomeCache = Util.getJavaHome();
3457 }
3458 return this.javaHomeCache;
3459 }
3460
3461 public FileSystem getLibraryAccess() {
3462 FileSystem nameEnvironment = new FileSystem(this.checkedClasspaths, this.filenames,
3463 this.annotationsFromClasspath && CompilerOptions.ENABLED.equals(this.options.get(CompilerOptions.OPTION_AnnotationBasedNullAnalysis)),
3464 this.limitedModules);
3465 nameEnvironment.module = this.module;
3466 processAddonModuleOptions(nameEnvironment);
3467 return nameEnvironment;
3468 }
3469
3470 /*
3471 * Low-level API performing the actual compilation
3472 */
3473 public IProblemFactory getProblemFactory() {
3474 return new DefaultProblemFactory(this.compilerLocale);
3475 }
3476
3477 /*
3478 * External API
3479 */
3480 protected ArrayList<Classpath> handleBootclasspath(ArrayList<String> bootclasspaths, String customEncoding) {
3481 final int bootclasspathsSize;
3482 ArrayList<Classpath> result = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
3483 if ((bootclasspaths != null)
3484 && ((bootclasspathsSize = bootclasspaths.size()) != 0)) {
3485 result = new ArrayList<>(bootclasspathsSize);
3486 for (String path : bootclasspaths) {
3487 processPathEntries(DEFAULT_SIZE_CLASSPATH, result, path, customEncoding, false, true);
3488 }
3489 } else {
3490 try {
3491 Util.collectVMBootclasspath(result, this.javaHomeCache);
3492 } catch(IllegalStateException e) {
3493 throw new IllegalArgumentException(this.bind("configure.invalidSystem", this.javaHomeCache.toString())); //$NON-NLS-1$
3494 }
3495 }
3496 return result;
3497 }
3498 private void processAddonModuleOptions(FileSystem env) {
3499 Map<String, IPackageExport[]> exports = new HashMap<>();
3500 for (String option : this.addonExports) {
3501 AddExport addExport = ModuleFinder.extractAddonExport(option);
3502 if (addExport != null) {
3503 String modName = addExport.sourceModuleName;
3504 IPackageExport export = addExport.export;
3505 IPackageExport[] existing = exports.get(modName);
3506 if (existing == null) {
3507 existing = new IPackageExport[1];
3508 existing[0] = export;
3509 exports.put(modName, existing);
3510 } else {
3511 for (IPackageExport iPackageExport : existing) {
3512 if (CharOperation.equals(iPackageExport.name(), export.name())) {
3513 throw new IllegalArgumentException(this.bind("configure.duplicateExport")); //$NON-NLS-1$
3514 }
3515 }
3516 IPackageExport[] updated = new IPackageExport[existing.length + 1];
3517 System.arraycopy(existing, 0, updated, 0, existing.length);
3518 updated[existing.length] = export;
3519 exports.put(modName, updated);
3520 }
3521 env.addModuleUpdate(modName, m -> m.addExports(export.name(), export.targets()), UpdateKind.PACKAGE);
3522 } else {
3523 throw new IllegalArgumentException(this.bind("configure.invalidModuleOption", "--add-exports " + option)); //$NON-NLS-1$ //$NON-NLS-2$
3524 }
3525 }
3526 for (String option : this.addonReads) {
3527 String[] result = ModuleFinder.extractAddonRead(option);
3528 if (result != null && result.length == 2) {
3529 env.addModuleUpdate(result[0], m -> m.addReads(result[1].toCharArray()), UpdateKind.MODULE);
3530 } else {
3531 throw new IllegalArgumentException(this.bind("configure.invalidModuleOption", "--add-reads " + option)); //$NON-NLS-1$ //$NON-NLS-2$
3532 }
3533 }
3534 }
3535 protected ArrayList<FileSystem.Classpath> handleModulepath(String arg) {
3536 ArrayList<String> modulePaths = processModulePathEntries(arg);
3537 ArrayList<Classpath> result = new ArrayList<>();
3538 if ((modulePaths != null && modulePaths.size() > 0)) {
3539 for (String path : modulePaths) {
3540 File file = new File(path);
3541 if (file.isDirectory()) {
3542 result.addAll(
3543 ModuleFinder.findModules(file, null, getNewParser(), this.options, true, this.releaseVersion));
3544 } else {
3545 Classpath modulePath = ModuleFinder.findModule(file, null, getNewParser(), this.options, true, this.releaseVersion);
3546 if (modulePath != null)
3547 result.add(modulePath);
3548 }
3549 }
3550 }
3551 // TODO: What about chained jars from MANIFEST.MF? Check with spec
3552 return result;
3553 }
3554 protected ArrayList<FileSystem.Classpath> handleModuleSourcepath(String arg) {
3555 ArrayList<String> modulePaths = processModulePathEntries(arg);
3556 ArrayList<FileSystem.Classpath> result = new ArrayList<>();
3557 if ((modulePaths != null)
3558 && (modulePaths.size() != 0)) {
3559
3560 if (this.destinationPath == null) {
3561 addPendingErrors(this.bind("configure.missingDestinationPath"));//$NON-NLS-1$
3562 }
3563 String[] paths = new String[modulePaths.size()];
3564 modulePaths.toArray(paths);
3565 for (int i = 0; i < paths.length; i++) {
3566 File dir = new File(paths[i]);
3567 if (dir.isDirectory()) {
3568 // 1. Create FileSystem.Classpath for each module
3569 // 2. Iterator each module in case of directory for source files and add to this.fileNames
3570
3571 List<Classpath> modules = ModuleFinder.findModules(dir, this.destinationPath, getNewParser(), this.options, false, this.releaseVersion);
3572 for (Classpath classpath : modules) {
3573 result.add(classpath);
3574 Path modLocation = Paths.get(classpath.getPath()).toAbsolutePath();
3575 String destPath = classpath.getDestinationPath();
3576 IModule mod = classpath.getModule();
3577 String moduleName = mod == null ? null : new String(mod.name());
3578 for(int j = 0; j < this.filenames.length; j++) {
3579 Path filePath;
3580 try {
3581 // Get canonical path just as the classpath location is stored with the same.
3582 // To avoid mismatch of /USER_JAY and /USE~1 in windows systems.
3583 filePath = new File(this.filenames[j]).getCanonicalFile().toPath();
3584 if (filePath.startsWith(modLocation)) {
3585 this.modNames[j] = moduleName;
3586 this.destinationPaths[j] = destPath;
3587 }
3588 } catch (IOException e) {
3589 // Files doesn't exist and perhaps doesn't belong in a module, move on to other files
3590 // Use empty module name to distinguish from missing module case
3591 this.modNames[j] = ""; //$NON-NLS-1$
3592 }
3593 }
3594 }
3595 }
3596 }
3597 for(int j = 0; j < this.filenames.length; j++) {
3598 if (this.modNames[j] == null) {
3599 throw new IllegalArgumentException(this.bind("configure.notOnModuleSourcePath", new String[] {this.filenames[j]})); //$NON-NLS-1$
3600 }
3601 }
3602 }
3603 return result;
3604 }
3605 /*
3606 * External API
3607 */
3608 protected ArrayList<FileSystem.Classpath> handleClasspath(ArrayList<String> classpaths, String customEncoding) {
3609 ArrayList<FileSystem.Classpath> initial = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
3610 if (classpaths != null && classpaths.size() > 0) {
3611 for (String path : classpaths) {
3612 processPathEntries(DEFAULT_SIZE_CLASSPATH, initial, path, customEncoding, false, true);
3613 }
3614 } else {
3615 // no user classpath specified.
3616 String classProp = System.getProperty("java.class.path"); //$NON-NLS-1$
3617 if ((classProp == null) || (classProp.length() == 0)) {
3618 addPendingErrors(this.bind("configure.noClasspath")); //$NON-NLS-1$
3619 final Classpath classpath = FileSystem.getClasspath(System.getProperty("user.dir"), customEncoding, null, this.options, this.releaseVersion);//$NON-NLS-1$
3620 if (classpath != null) {
3621 initial.add(classpath);
3622 }
3623 } else {
3624 StringTokenizer tokenizer = new StringTokenizer(classProp, File.pathSeparator);
3625 String token;
3626 while (tokenizer.hasMoreTokens()) {
3627 token = tokenizer.nextToken();
3628 FileSystem.Classpath currentClasspath = FileSystem
3629 .getClasspath(token, customEncoding, null, this.options, this.releaseVersion);
3630 if (currentClasspath != null) {
3631 initial.add(currentClasspath);
3632 } else if (token.length() != 0) {
3633 addPendingErrors(this.bind("configure.incorrectClasspath", token));//$NON-NLS-1$
3634 }
3635 }
3636 }
3637 }
3638 ArrayList<Classpath> result = new ArrayList<>();
3639 HashMap<String, Classpath> knownNames = new HashMap<>();
3640 FileSystem.ClasspathSectionProblemReporter problemReporter =
3641 new FileSystem.ClasspathSectionProblemReporter() {
3642 @Override
3643 public void invalidClasspathSection(String jarFilePath) {
3644 addPendingErrors(bind("configure.invalidClasspathSection", jarFilePath)); //$NON-NLS-1$
3645 }
3646 @Override
3647 public void multipleClasspathSections(String jarFilePath) {
3648 addPendingErrors(bind("configure.multipleClasspathSections", jarFilePath)); //$NON-NLS-1$
3649 }
3650 };
3651 while (! initial.isEmpty()) {
3652 Classpath current = initial.remove(0);
3653 String currentPath = current.getPath();
3654 if (knownNames.get(currentPath) == null) {
3655 knownNames.put(currentPath, current);
3656 result.add(current);
3657 List<Classpath> linkedJars = current.fetchLinkedJars(problemReporter);
3658 if (linkedJars != null) {
3659 initial.addAll(0, linkedJars);
3660 }
3661 }
3662 }
3663 return result;
3664 }
3665 /*
3666 * External API
3667 */
3668 protected ArrayList<FileSystem.Classpath> handleEndorseddirs(ArrayList<String> endorsedDirClasspaths) {
3669 final File javaHome = getJavaHome();
3670 /*
3671 * Feed endorsedDirClasspath according to:
3672 * - -endorseddirs first if present;
3673 * - else java.endorsed.dirs if defined;
3674 * - else default extensions directory for the platform. (/lib/endorsed)
3675 */
3676 if (endorsedDirClasspaths == null) {
3677 endorsedDirClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
3678 String endorsedDirsStr = System.getProperty("java.endorsed.dirs"); //$NON-NLS-1$
3679 if (endorsedDirsStr == null) {
3680 if (javaHome != null) {
3681 endorsedDirClasspaths.add(javaHome.getAbsolutePath() + "/lib/endorsed"); //$NON-NLS-1$
3682 }
3683 } else {
3684 StringTokenizer tokenizer = new StringTokenizer(endorsedDirsStr, File.pathSeparator);
3685 while (tokenizer.hasMoreTokens()) {
3686 endorsedDirClasspaths.add(tokenizer.nextToken());
3687 }
3688 }
3689 }
3690
3691 /*
3692 * Feed extdirsClasspath with the entries found into the directories listed by
3693 * extdirsNames.
3694 */
3695 if (endorsedDirClasspaths.size() != 0) {
3696 ArrayList<FileSystem.Classpath> result = new ArrayList<>();
3697 File[] directoriesToCheck = new File[endorsedDirClasspaths.size()];
3698 for (int i = 0; i < directoriesToCheck.length; i++)
3699 directoriesToCheck[i] = new File(endorsedDirClasspaths.get(i));
3700 File[][] endorsedDirsJars = getLibrariesFiles(directoriesToCheck);
3701 if (endorsedDirsJars != null) {
3702 for (int i = 0, max = endorsedDirsJars.length; i < max; i++) {
3703 File[] current = endorsedDirsJars[i];
3704 if (current != null) {
3705 for (int j = 0, max2 = current.length; j < max2; j++) {
3706 FileSystem.Classpath classpath =
3707 FileSystem.getClasspath(
3708 current[j].getAbsolutePath(),
3709 null, null, this.options, this.releaseVersion);
3710 if (classpath != null) {
3711 result.add(classpath);
3712 }
3713 }
3714 } else if (directoriesToCheck[i].isFile()) {
3715 addPendingErrors(
3716 this.bind(
3717 "configure.incorrectEndorsedDirsEntry", //$NON-NLS-1$
3718 directoriesToCheck[i].getAbsolutePath()));
3719 }
3720 }
3721 }
3722 return result;
3723 }
3724 return FileSystem.EMPTY_CLASSPATH;
3725 }
3726
3727 /*
3728 * External API
3729 * Handle extdirs processing
3730 */
3731 protected ArrayList<FileSystem.Classpath> handleExtdirs(ArrayList<String> extdirsClasspaths) {
3732 final File javaHome = getJavaHome();
3733
3734 /*
3735 * Feed extDirClasspath according to:
3736 * - -extdirs first if present;
3737 * - else java.ext.dirs if defined;
3738 * - else default extensions directory for the platform.
3739 */
3740 if (extdirsClasspaths == null) {
3741 extdirsClasspaths = new ArrayList<>(DEFAULT_SIZE_CLASSPATH);
3742 String extdirsStr = System.getProperty("java.ext.dirs"); //$NON-NLS-1$
3743 if (extdirsStr == null) {
3744 extdirsClasspaths.add(javaHome.getAbsolutePath() + "/lib/ext"); //$NON-NLS-1$
3745 } else {
3746 StringTokenizer tokenizer = new StringTokenizer(extdirsStr, File.pathSeparator);
3747 while (tokenizer.hasMoreTokens())
3748 extdirsClasspaths.add(tokenizer.nextToken());
3749 }
3750 }
3751
3752 /*
3753 * Feed extdirsClasspath with the entries found into the directories listed by
3754 * extdirsNames.
3755 */
3756 if (extdirsClasspaths.size() != 0) {
3757 ArrayList<FileSystem.Classpath> result = new ArrayList<>();
3758 File[] directoriesToCheck = new File[extdirsClasspaths.size()];
3759 for (int i = 0; i < directoriesToCheck.length; i++)
3760 directoriesToCheck[i] = new File(extdirsClasspaths.get(i));
3761 File[][] extdirsJars = getLibrariesFiles(directoriesToCheck);
3762 if (extdirsJars != null) {
3763 for (int i = 0, max = extdirsJars.length; i < max; i++) {
3764 File[] current = extdirsJars[i];
3765 if (current != null) {
3766 for (int j = 0, max2 = current.length; j < max2; j++) {
3767 FileSystem.Classpath classpath =
3768 FileSystem.getClasspath(
3769 current[j].getAbsolutePath(),
3770 null, null, this.options, this.releaseVersion);
3771 if (classpath != null) {
3772 result.add(classpath);
3773 }
3774 }
3775 } else if (directoriesToCheck[i].isFile()) {
3776 addPendingErrors(this.bind(
3777 "configure.incorrectExtDirsEntry", //$NON-NLS-1$
3778 directoriesToCheck[i].getAbsolutePath()));
3779 }
3780 }
3781 }
3782 return result;
3783 }
3784
3785 return FileSystem.EMPTY_CLASSPATH;
3786 }
3787
3788 protected boolean isIgnored(IProblem problem) {
3789 if (problem == null) {
3790 return true;
3791 }
3792 if (problem.isError()) {
3793 return false;
3794 }
3795 String key = problem.isInfo() ? CompilerOptions.INFO : CompilerOptions.WARNING;
3796 if (CompilerOptions.IGNORE.equals(this.options.get(key))) {
3797 return true;
3798 }
3799 if (this.ignoreOptionalProblemsFromFolders != null) {
3800 char[] fileName = problem.getOriginatingFileName();
3801 if (fileName != null) {
3802 return shouldIgnoreOptionalProblems(this.ignoreOptionalProblemsFromFolders, fileName);
3803 }
3804 }
3805 return false;
3806 }
3807
3808 /*
3809 * External API
3810 * Handle a single warning token.
3811 */
3812 protected void handleInfoToken(String token, boolean isEnabling) {
3813 handleErrorOrWarningToken(token, isEnabling, ProblemSeverities.Info);
3814 }
3815 protected void handleWarningToken(String token, boolean isEnabling) {
3816 handleErrorOrWarningToken(token, isEnabling, ProblemSeverities.Warning);
3817 }
3818 protected void handleErrorToken(String token, boolean isEnabling) {
3819 handleErrorOrWarningToken(token, isEnabling, ProblemSeverities.Error);
3820 }
3821 private void setSeverity(String compilerOptions, int severity, boolean isEnabling) {
3822 if (isEnabling) {
3823 switch(severity) {
3824 case ProblemSeverities.Error :
3825 this.options.put(compilerOptions, CompilerOptions.ERROR);
3826 break;
3827 case ProblemSeverities.Warning :
3828 this.options.put(compilerOptions, CompilerOptions.WARNING);
3829 break;
3830 case ProblemSeverities.Info :
3831 this.options.put(compilerOptions, CompilerOptions.INFO);
3832 break;
3833 default:
3834 this.options.put(compilerOptions, CompilerOptions.IGNORE);
3835 }
3836 } else {
3837 switch(severity) {
3838 case ProblemSeverities.Error :
3839 String currentValue = this.options.get(compilerOptions);
3840 if (CompilerOptions.ERROR.equals(currentValue)) {
3841 this.options.put(compilerOptions, CompilerOptions.IGNORE);
3842 }
3843 break;
3844 case ProblemSeverities.Warning :
3845 currentValue = this.options.get(compilerOptions);
3846 if (CompilerOptions.WARNING.equals(currentValue)) {
3847 this.options.put(compilerOptions, CompilerOptions.IGNORE);
3848 }
3849 break;
3850 case ProblemSeverities.Info :
3851 currentValue = this.options.get(compilerOptions);
3852 if (CompilerOptions.INFO.equals(currentValue)) {
3853 this.options.put(compilerOptions, CompilerOptions.IGNORE);
3854 }
3855 break;
3856 default:
3857 this.options.put(compilerOptions, CompilerOptions.IGNORE);
3858 }
3859 }
3860 }
3861 private void handleErrorOrWarningToken(String token, boolean isEnabling, int severity) {
3862 if (token.length() == 0) return;
3863 switch(token.charAt(0)) {
3864 case 'a' :
3865 if (token.equals("allDeprecation")) { //$NON-NLS-1$
3866 setSeverity(CompilerOptions.OPTION_ReportDeprecation, severity, isEnabling);
3867 setSeverity(CompilerOptions.OPTION_ReportTerminalDeprecation, severity, isEnabling);
3868 this.options.put(
3869 CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
3870 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3871 this.options.put(
3872 CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
3873 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3874 return;
3875 } else if (token.equals("allJavadoc")) { //$NON-NLS-1$
3876 this.warnAllJavadocOn = this.warnJavadocOn = isEnabling;
3877 setSeverity(CompilerOptions.OPTION_ReportInvalidJavadoc, severity, isEnabling);
3878 setSeverity(CompilerOptions.OPTION_ReportMissingJavadocTags, severity, isEnabling);
3879 setSeverity(CompilerOptions.OPTION_ReportMissingJavadocComments, severity, isEnabling);
3880 return;
3881 } else if (token.equals("assertIdentifier")) { //$NON-NLS-1$
3882 setSeverity(CompilerOptions.OPTION_ReportAssertIdentifier, severity, isEnabling);
3883 return;
3884 } else if (token.equals("allDeadCode")) { //$NON-NLS-1$
3885 setSeverity(CompilerOptions.OPTION_ReportDeadCode, severity, isEnabling);
3886 this.options.put(
3887 CompilerOptions.OPTION_ReportDeadCodeInTrivialIfStatement,
3888 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3889 return;
3890 } else if (token.equals("allOver-ann")) { //$NON-NLS-1$
3891 setSeverity(CompilerOptions.OPTION_ReportMissingOverrideAnnotation, severity, isEnabling);
3892 this.options.put(
3893 CompilerOptions.OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation,
3894 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3895 return;
3896 } else if (token.equals("all-static-method")) { //$NON-NLS-1$
3897 setSeverity(CompilerOptions.OPTION_ReportMethodCanBeStatic, severity, isEnabling);
3898 setSeverity(CompilerOptions.OPTION_ReportMethodCanBePotentiallyStatic, severity, isEnabling);
3899 return;
3900 } else if (token.equals("all")) { //$NON-NLS-1$
3901 if (isEnabling) {
3902 enableAll(severity);
3903 } else {
3904 disableAll(severity);
3905 }
3906 return;
3907 }
3908 break;
3909 case 'b' :
3910 if (token.equals("boxing")) { //$NON-NLS-1$
3911 setSeverity(CompilerOptions.OPTION_ReportAutoboxing, severity, isEnabling);
3912 return;
3913 }
3914 break;
3915 case 'c' :
3916 if (token.equals("constructorName")) { //$NON-NLS-1$
3917 setSeverity(CompilerOptions.OPTION_ReportMethodWithConstructorName, severity, isEnabling);
3918 return;
3919 } else if (token.equals("conditionAssign")) { //$NON-NLS-1$
3920 setSeverity(CompilerOptions.OPTION_ReportPossibleAccidentalBooleanAssignment, severity, isEnabling);
3921 return;
3922 } else if (token.equals("compareIdentical")) { //$NON-NLS-1$
3923 setSeverity(CompilerOptions.OPTION_ReportComparingIdentical, severity, isEnabling);
3924 return;
3925 } else if (token.equals("charConcat") /*|| token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$
3926 setSeverity(CompilerOptions.OPTION_ReportNoImplicitStringConversion, severity, isEnabling);
3927 return;
3928 }
3929 break;
3930 case 'd' :
3931 if (token.equals("deprecation")) { //$NON-NLS-1$
3932 setSeverity(CompilerOptions.OPTION_ReportDeprecation, severity, isEnabling);
3933 this.options.put(
3934 CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
3935 CompilerOptions.DISABLED);
3936 this.options.put(
3937 CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
3938 CompilerOptions.DISABLED);
3939 return;
3940 } else if (token.equals("dep-ann")) { //$NON-NLS-1$
3941 setSeverity(CompilerOptions.OPTION_ReportMissingDeprecatedAnnotation, severity, isEnabling);
3942 return;
3943 } else if (token.equals("discouraged")) { //$NON-NLS-1$
3944 setSeverity(CompilerOptions.OPTION_ReportDiscouragedReference, severity, isEnabling);
3945 return;
3946 } else if (token.equals("deadCode")) { //$NON-NLS-1$
3947 setSeverity(CompilerOptions.OPTION_ReportDeadCode, severity, isEnabling);
3948 this.options.put(
3949 CompilerOptions.OPTION_ReportDeadCodeInTrivialIfStatement,
3950 CompilerOptions.DISABLED);
3951 return;
3952 }
3953 break;
3954 case 'e' :
3955 if (token.equals("enumSwitch")) { //$NON-NLS-1$
3956 setSeverity(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, severity, isEnabling);
3957 return;
3958 } else if (token.equals("enumSwitchPedantic")) { //$NON-NLS-1$
3959 if (isEnabling) {
3960 switch (severity) {
3961 case ProblemSeverities.Error:
3962 setSeverity(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, severity, isEnabling);
3963 break;
3964 case ProblemSeverities.Warning:
3965 if (CompilerOptions.IGNORE.equals(this.options.get(CompilerOptions.OPTION_ReportIncompleteEnumSwitch))) {
3966 setSeverity(CompilerOptions.OPTION_ReportIncompleteEnumSwitch, severity, isEnabling);
3967 }
3968 break;
3969 default: // no severity update
3970 }
3971 }
3972 this.options.put(CompilerOptions.OPTION_ReportMissingEnumCaseDespiteDefault,
3973 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
3974 return;
3975 } else if (token.equals("emptyBlock")) {//$NON-NLS-1$
3976 setSeverity(CompilerOptions.OPTION_ReportUndocumentedEmptyBlock, severity, isEnabling);
3977 return;
3978 } else if (token.equals("enumIdentifier")) { //$NON-NLS-1$
3979 setSeverity(CompilerOptions.OPTION_ReportEnumIdentifier, severity, isEnabling);
3980 return;
3981 } else if (token.equals("exports")) { //$NON-NLS-1$
3982 setSeverity(CompilerOptions.OPTION_ReportAPILeak, severity, isEnabling);
3983 return;
3984 }
3985 break;
3986 case 'f' :
3987 if (token.equals("fieldHiding")) { //$NON-NLS-1$
3988 setSeverity(CompilerOptions.OPTION_ReportFieldHiding, severity, isEnabling);
3989 return;
3990 } else if (token.equals("finalBound")) {//$NON-NLS-1$
3991 setSeverity(CompilerOptions.OPTION_ReportFinalParameterBound, severity, isEnabling);
3992 return;
3993 } else if (token.equals("finally")) { //$NON-NLS-1$
3994 setSeverity(CompilerOptions.OPTION_ReportFinallyBlockNotCompletingNormally, severity, isEnabling);
3995 return;
3996 } else if (token.equals("forbidden")) { //$NON-NLS-1$
3997 setSeverity(CompilerOptions.OPTION_ReportForbiddenReference, severity, isEnabling);
3998 return;
3999 } else if (token.equals("fallthrough")) { //$NON-NLS-1$
4000 setSeverity(CompilerOptions.OPTION_ReportFallthroughCase, severity, isEnabling);
4001 return;
4002 }
4003 break;
4004 case 'h' :
4005 if (token.equals("hiding")) { //$NON-NLS-1$
4006 setSeverity(CompilerOptions.OPTION_ReportHiddenCatchBlock, severity, isEnabling);
4007 setSeverity(CompilerOptions.OPTION_ReportLocalVariableHiding, severity, isEnabling);
4008 setSeverity(CompilerOptions.OPTION_ReportFieldHiding, severity, isEnabling);
4009 setSeverity(CompilerOptions.OPTION_ReportTypeParameterHiding, severity, isEnabling);
4010 return;
4011 } else if (token.equals("hashCode")) { //$NON-NLS-1$
4012 setSeverity(CompilerOptions.OPTION_ReportMissingHashCodeMethod, severity, isEnabling);
4013 return;
4014 }
4015 break;
4016 case 'i' :
4017 if (token.equals("indirectStatic")) { //$NON-NLS-1$
4018 setSeverity(CompilerOptions.OPTION_ReportIndirectStaticAccess, severity, isEnabling);
4019 return;
4020 } else if (token.equals("inheritNullAnnot")) { //$NON-NLS-1$
4021 this.options.put(
4022 CompilerOptions.OPTION_InheritNullAnnotations,
4023 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4024 return;
4025 } else if (token.equals("intfNonInherited") || token.equals("interfaceNonInherited")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
4026 setSeverity(CompilerOptions.OPTION_ReportIncompatibleNonInheritedInterfaceMethod, severity, isEnabling);
4027 return;
4028 } else if (token.equals("intfAnnotation")) { //$NON-NLS-1$
4029 setSeverity(CompilerOptions.OPTION_ReportAnnotationSuperInterface, severity, isEnabling);
4030 return;
4031 } else if (token.equals("intfRedundant") /*|| token.equals("redundantSuperinterface")*/) { //$NON-NLS-1$
4032 setSeverity(CompilerOptions.OPTION_ReportRedundantSuperinterface, severity, isEnabling);
4033 return;
4034 } else if (token.equals("includeAssertNull")) { //$NON-NLS-1$
4035 this.options.put(
4036 CompilerOptions.OPTION_IncludeNullInfoFromAsserts,
4037 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4038 return;
4039 } else if (token.equals("invalidJavadoc")) { //$NON-NLS-1$
4040 setSeverity(CompilerOptions.OPTION_ReportInvalidJavadoc, severity, isEnabling);
4041 this.options.put(
4042 CompilerOptions.OPTION_ReportInvalidJavadocTags,
4043 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4044 this.options.put(
4045 CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
4046 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4047 this.options.put(
4048 CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
4049 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4050 if (isEnabling) {
4051 this.options.put(
4052 CompilerOptions.OPTION_DocCommentSupport,
4053 CompilerOptions.ENABLED);
4054 this.options.put(
4055 CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
4056 CompilerOptions.PRIVATE);
4057 }
4058 return;
4059 } else if (token.equals("invalidJavadocTag")) { //$NON-NLS-1$
4060 this.options.put(
4061 CompilerOptions.OPTION_ReportInvalidJavadocTags,
4062 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4063 return;
4064 } else if (token.equals("invalidJavadocTagDep")) { //$NON-NLS-1$
4065 this.options.put(
4066 CompilerOptions.OPTION_ReportInvalidJavadocTagsDeprecatedRef,
4067 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4068 return;
4069 } else if (token.equals("invalidJavadocTagNotVisible")) { //$NON-NLS-1$
4070 this.options.put(
4071 CompilerOptions.OPTION_ReportInvalidJavadocTagsNotVisibleRef,
4072 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4073 return;
4074 } else if (token.startsWith("invalidJavadocTagVisibility")) { //$NON-NLS-1$
4075 int start = token.indexOf('(');
4076 int end = token.indexOf(')');
4077 String visibility = null;
4078 if (isEnabling && start >= 0 && end >= 0 && start < end){
4079 visibility = token.substring(start+1, end).trim();
4080 }
4081 if (visibility != null && visibility.equals(CompilerOptions.PUBLIC)
4082 || visibility.equals(CompilerOptions.PRIVATE)
4083 || visibility.equals(CompilerOptions.PROTECTED)
4084 || visibility.equals(CompilerOptions.DEFAULT)) {
4085 this.options.put(
4086 CompilerOptions.OPTION_ReportInvalidJavadocTagsVisibility,
4087 visibility);
4088 return;
4089 } else {
4090 throw new IllegalArgumentException(this.bind("configure.invalidJavadocTagVisibility", token)); //$NON-NLS-1$
4091 }
4092 }
4093 break;
4094 case 'j' :
4095 if (token.equals("javadoc")) {//$NON-NLS-1$
4096 this.warnJavadocOn = isEnabling;
4097 setSeverity(CompilerOptions.OPTION_ReportInvalidJavadoc, severity, isEnabling);
4098 setSeverity(CompilerOptions.OPTION_ReportMissingJavadocTags, severity, isEnabling);
4099 return;
4100 }
4101 break;
4102 case 'l' :
4103 if (token.equals("localHiding")) { //$NON-NLS-1$
4104 setSeverity(CompilerOptions.OPTION_ReportLocalVariableHiding, severity, isEnabling);
4105 return;
4106 }
4107 break;
4108 case 'm' :
4109 if (token.equals("maskedCatchBlock") || token.equals("maskedCatchBlocks")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
4110 setSeverity(CompilerOptions.OPTION_ReportHiddenCatchBlock, severity, isEnabling);
4111 return;
4112 } else if (token.equals("missingJavadocTags")) { //$NON-NLS-1$
4113 setSeverity(CompilerOptions.OPTION_ReportMissingJavadocTags, severity, isEnabling);
4114 this.options.put(
4115 CompilerOptions.OPTION_ReportMissingJavadocTagsOverriding,
4116 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4117 this.options.put(
4118 CompilerOptions.OPTION_ReportMissingJavadocTagsMethodTypeParameters,
4119 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4120 if (isEnabling) {
4121 this.options.put(
4122 CompilerOptions.OPTION_DocCommentSupport,
4123 CompilerOptions.ENABLED);
4124 this.options.put(
4125 CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
4126 CompilerOptions.PRIVATE);
4127 }
4128 return;
4129 } else if (token.equals("missingJavadocTagsOverriding")) { //$NON-NLS-1$
4130 this.options.put(
4131 CompilerOptions.OPTION_ReportMissingJavadocTagsOverriding,
4132 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4133 return;
4134 } else if (token.equals("missingJavadocTagsMethod")) { //$NON-NLS-1$
4135 this.options.put(
4136 CompilerOptions.OPTION_ReportMissingJavadocTagsMethodTypeParameters,
4137 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4138 return;
4139 } else if (token.startsWith("missingJavadocTagsVisibility")) { //$NON-NLS-1$
4140 int start = token.indexOf('(');
4141 int end = token.indexOf(')');
4142 String visibility = null;
4143 if (isEnabling && start >= 0 && end >= 0 && start < end){
4144 visibility = token.substring(start+1, end).trim();
4145 }
4146 if (visibility != null && visibility.equals(CompilerOptions.PUBLIC)
4147 || visibility.equals(CompilerOptions.PRIVATE)
4148 || visibility.equals(CompilerOptions.PROTECTED)
4149 || visibility.equals(CompilerOptions.DEFAULT)) {
4150 this.options.put(
4151 CompilerOptions.OPTION_ReportMissingJavadocTagsVisibility,
4152 visibility);
4153 return;
4154 } else {
4155 throw new IllegalArgumentException(this.bind("configure.missingJavadocTagsVisibility", token)); //$NON-NLS-1$
4156 }
4157 } else if (token.equals("missingJavadocComments")) { //$NON-NLS-1$
4158 setSeverity(CompilerOptions.OPTION_ReportMissingJavadocComments, severity, isEnabling);
4159 this.options.put(
4160 CompilerOptions.OPTION_ReportMissingJavadocCommentsOverriding,
4161 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4162 if (isEnabling) {
4163 this.options.put(
4164 CompilerOptions.OPTION_DocCommentSupport,
4165 CompilerOptions.ENABLED);
4166 this.options.put(
4167 CompilerOptions.OPTION_ReportMissingJavadocCommentsVisibility,
4168 CompilerOptions.PRIVATE);
4169 }
4170 return;
4171 } else if (token.equals("missingJavadocCommentsOverriding")) { //$NON-NLS-1$
4172 setSeverity(CompilerOptions.OPTION_ReportMissingJavadocComments, severity, isEnabling);
4173 this.options.put(
4174 CompilerOptions.OPTION_ReportMissingJavadocCommentsOverriding,
4175 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4176 return;
4177 } else if (token.startsWith("missingJavadocCommentsVisibility")) { //$NON-NLS-1$
4178 int start = token.indexOf('(');
4179 int end = token.indexOf(')');
4180 String visibility = null;
4181 if (isEnabling && start >= 0 && end >= 0 && start < end){
4182 visibility = token.substring(start+1, end).trim();
4183 }
4184 if (visibility != null && visibility.equals(CompilerOptions.PUBLIC)
4185 || visibility.equals(CompilerOptions.PRIVATE)
4186 || visibility.equals(CompilerOptions.PROTECTED)
4187 || visibility.equals(CompilerOptions.DEFAULT)) {
4188 this.options.put(
4189 CompilerOptions.OPTION_ReportMissingJavadocCommentsVisibility,
4190 visibility);
4191 return;
4192 } else {
4193 throw new IllegalArgumentException(this.bind("configure.missingJavadocCommentsVisibility", token)); //$NON-NLS-1$
4194 }
4195 } else if (token.equals("module")) { //$NON-NLS-1$
4196 setSeverity(CompilerOptions.OPTION_ReportUnstableAutoModuleName, severity, isEnabling);
4197 return;
4198 }
4199 break;
4200 case 'n' :
4201 if (token.equals("nls")) { //$NON-NLS-1$
4202 setSeverity(CompilerOptions.OPTION_ReportNonExternalizedStringLiteral, severity, isEnabling);
4203 return;
4204 } else if (token.equals("noEffectAssign")) { //$NON-NLS-1$
4205 setSeverity(CompilerOptions.OPTION_ReportNoEffectAssignment, severity, isEnabling);
4206 return;
4207 } else if (/*token.equals("charConcat") ||*/ token.equals("noImplicitStringConversion")/*backward compatible*/) {//$NON-NLS-1$
4208 setSeverity(CompilerOptions.OPTION_ReportNoImplicitStringConversion, severity, isEnabling);
4209 return;
4210 } else if (token.equals("null")) { //$NON-NLS-1$
4211 setSeverity(CompilerOptions.OPTION_ReportNullReference, severity, isEnabling);
4212 setSeverity(CompilerOptions.OPTION_ReportPotentialNullReference, severity, isEnabling);
4213 setSeverity(CompilerOptions.OPTION_ReportRedundantNullCheck, severity, isEnabling);
4214 return;
4215 } else if (token.equals("nullDereference")) { //$NON-NLS-1$
4216 setSeverity(CompilerOptions.OPTION_ReportNullReference, severity, isEnabling);
4217 if (!isEnabling) {
4218 setSeverity(CompilerOptions.OPTION_ReportPotentialNullReference, ProblemSeverities.Ignore, isEnabling);
4219 setSeverity(CompilerOptions.OPTION_ReportRedundantNullCheck, ProblemSeverities.Ignore, isEnabling);
4220 }
4221 return;
4222 }else if (token.equals("nullAnnotConflict")) { //$NON-NLS-1$
4223 setSeverity(CompilerOptions.OPTION_ReportNullAnnotationInferenceConflict, severity, isEnabling);
4224 return;
4225 } else if (token.equals("nullAnnotRedundant")) { //$NON-NLS-1$
4226 setSeverity(CompilerOptions.OPTION_ReportRedundantNullAnnotation, severity, isEnabling);
4227 return;
4228 } else if (token.startsWith("nullAnnot")) { //$NON-NLS-1$
4229 String annotationNames = Util.EMPTY_STRING;
4230 int start = token.indexOf('(');
4231 int end = token.indexOf(')');
4232 String nonNullAnnotName = null, nullableAnnotName = null, nonNullByDefaultAnnotName = null;
4233 if (isEnabling && start >= 0 && end >= 0 && start < end){
4234 boolean isPrimarySet = !this.primaryNullAnnotationsSeen;
4235 annotationNames = token.substring(start+1, end).trim();
4236 int separator1 = annotationNames.indexOf('|');
4237 if (separator1 == -1) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
4238 nullableAnnotName = annotationNames.substring(0, separator1).trim();
4239 if (isPrimarySet && nullableAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
4240 int separator2 = annotationNames.indexOf('|', separator1 + 1);
4241 if (separator2 == -1) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
4242 nonNullAnnotName = annotationNames.substring(separator1 + 1, separator2).trim();
4243 if (isPrimarySet && nonNullAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
4244 nonNullByDefaultAnnotName = annotationNames.substring(separator2 + 1).trim();
4245 if (isPrimarySet && nonNullByDefaultAnnotName.length() == 0) throw new IllegalArgumentException(this.bind("configure.invalidNullAnnot", token)); //$NON-NLS-1$
4246 if (isPrimarySet) {
4247 this.primaryNullAnnotationsSeen = true;
4248 this.options.put(CompilerOptions.OPTION_NullableAnnotationName, nullableAnnotName);
4249 this.options.put(CompilerOptions.OPTION_NonNullAnnotationName, nonNullAnnotName);
4250 this.options.put(CompilerOptions.OPTION_NonNullByDefaultAnnotationName, nonNullByDefaultAnnotName);
4251 } else {
4252 if (nullableAnnotName.length() > 0) {
4253 String nullableList = this.options.get(CompilerOptions.OPTION_NullableAnnotationSecondaryNames);
4254 nullableList = nullableList.isEmpty() ? nullableAnnotName : nullableList + ',' + nullableAnnotName;
4255 this.options.put(CompilerOptions.OPTION_NullableAnnotationSecondaryNames, nullableList);
4256 }
4257 if (nonNullAnnotName.length() > 0) {
4258 String nonnullList = this.options.get(CompilerOptions.OPTION_NonNullAnnotationSecondaryNames);
4259 nonnullList = nonnullList.isEmpty() ? nonNullAnnotName : nonnullList + ',' + nonNullAnnotName;
4260 this.options.put(CompilerOptions.OPTION_NonNullAnnotationSecondaryNames, nonnullList);
4261 }
4262 if (nonNullByDefaultAnnotName.length() > 0) {
4263 String nnbdList = this.options.get(CompilerOptions.OPTION_NonNullByDefaultAnnotationSecondaryNames);
4264 nnbdList = nnbdList.isEmpty() ? nonNullByDefaultAnnotName : nnbdList + ',' + nonNullByDefaultAnnotName;
4265 this.options.put(CompilerOptions.OPTION_NonNullByDefaultAnnotationSecondaryNames, nnbdList);
4266 }
4267 }
4268 }
4269 this.options.put(
4270 CompilerOptions.OPTION_AnnotationBasedNullAnalysis,
4271 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4272 setSeverity(CompilerOptions.OPTION_ReportNullSpecViolation, severity, isEnabling);
4273 setSeverity(CompilerOptions.OPTION_ReportNullAnnotationInferenceConflict, severity, isEnabling);
4274 setSeverity(CompilerOptions.OPTION_ReportNullUncheckedConversion, severity, isEnabling);
4275 setSeverity(CompilerOptions.OPTION_ReportRedundantNullAnnotation, severity, isEnabling);
4276 return;
4277 } else if (token.equals("nullUncheckedConversion")) { //$NON-NLS-1$
4278 setSeverity(CompilerOptions.OPTION_ReportNullUncheckedConversion, severity, isEnabling);
4279 return;
4280 } else if (token.equals("nonnullNotRepeated")) { //$NON-NLS-1$
4281 setSeverity(CompilerOptions.OPTION_ReportNonnullParameterAnnotationDropped, severity, isEnabling);
4282 return;
4283 }
4284
4285 break;
4286 case 'o' :
4287 if (token.equals("over-sync") /*|| token.equals("syncOverride")*/) { //$NON-NLS-1$
4288 setSeverity(CompilerOptions.OPTION_ReportMissingSynchronizedOnInheritedMethod, severity, isEnabling);
4289 return;
4290 } else if (token.equals("over-ann")) { //$NON-NLS-1$
4291 setSeverity(CompilerOptions.OPTION_ReportMissingOverrideAnnotation, severity, isEnabling);
4292 this.options.put(
4293 CompilerOptions.OPTION_ReportMissingOverrideAnnotationForInterfaceMethodImplementation,
4294 CompilerOptions.DISABLED);
4295 return;
4296 }
4297 break;
4298 case 'p' :
4299 if (token.equals("pkgDefaultMethod") || token.equals("packageDefaultMethod")/*backward compatible*/ ) { //$NON-NLS-1$ //$NON-NLS-2$
4300 setSeverity(CompilerOptions.OPTION_ReportOverridingPackageDefaultMethod, severity, isEnabling);
4301 return;
4302 } else if (token.equals("paramAssign")) { //$NON-NLS-1$
4303 setSeverity(CompilerOptions.OPTION_ReportParameterAssignment, severity, isEnabling);
4304 return;
4305 }
4306 break;
4307 case 'r' :
4308 if (token.equals("raw")) {//$NON-NLS-1$
4309 setSeverity(CompilerOptions.OPTION_ReportRawTypeReference, severity, isEnabling);
4310 return;
4311 } else if (/*token.equals("intfRedundant") ||*/ token.equals("redundantSuperinterface")) { //$NON-NLS-1$
4312 setSeverity(CompilerOptions.OPTION_ReportRedundantSuperinterface, severity, isEnabling);
4313 return;
4314 } else if (token.equals("resource")) { //$NON-NLS-1$
4315 setSeverity(CompilerOptions.OPTION_ReportUnclosedCloseable, severity, isEnabling);
4316 setSeverity(CompilerOptions.OPTION_ReportPotentiallyUnclosedCloseable, severity, isEnabling);
4317 setSeverity(CompilerOptions.OPTION_ReportExplicitlyClosedAutoCloseable, severity, isEnabling);
4318 return;
4319 } else if (token.equals("removal")) { //$NON-NLS-1$
4320 setSeverity(CompilerOptions.OPTION_ReportTerminalDeprecation, severity, isEnabling);
4321 this.options.put(
4322 CompilerOptions.OPTION_ReportDeprecationInDeprecatedCode,
4323 CompilerOptions.DISABLED);
4324 this.options.put(
4325 CompilerOptions.OPTION_ReportDeprecationWhenOverridingDeprecatedMethod,
4326 CompilerOptions.DISABLED);
4327 return;
4328 }
4329 break;
4330 case 's' :
4331 if (token.equals("specialParamHiding")) { //$NON-NLS-1$
4332 this.options.put(
4333 CompilerOptions.OPTION_ReportSpecialParameterHidingField,
4334 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4335 return;
4336 } else if (token.equals("syntheticAccess") || token.equals("synthetic-access")) { //$NON-NLS-1$ //$NON-NLS-2$
4337 setSeverity(CompilerOptions.OPTION_ReportSyntheticAccessEmulation, severity, isEnabling);
4338 return;
4339 } else if (token.equals("staticReceiver")) { //$NON-NLS-1$
4340 setSeverity(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, severity, isEnabling);
4341 return;
4342 } else if (/*token.equals("over-sync") ||*/ token.equals("syncOverride")) { //$NON-NLS-1$
4343 setSeverity(CompilerOptions.OPTION_ReportMissingSynchronizedOnInheritedMethod, severity, isEnabling);
4344 return;
4345 } else if (token.equals("semicolon")) {//$NON-NLS-1$
4346 setSeverity(CompilerOptions.OPTION_ReportEmptyStatement, severity, isEnabling);
4347 return;
4348 } else if (token.equals("serial")) {//$NON-NLS-1$
4349 setSeverity(CompilerOptions.OPTION_ReportMissingSerialVersion, severity, isEnabling);
4350 return;
4351 } else if (token.equals("suppress")) {//$NON-NLS-1$
4352 switch(severity) {
4353 case ProblemSeverities.Warning :
4354 this.options.put(
4355 CompilerOptions.OPTION_SuppressWarnings,
4356 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4357 this.options.put(
4358 CompilerOptions.OPTION_SuppressOptionalErrors,
4359 CompilerOptions.DISABLED);
4360 break;
4361 case ProblemSeverities.Error :
4362 this.options.put(
4363 CompilerOptions.OPTION_SuppressWarnings,
4364 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4365 this.options.put(
4366 CompilerOptions.OPTION_SuppressOptionalErrors,
4367 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4368 }
4369 return;
4370 } else if (token.equals("static-access")) { //$NON-NLS-1$
4371 setSeverity(CompilerOptions.OPTION_ReportNonStaticAccessToStatic, severity, isEnabling);
4372 setSeverity(CompilerOptions.OPTION_ReportIndirectStaticAccess, severity, isEnabling);
4373 return;
4374 } else if (token.equals("super")) { //$NON-NLS-1$
4375 setSeverity(CompilerOptions.OPTION_ReportOverridingMethodWithoutSuperInvocation, severity, isEnabling);
4376 return;
4377 } else if (token.equals("static-method")) { //$NON-NLS-1$
4378 setSeverity(CompilerOptions.OPTION_ReportMethodCanBeStatic, severity, isEnabling);
4379 return;
4380 } else if (token.equals("switchDefault")) { //$NON-NLS-1$
4381 setSeverity(CompilerOptions.OPTION_ReportMissingDefaultCase, severity, isEnabling);
4382 return;
4383 } else if (token.equals("syntacticAnalysis")) { //$NON-NLS-1$
4384 this.options.put(
4385 CompilerOptions.OPTION_SyntacticNullAnalysisForFields,
4386 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4387 return;
4388 }
4389 break;
4390 case 't' :
4391 if (token.startsWith("tasks")) { //$NON-NLS-1$
4392 String taskTags = Util.EMPTY_STRING;
4393 int start = token.indexOf('(');
4394 int end = token.indexOf(')');
4395 if (start >= 0 && end >= 0 && start < end){
4396 taskTags = token.substring(start+1, end).trim();
4397 taskTags = taskTags.replace('|',',');
4398 }
4399 if (taskTags.length() == 0){
4400 throw new IllegalArgumentException(this.bind("configure.invalidTaskTag", token)); //$NON-NLS-1$
4401 }
4402 this.options.put(
4403 CompilerOptions.OPTION_TaskTags,
4404 isEnabling ? taskTags : Util.EMPTY_STRING);
4405
4406 setSeverity(CompilerOptions.OPTION_ReportTasks, severity, isEnabling);
4407 return;
4408 } else if (token.equals("typeHiding")) { //$NON-NLS-1$
4409 setSeverity(CompilerOptions.OPTION_ReportTypeParameterHiding, severity, isEnabling);
4410 return;
4411 }
4412 break;
4413 case 'u' :
4414 if (token.equals("unusedLocal") || token.equals("unusedLocals")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
4415 setSeverity(CompilerOptions.OPTION_ReportUnusedLocal, severity, isEnabling);
4416 return;
4417 } else if (token.equals("unusedArgument") || token.equals("unusedArguments")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
4418 setSeverity(CompilerOptions.OPTION_ReportUnusedParameter, severity, isEnabling);
4419 return;
4420 } else if (token.equals("unusedExceptionParam")) { //$NON-NLS-1$
4421 setSeverity(CompilerOptions.OPTION_ReportUnusedExceptionParameter, severity, isEnabling);
4422 return;
4423 } else if (token.equals("unusedImport") || token.equals("unusedImports")/*backward compatible*/) { //$NON-NLS-1$ //$NON-NLS-2$
4424 setSeverity(CompilerOptions.OPTION_ReportUnusedImport, severity, isEnabling);
4425 return;
4426 } else if (token.equals("unusedAllocation")) { //$NON-NLS-1$
4427 setSeverity(CompilerOptions.OPTION_ReportUnusedObjectAllocation, severity, isEnabling);
4428 return;
4429 } else if (token.equals("unusedPrivate")) { //$NON-NLS-1$
4430 setSeverity(CompilerOptions.OPTION_ReportUnusedPrivateMember, severity, isEnabling);
4431 return;
4432 } else if (token.equals("unusedLabel")) { //$NON-NLS-1$
4433 setSeverity(CompilerOptions.OPTION_ReportUnusedLabel, severity, isEnabling);
4434 return;
4435 } else if (token.equals("uselessTypeCheck")) {//$NON-NLS-1$
4436 setSeverity(CompilerOptions.OPTION_ReportUnnecessaryTypeCheck, severity, isEnabling);
4437 return;
4438 } else if (token.equals("unchecked") || token.equals("unsafe")) {//$NON-NLS-1$ //$NON-NLS-2$
4439 setSeverity(CompilerOptions.OPTION_ReportUncheckedTypeOperation, severity, isEnabling);
4440 return;
4441 } else if (token.equals("unlikelyCollectionMethodArgumentType")) { //$NON-NLS-1$
4442 setSeverity(CompilerOptions.OPTION_ReportUnlikelyCollectionMethodArgumentType, severity, isEnabling);
4443 return;
4444 } else if (token.equals("unlikelyEqualsArgumentType")) { //$NON-NLS-1$
4445 setSeverity(CompilerOptions.OPTION_ReportUnlikelyEqualsArgumentType, severity, isEnabling);
4446 return;
4447 } else if (token.equals("unnecessaryElse")) {//$NON-NLS-1$
4448 setSeverity(CompilerOptions.OPTION_ReportUnnecessaryElse, severity, isEnabling);
4449 return;
4450 } else if (token.equals("unusedThrown")) { //$NON-NLS-1$
4451 setSeverity(CompilerOptions.OPTION_ReportUnusedDeclaredThrownException, severity, isEnabling);
4452 return;
4453 } else if (token.equals("unusedThrownWhenOverriding")) { //$NON-NLS-1$
4454 this.options.put(
4455 CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionWhenOverriding,
4456 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4457 return;
4458 } else if (token.equals("unusedThrownIncludeDocComment")) { //$NON-NLS-1$
4459 this.options.put(
4460 CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionIncludeDocCommentReference,
4461 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4462 return;
4463 } else if (token.equals("unusedThrownExemptExceptionThrowable")) { //$NON-NLS-1$
4464 this.options.put(
4465 CompilerOptions.OPTION_ReportUnusedDeclaredThrownExceptionExemptExceptionAndThrowable,
4466 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4467 return;
4468 } else if (token.equals("unqualifiedField") || token.equals("unqualified-field-access")) { //$NON-NLS-1$ //$NON-NLS-2$
4469 setSeverity(CompilerOptions.OPTION_ReportUnqualifiedFieldAccess, severity, isEnabling);
4470 return;
4471 } else if (token.equals("unused")) { //$NON-NLS-1$
4472 setSeverity(CompilerOptions.OPTION_ReportDeadCode, severity, isEnabling);
4473 setSeverity(CompilerOptions.OPTION_ReportRedundantSuperinterface, severity, isEnabling);
4474 setSeverity(CompilerOptions.OPTION_ReportRedundantSpecificationOfTypeArguments, severity, isEnabling);
4475 setSeverity(CompilerOptions.OPTION_ReportUnusedDeclaredThrownException, severity, isEnabling);
4476 setSeverity(CompilerOptions.OPTION_ReportUnusedExceptionParameter, severity, isEnabling);
4477 setSeverity(CompilerOptions.OPTION_ReportUnusedImport, severity, isEnabling);
4478 setSeverity(CompilerOptions.OPTION_ReportUnusedLabel, severity, isEnabling);
4479 setSeverity(CompilerOptions.OPTION_ReportUnusedLocal, severity, isEnabling);
4480 setSeverity(CompilerOptions.OPTION_ReportUnusedObjectAllocation, severity,isEnabling);
4481 setSeverity(CompilerOptions.OPTION_ReportUnusedParameter, severity, isEnabling);
4482 setSeverity(CompilerOptions.OPTION_ReportUnusedPrivateMember, severity, isEnabling);
4483 setSeverity(CompilerOptions.OPTION_ReportUnusedTypeArgumentsForMethodInvocation, severity, isEnabling);
4484 setSeverity(CompilerOptions.OPTION_ReportUnusedTypeParameter, severity,isEnabling);
4485 return;
4486 } else if (token.equals("unusedParam")) { //$NON-NLS-1$
4487 setSeverity(CompilerOptions.OPTION_ReportUnusedParameter, severity, isEnabling);
4488 return;
4489 } else if (token.equals("unusedTypeParameter")) { //$NON-NLS-1$
4490 setSeverity(CompilerOptions.OPTION_ReportUnusedTypeParameter, severity, isEnabling);
4491 return;
4492 } else if (token.equals("unusedParamIncludeDoc")) { //$NON-NLS-1$
4493 this.options.put(
4494 CompilerOptions.OPTION_ReportUnusedParameterIncludeDocCommentReference,
4495 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4496 return;
4497 } else if (token.equals("unusedParamOverriding")) { //$NON-NLS-1$
4498 this.options.put(
4499 CompilerOptions.OPTION_ReportUnusedParameterWhenOverridingConcrete,
4500 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4501 return;
4502 } else if (token.equals("unusedParamImplementing")) { //$NON-NLS-1$
4503 this.options.put(
4504 CompilerOptions.OPTION_ReportUnusedParameterWhenImplementingAbstract,
4505 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4506 return;
4507 } else if (token.equals("unusedTypeArgs")) { //$NON-NLS-1$
4508 setSeverity(CompilerOptions.OPTION_ReportUnusedTypeArgumentsForMethodInvocation, severity, isEnabling);
4509 setSeverity(CompilerOptions.OPTION_ReportRedundantSpecificationOfTypeArguments, severity, isEnabling);
4510 return;
4511 } else if (token.equals("unavoidableGenericProblems")) { //$NON-NLS-1$
4512 this.options.put(
4513 CompilerOptions.OPTION_ReportUnavoidableGenericTypeProblems,
4514 isEnabling ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
4515 return;
4516 }
4517 break;
4518 case 'v' :
4519 if (token.equals("varargsCast")) { //$NON-NLS-1$
4520 setSeverity(CompilerOptions.OPTION_ReportVarargsArgumentNeedCast, severity, isEnabling);
4521 return;
4522 }
4523 break;
4524 case 'w' :
4525 if (token.equals("warningToken")) {//$NON-NLS-1$
4526 setSeverity(CompilerOptions.OPTION_ReportUnhandledWarningToken, severity, isEnabling);
4527 setSeverity(CompilerOptions.OPTION_ReportUnusedWarningToken, severity, isEnabling);
4528 return;
4529 }
4530 break;
4531 }
4532 String message = null;
4533 switch(severity) {
4534 case ProblemSeverities.Info:
4535 message = this.bind("configure.invalidInfo", token); //$NON-NLS-1$
4536 break;
4537 case ProblemSeverities.Warning :
4538 message = this.bind("configure.invalidWarning", token); //$NON-NLS-1$
4539 break;
4540 case ProblemSeverities.Error :
4541 message = this.bind("configure.invalidError", token); //$NON-NLS-1$
4542 }
4543 addPendingErrors(message);
4544 }
4545 /**
4546 * @deprecated - use {@link #initialize(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead
4547 * e.g. initialize(outWriter, errWriter, systemExit, null, null)
4548 */
4549 protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit) {
4550 this.initialize(outWriter, errWriter, systemExit, null /* options */, null /* progress */);
4551 }
4552 /**
4553 * @deprecated - use {@link #initialize(PrintWriter, PrintWriter, boolean, Map, CompilationProgress)} instead
4554 * e.g. initialize(outWriter, errWriter, systemExit, customDefaultOptions, null)
4555 */
4556 protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map<String, String> customDefaultOptions) {
4557 this.initialize(outWriter, errWriter, systemExit, customDefaultOptions, null /* progress */);
4558 }
4559 protected void initialize(PrintWriter outWriter, PrintWriter errWriter, boolean systemExit, Map<String, String> customDefaultOptions, CompilationProgress compilationProgress) {
4560 this.logger = new Logger(this, outWriter, errWriter);
4561 this.proceed = true;
4562 this.out = outWriter;
4563 this.err = errWriter;
4564 this.systemExitWhenFinished = systemExit;
4565 this.options = new CompilerOptions().getMap();
4566 this.ignoreOptionalProblemsFromFolders = null;
4567
4568 this.progress = compilationProgress;
4569 if (customDefaultOptions != null) {
4570 this.didSpecifySource = customDefaultOptions.get(CompilerOptions.OPTION_Source) != null;
4571 this.didSpecifyTarget = customDefaultOptions.get(CompilerOptions.OPTION_TargetPlatform) != null;
4572 for (Iterator<Map.Entry<String, String>> iter = customDefaultOptions.entrySet().iterator(); iter.hasNext();) {
4573 Map.Entry<String, String> entry = iter.next();
4574 this.options.put(entry.getKey(), entry.getValue());
4575 }
4576 } else {
4577 this.didSpecifySource = false;
4578 this.didSpecifyTarget = false;
4579 }
4580 this.classNames = null;
4581 }
4582 protected void initializeAnnotationProcessorManager() {
4583 String className = "org.eclipse.jdt.internal.compiler.apt.dispatch.BatchAnnotationProcessorManager"; //$NON-NLS-1$
4584 try {
4585 Class<?> c = Class.forName(className);
4586 AbstractAnnotationProcessorManager annotationManager = (AbstractAnnotationProcessorManager) c.newInstance();
4587 annotationManager.configure(this, this.expandedCommandLine);
4588 annotationManager.setErr(this.err);
4589 annotationManager.setOut(this.out);
4590 this.batchCompiler.annotationProcessorManager = annotationManager;
4591 } catch (ClassNotFoundException | InstantiationException e) {
4592 this.logger.logUnavaibleAPT(className);
4593 throw new org.eclipse.jdt.internal.compiler.problem.AbortCompilation();
4594 } catch (IllegalAccessException e) {
4595 // should not happen
4596 throw new org.eclipse.jdt.internal.compiler.problem.AbortCompilation();
4597 } catch(UnsupportedClassVersionError e) {
4598 // report a warning
4599 this.logger.logIncorrectVMVersionForAnnotationProcessing();
4600 }
4601 }
4602 private static boolean isParentOf(char[] folderName, char[] fileName) {
4603 if (folderName.length >= fileName.length) {
4604 return false;
4605 }
4606 if (fileName[folderName.length] != '\\' && fileName[folderName.length] != '/') {
4607 return false;
4608 }
4609 for (int i = folderName.length - 1; i >= 0; i--) {
4610 if (folderName[i] != fileName[i]) {
4611 return false;
4612 }
4613 }
4614 return true;
4615 }
4616 // Dump classfiles onto disk for all compilation units that where successful
4617 // and do not carry a -d none spec, either directly or inherited from Main.
4618 public void outputClassFiles(CompilationResult unitResult) {
4619 if (!((unitResult == null) || (unitResult.hasErrors() && !this.proceedOnError))) {
4620 ClassFile[] classFiles = unitResult.getClassFiles();
4621 String currentDestinationPath = null;
4622 boolean generateClasspathStructure = false;
4623 CompilationUnit compilationUnit =
4624 (CompilationUnit) unitResult.compilationUnit;
4625 if (compilationUnit.destinationPath == null) {
4626 if (this.destinationPath == null) {
4627 currentDestinationPath =
4628 extractDestinationPathFromSourceFile(unitResult);
4629 } else if (this.destinationPath != NONE) {
4630 currentDestinationPath = this.destinationPath;
4631 generateClasspathStructure = true;
4632 } // else leave currentDestinationPath null
4633 } else if (compilationUnit.destinationPath != NONE) {
4634 currentDestinationPath = compilationUnit.destinationPath;
4635 generateClasspathStructure = true;
4636 } // else leave currentDestinationPath null
4637 if (currentDestinationPath != null) {
4638 for (int i = 0, fileCount = classFiles.length; i < fileCount; i++) {
4639 // retrieve the key and the corresponding classfile
4640 ClassFile classFile = classFiles[i];
4641 char[] filename = classFile.fileName();
4642 int length = filename.length;
4643 char[] relativeName = new char[length + 6];
4644 System.arraycopy(filename, 0, relativeName, 0, length);
4645 System.arraycopy(SuffixConstants.SUFFIX_class, 0, relativeName, length, 6);
4646 CharOperation.replace(relativeName, '/', File.separatorChar);
4647 String relativeStringName = new String(relativeName);
4648 try {
4649 if (this.compilerOptions.verbose)
4650 this.out.println(
4651 Messages.bind(
4652 Messages.compilation_write,
4653 new String[] {
4654 String.valueOf(this.exportedClassFilesCounter+1),
4655 relativeStringName
4656 }));
4657 Util.writeToDisk(
4658 generateClasspathStructure,
4659 currentDestinationPath,
4660 relativeStringName,
4661 classFile);
4662 this.logger.logClassFile(
4663 generateClasspathStructure,
4664 currentDestinationPath,
4665 relativeStringName);
4666 this.exportedClassFilesCounter++;
4667 } catch (IOException e) {
4668 this.logger.logNoClassFileCreated(currentDestinationPath, relativeStringName, e);
4669 }
4670 }
4671 this.batchCompiler.lookupEnvironment.releaseClassFiles(classFiles);
4672 }
4673 }
4674 }
4675 /*
4676 * Low-level API performing the actual compilation
4677 */
4678 public void performCompilation() {
4679 this.startTime = System.currentTimeMillis();
4680
4681 FileSystem environment = getLibraryAccess();
4682 try {
4683 this.compilerOptions = new CompilerOptions(this.options);
4684 this.compilerOptions.performMethodsFullRecovery = false;
4685 this.compilerOptions.performStatementsRecovery = false;
4686 this.batchCompiler =
4687 new Compiler(
4688 environment,
4689 getHandlingPolicy(),
4690 this.compilerOptions,
4691 getBatchRequestor(),
4692 getProblemFactory(),
4693 this.out,
4694 this.progress);
4695 this.batchCompiler.remainingIterations = this.maxRepetition-this.currentRepetition/*remaining iterations including this one*/;
4696 // temporary code to allow the compiler to revert to a single thread
4697 String setting = System.getProperty("jdt.compiler.useSingleThread"); //$NON-NLS-1$
4698 this.batchCompiler.useSingleThread = setting != null && setting.equals("true"); //$NON-NLS-1$
4699
4700 if (this.compilerOptions.complianceLevel >= ClassFileConstants.JDK1_6
4701 && this.compilerOptions.processAnnotations) {
4702 if (checkVMVersion(ClassFileConstants.JDK1_6)) {
4703 initializeAnnotationProcessorManager();
4704 if (this.classNames != null) {
4705 this.batchCompiler.setBinaryTypes(processClassNames(this.batchCompiler.lookupEnvironment));
4706 }
4707 } else {
4708 // report a warning
4709 this.logger.logIncorrectVMVersionForAnnotationProcessing();
4710 }
4711 if (checkVMVersion(ClassFileConstants.JDK9)) {
4712 initRootModules(this.batchCompiler.lookupEnvironment, environment);
4713 }
4714 }
4715
4716 // set the non-externally configurable options.
4717 this.compilerOptions.verbose = this.verbose;
4718 this.compilerOptions.produceReferenceInfo = this.produceRefInfo;
4719 try {
4720 this.logger.startLoggingSources();
4721 this.batchCompiler.compile(getCompilationUnits());
4722 } finally {
4723 this.logger.endLoggingSources();
4724 }
4725
4726 if (this.extraProblems != null) {
4727 loggingExtraProblems();
4728 this.extraProblems = null;
4729 }
4730 if (this.compilerStats != null) {
4731 this.compilerStats[this.currentRepetition] = this.batchCompiler.stats;
4732 }
4733 this.logger.printStats();
4734 }
4735 finally {
4736 // cleanup
4737 environment.cleanup();
4738 }
4739 }
4740 protected void loggingExtraProblems() {
4741 this.logger.loggingExtraProblems(this);
4742 }
4743 public void printUsage() {
4744 printUsage("misc.usage"); //$NON-NLS-1$
4745 }
4746 private void printUsage(String sectionID) {
4747 this.logger.logUsage(
4748 this.bind(
4749 sectionID,
4750 new String[] {
4751 System.getProperty("path.separator"), //$NON-NLS-1$
4752 this.bind("compiler.name"), //$NON-NLS-1$
4753 this.bind("compiler.version"), //$NON-NLS-1$
4754 this.bind("compiler.copyright") //$NON-NLS-1$
4755 }));
4756 this.logger.flush();
4757 }
4758 private void initRootModules(LookupEnvironment environment, FileSystem fileSystem) {
4759 Map<String, String> map = new HashMap<>();
4760 for (String m : this.rootModules) {
4761 ModuleBinding mod = environment.getModule(m.toCharArray());
4762 if (mod == null) {
4763 throw new IllegalArgumentException(this.bind("configure.invalidModuleName", m)); //$NON-NLS-1$
4764 }
4765 PackageBinding[] exports = mod.getExports();
4766 for (PackageBinding packageBinding : exports) {
4767 String qName = CharOperation.toString(packageBinding.compoundName);
4768 String existing = map.get(qName);
4769 if (existing != null) {
4770 throw new IllegalArgumentException(this.bind("configure.packageConflict", new String[] {qName, existing, m})); //$NON-NLS-1$
4771 // report an error and bail out
4772 }
4773 map.put(qName, m);
4774 }
4775 }
4776 if (this.limitedModules != null) {
4777 for (String m : this.limitedModules) {
4778 ModuleBinding mod = environment.getModule(m.toCharArray());
4779 if (mod == null) {
4780 throw new IllegalArgumentException(this.bind("configure.invalidModuleName", m)); //$NON-NLS-1$
4781 }
4782 }
4783 }
4784 environment.moduleVersion = this.moduleVersion;
4785 }
4786 private ReferenceBinding[] processClassNames(LookupEnvironment environment) {
4787 // check for .class file presence in case of apt processing
4788 int length = this.classNames.length;
4789 ReferenceBinding[] referenceBindings = new ReferenceBinding[length];
4790 ModuleBinding[] modules = new ModuleBinding[length];
4791 Set<ModuleBinding> modSet = new HashSet<>();
4792 String[] typeNames = new String[length];
4793 if (this.complianceLevel <= ClassFileConstants.JDK1_8) {
4794 typeNames = this.classNames;
4795 } else {
4796 for (int i = 0; i < length; i++) {
4797 String currentName = this.classNames[i];
4798 int idx = currentName.indexOf('/');
4799 ModuleBinding mod = null;
4800 if (idx > 0) {
4801 String m = currentName.substring(0, idx);
4802 mod = environment.getModule(m.toCharArray());
4803 if (mod == null) {
4804 throw new IllegalArgumentException(this.bind("configure.invalidModuleName", m)); //$NON-NLS-1$
4805 }
4806 modules[i] = mod;
4807 modSet.add(mod);
4808 currentName = currentName.substring(idx + 1);
4809 }
4810 typeNames[i] = currentName;
4811 }
4812 }
4813
4814 for (int i = 0; i < length; i++) {
4815 char[][] compoundName = null;
4816 String cls = typeNames[i];
4817 if (cls.indexOf('.') != -1) {
4818 // consider names with '.' as fully qualified names
4819 char[] typeName = cls.toCharArray();
4820 compoundName = CharOperation.splitOn('.', typeName);
4821 } else {
4822 compoundName = new char[][] { cls.toCharArray() };
4823 }
4824 ModuleBinding mod = modules[i];
4825 ReferenceBinding type = mod != null ? environment.getType(compoundName, mod) : environment.getType(compoundName);
4826 if (type != null && type.isValidBinding()) {
4827 if (type.isBinaryBinding()) {
4828 referenceBindings[i] = type;
4829 type.superclass();
4830 }
4831 } else {
4832 throw new IllegalArgumentException(
4833 this.bind("configure.invalidClassName", this.classNames[i]));//$NON-NLS-1$
4834 }
4835 }
4836 return referenceBindings;
4837 }
4838 private ArrayList<String> processModulePathEntries(String arg) {
4839 ArrayList<String> paths = new ArrayList<>();
4840 if (arg == null)
4841 return paths;
4842 StringTokenizer tokenizer = new StringTokenizer(arg, File.pathSeparator, false);
4843 while (tokenizer.hasMoreTokens()) {
4844 paths.add(tokenizer.nextToken());
4845 }
4846 return paths;
4847 }
4848 /*
4849 * External API
4850 */
4851 public void processPathEntries(final int defaultSize, final ArrayList<FileSystem.Classpath> paths,
4852 final String currentPath, String customEncoding, boolean isSourceOnly,
4853 boolean rejectDestinationPathOnJars) {
4854 String currentClasspathName = null;
4855 String currentDestinationPath = null;
4856 ArrayList<String> currentRuleSpecs = new ArrayList<>(defaultSize);
4857 StringTokenizer tokenizer = new StringTokenizer(currentPath,
4858 File.pathSeparator + "[]", true); //$NON-NLS-1$
4859 ArrayList<String> tokens = new ArrayList<>();
4860 while (tokenizer.hasMoreTokens()) {
4861 tokens.add(tokenizer.nextToken());
4862 }
4863 // state machine
4864 final int start = 0;
4865 final int readyToClose = 1;
4866 // 'path' 'path1[rule];path2'
4867 final int readyToCloseEndingWithRules = 2;
4868 // 'path[rule]' 'path1;path2[rule]'
4869 final int readyToCloseOrOtherEntry = 3;
4870 // 'path[rule];' 'path;' 'path1;path2;'
4871 final int rulesNeedAnotherRule = 4;
4872 // 'path[rule1;'
4873 final int rulesStart = 5;
4874 // 'path[' 'path1;path2['
4875 final int rulesReadyToClose = 6;
4876 // 'path[rule' 'path[rule1;rule2'
4877 final int destinationPathReadyToClose = 7;
4878 // 'path[-d bin'
4879 final int readyToCloseEndingWithDestinationPath = 8;
4880 // 'path[-d bin]' 'path[rule][-d bin]'
4881 final int destinationPathStart = 9;
4882 // 'path[rule]['
4883 final int bracketOpened = 10;
4884 // '.*[.*'
4885 final int bracketClosed = 11;
4886 // '.*([.*])+'
4887
4888 final int error = 99;
4889 int state = start;
4890 String token = null;
4891 int cursor = 0, tokensNb = tokens.size(), bracket = -1;
4892 while (cursor < tokensNb && state != error) {
4893 token = tokens.get(cursor++);
4894 if (token.equals(File.pathSeparator)) {
4895 switch (state) {
4896 case start:
4897 case readyToCloseOrOtherEntry:
4898 case bracketOpened:
4899 break;
4900 case readyToClose:
4901 case readyToCloseEndingWithRules:
4902 case readyToCloseEndingWithDestinationPath:
4903 state = readyToCloseOrOtherEntry;
4904 addNewEntry(paths, currentClasspathName, currentRuleSpecs,
4905 customEncoding, currentDestinationPath, isSourceOnly,
4906 rejectDestinationPathOnJars);
4907 currentRuleSpecs.clear();
4908 break;
4909 case rulesReadyToClose:
4910 state = rulesNeedAnotherRule;
4911 break;
4912 case destinationPathReadyToClose:
4913 throw new IllegalArgumentException(
4914 this.bind("configure.incorrectDestinationPathEntry", //$NON-NLS-1$
4915 currentPath));
4916 case bracketClosed:
4917 cursor = bracket + 1;
4918 state = rulesStart;
4919 break;
4920 default:
4921 state = error;
4922 }
4923 } else if (token.equals("[")) { //$NON-NLS-1$
4924 switch (state) {
4925 case start:
4926 currentClasspathName = ""; //$NON-NLS-1$
4927 //$FALL-THROUGH$
4928 case readyToClose:
4929 bracket = cursor - 1;
4930 //$FALL-THROUGH$
4931 case bracketClosed:
4932 state = bracketOpened;
4933 break;
4934 case readyToCloseEndingWithRules:
4935 state = destinationPathStart;
4936 break;
4937 case readyToCloseEndingWithDestinationPath:
4938 state = rulesStart;
4939 break;
4940 case bracketOpened:
4941 default:
4942 state = error;
4943 }
4944 } else if (token.equals("]")) { //$NON-NLS-1$
4945 switch (state) {
4946 case rulesReadyToClose:
4947 state = readyToCloseEndingWithRules;
4948 break;
4949 case destinationPathReadyToClose:
4950 state = readyToCloseEndingWithDestinationPath;
4951 break;
4952 case bracketOpened:
4953 state = bracketClosed;
4954 break;
4955 case bracketClosed:
4956 default:
4957 state = error;
4958 }
4959 } else {
4960 // regular word
4961 switch (state) {
4962 case start:
4963 case readyToCloseOrOtherEntry:
4964 state = readyToClose;
4965 currentClasspathName = token;
4966 break;
4967 case rulesStart:
4968 if (token.startsWith("-d ")) { //$NON-NLS-1$
4969 if (currentDestinationPath != null) {
4970 throw new IllegalArgumentException(
4971 this.bind("configure.duplicateDestinationPathEntry", //$NON-NLS-1$
4972 currentPath));
4973 }
4974 currentDestinationPath = token.substring(3).trim();
4975 state = destinationPathReadyToClose;
4976 break;
4977 } // else we proceed with a rule
4978 //$FALL-THROUGH$
4979 case rulesNeedAnotherRule:
4980 if (currentDestinationPath != null) {
4981 throw new IllegalArgumentException(
4982 this.bind("configure.accessRuleAfterDestinationPath", //$NON-NLS-1$
4983 currentPath));
4984 }
4985 state = rulesReadyToClose;
4986 currentRuleSpecs.add(token);
4987 break;
4988 case destinationPathStart:
4989 if (!token.startsWith("-d ")) { //$NON-NLS-1$
4990 state = error;
4991 } else {
4992 currentDestinationPath = token.substring(3).trim();
4993 state = destinationPathReadyToClose;
4994 }
4995 break;
4996 case bracketClosed:
4997 for (int i = bracket; i < cursor ; i++) {
4998 currentClasspathName += tokens.get(i);
4999 }
5000 state = readyToClose;
5001 break;
5002 case bracketOpened:
5003 break;
5004 default:
5005 state = error;
5006 }
5007 }
5008 if (state == bracketClosed && cursor == tokensNb) {
5009 cursor = bracket + 1;
5010 state = rulesStart;
5011 }
5012 }
5013 switch(state) {
5014 case readyToCloseOrOtherEntry:
5015 break;
5016 case readyToClose:
5017 case readyToCloseEndingWithRules:
5018 case readyToCloseEndingWithDestinationPath:
5019 addNewEntry(paths, currentClasspathName, currentRuleSpecs,
5020 customEncoding, currentDestinationPath, isSourceOnly,
5021 rejectDestinationPathOnJars);
5022 break;
5023 case bracketOpened:
5024 case bracketClosed:
5025 default :
5026 // we go on anyway
5027 if (currentPath.length() != 0) {
5028 addPendingErrors(this.bind("configure.incorrectClasspath", currentPath));//$NON-NLS-1$
5029 }
5030 }
5031 }
5032
5033 private int processPaths(String[] args, int index, String currentArg, ArrayList<String> paths) {
5034 int localIndex = index;
5035 int count = 0;
5036 for (int i = 0, max = currentArg.length(); i < max; i++) {
5037 switch(currentArg.charAt(i)) {
5038 case '[' :
5039 count++;
5040 break;
5041 case ']' :
5042 count--;
5043 break;
5044 }
5045 }
5046 if (count == 0) {
5047 paths.add(currentArg);
5048 } else if (count > 1) {
5049 throw new IllegalArgumentException(
5050 this.bind("configure.unexpectedBracket", //$NON-NLS-1$
5051 currentArg));
5052 } else {
5053 StringBuffer currentPath = new StringBuffer(currentArg);
5054 while (true) {
5055 if (localIndex >= args.length) {
5056 throw new IllegalArgumentException(
5057 this.bind("configure.unexpectedBracket", //$NON-NLS-1$
5058 currentArg));
5059 }
5060 localIndex++;
5061 String nextArg = args[localIndex];
5062 for (int i = 0, max = nextArg.length(); i < max; i++) {
5063 switch(nextArg.charAt(i)) {
5064 case '[' :
5065 if (count > 1) {
5066 throw new IllegalArgumentException(
5067 this.bind("configure.unexpectedBracket", //$NON-NLS-1$
5068 nextArg));
5069 }
5070 count++;
5071 break;
5072 case ']' :
5073 count--;
5074 break;
5075 }
5076 }
5077 if (count == 0) {
5078 currentPath.append(' ');
5079 currentPath.append(nextArg);
5080 paths.add(currentPath.toString());
5081 return localIndex - index;
5082 } else if (count < 0) {
5083 throw new IllegalArgumentException(
5084 this.bind("configure.unexpectedBracket", //$NON-NLS-1$
5085 nextArg));
5086 } else {
5087 currentPath.append(' ');
5088 currentPath.append(nextArg);
5089 }
5090 }
5091
5092 }
5093 return localIndex - index;
5094 }
5095 private int processPaths(String[] args, int index, String currentArg, String[] paths) {
5096 int localIndex = index;
5097 int count = 0;
5098 for (int i = 0, max = currentArg.length(); i < max; i++) {
5099 switch(currentArg.charAt(i)) {
5100 case '[' :
5101 count++;
5102 break;
5103 case ']' :
5104 count--;
5105 break;
5106 }
5107 }
5108 if (count == 0) {
5109 paths[0] = currentArg;
5110 } else {
5111 StringBuffer currentPath = new StringBuffer(currentArg);
5112 while (true) {
5113 localIndex++;
5114 if (localIndex >= args.length) {
5115 throw new IllegalArgumentException(
5116 this.bind("configure.unexpectedBracket", //$NON-NLS-1$
5117 currentArg));
5118 }
5119 String nextArg = args[localIndex];
5120 for (int i = 0, max = nextArg.length(); i < max; i++) {
5121 switch(nextArg.charAt(i)) {
5122 case '[' :
5123 if (count > 1) {
5124 throw new IllegalArgumentException(
5125 this.bind("configure.unexpectedBracket", //$NON-NLS-1$
5126 currentArg));
5127 }
5128 count++;
5129 break;
5130 case ']' :
5131 count--;
5132 break;
5133 }
5134 }
5135 if (count == 0) {
5136 currentPath.append(' ');
5137 currentPath.append(nextArg);
5138 paths[0] = currentPath.toString();
5139 return localIndex - index;
5140 } else if (count < 0) {
5141 throw new IllegalArgumentException(
5142 this.bind("configure.unexpectedBracket", //$NON-NLS-1$
5143 currentArg));
5144 } else {
5145 currentPath.append(' ');
5146 currentPath.append(nextArg);
5147 }
5148 }
5149
5150 }
5151 return localIndex - index;
5152 }
5153 /**
5154 * Creates a NLS catalog for the given locale.
5155 */
5156 public void relocalize() {
5157 relocalize(Locale.getDefault());
5158 }
5159
5160 private void relocalize(Locale locale) {
5161 this.compilerLocale = locale;
5162 try {
5163 this.bundle = ResourceBundleFactory.getBundle(locale);
5164 } catch(MissingResourceException e) {
5165 System.out.println("Missing resource : " + Main.bundleName.replace('.', '/') + ".properties for locale " + locale); //$NON-NLS-1$//$NON-NLS-2$
5166 throw e;
5167 }
5168 }
5169 /*
5170 * External API
5171 */
5172 public void setDestinationPath(String dest) {
5173 this.destinationPath = dest;
5174 }
5175 /*
5176 * External API
5177 */
5178 public void setLocale(Locale locale) {
5179 relocalize(locale);
5180 }
5181 /*
5182 * External API
5183 */
5184 protected void setPaths(ArrayList<String> bootclasspaths,
5185 String sourcepathClasspathArg,
5186 ArrayList<String> sourcepathClasspaths,
5187 ArrayList<String> classpaths,
5188 String modulePath,
5189 String moduleSourcepath,
5190 ArrayList<String> extdirsClasspaths,
5191 ArrayList<String> endorsedDirClasspaths,
5192 String customEncoding) {
5193
5194 if (this.complianceLevel == 0) {
5195 String version = this.options.get(CompilerOptions.OPTION_Compliance);
5196 this.complianceLevel = CompilerOptions.versionToJdkLevel(version);
5197 }
5198 // process bootclasspath, classpath and sourcepaths
5199 ArrayList<Classpath> allPaths = null;
5200 long jdkLevel = validateClasspathOptions(bootclasspaths, endorsedDirClasspaths, extdirsClasspaths);
5201
5202 if (this.releaseVersion != null && this.complianceLevel < jdkLevel) {
5203 // TODO: Revisit for access rules
5204 allPaths = new ArrayList<Classpath>();
5205 allPaths.add(
5206 FileSystem.getOlderSystemRelease(this.javaHomeCache.getAbsolutePath(), this.releaseVersion, null));
5207 } else {
5208 allPaths = handleBootclasspath(bootclasspaths, customEncoding);
5209 }
5210
5211 List<FileSystem.Classpath> cp = handleClasspath(classpaths, customEncoding);
5212
5213 List<FileSystem.Classpath> mp = handleModulepath(modulePath);
5214
5215 List<FileSystem.Classpath> msp = handleModuleSourcepath(moduleSourcepath);
5216
5217 ArrayList<FileSystem.Classpath> sourcepaths = new ArrayList<>();
5218 if (sourcepathClasspathArg != null) {
5219 processPathEntries(DEFAULT_SIZE_CLASSPATH, sourcepaths,
5220 sourcepathClasspathArg, customEncoding, true, false);
5221 }
5222
5223 /*
5224 * Feed endorsedDirClasspath according to:
5225 * - -extdirs first if present;
5226 * - else java.ext.dirs if defined;
5227 * - else default extensions directory for the platform.
5228 */
5229 List<FileSystem.Classpath> extdirs = handleExtdirs(extdirsClasspaths);
5230
5231 List<FileSystem.Classpath> endorsed = handleEndorseddirs(endorsedDirClasspaths);
5232
5233 /*
5234 * Concatenate classpath entries
5235 * We put the bootclasspath at the beginning of the classpath
5236 * entries, followed by the extension libraries, followed by
5237 * the sourcepath followed by the classpath. All classpath
5238 * entries are searched for both sources and binaries except
5239 * the sourcepath entries which are searched for sources only.
5240 */
5241 allPaths.addAll(0, endorsed);
5242 allPaths.addAll(extdirs);
5243 allPaths.addAll(sourcepaths);
5244 allPaths.addAll(cp);
5245 allPaths.addAll(mp);
5246 allPaths.addAll(msp);
5247 allPaths = FileSystem.ClasspathNormalizer.normalize(allPaths);
5248 this.checkedClasspaths = new FileSystem.Classpath[allPaths.size()];
5249 allPaths.toArray(this.checkedClasspaths);
5250 this.logger.logClasspath(this.checkedClasspaths);
5251
5252 if (this.annotationPaths != null && CompilerOptions.ENABLED.equals(this.options.get(CompilerOptions.OPTION_AnnotationBasedNullAnalysis))) {
5253 for (FileSystem.Classpath c : this.checkedClasspaths) {
5254 if (c instanceof ClasspathJar)
5255 ((ClasspathJar) c).annotationPaths = this.annotationPaths;
5256 else if (c instanceof ClasspathJrt)
5257 ((ClasspathJrt) c).annotationPaths = this.annotationPaths;
5258 }
5259 }
5260 }
5261 public final static boolean shouldIgnoreOptionalProblems(char[][] folderNames, char[] fileName) {
5262 if (folderNames == null || fileName == null) {
5263 return false;
5264 }
5265 for (int i = 0, max = folderNames.length; i < max; i++) {
5266 char[] folderName = folderNames[i];
5267 if (isParentOf(folderName, fileName)) {
5268 return true;
5269 }
5270 }
5271 return false;
5272 }
5273 protected long validateClasspathOptions(ArrayList<String> bootclasspaths, ArrayList<String> endorsedDirClasspaths, ArrayList<String> extdirsClasspaths) {
5274 if (this.complianceLevel > ClassFileConstants.JDK1_8) {
5275 if (bootclasspaths != null && bootclasspaths.size() > 0)
5276 throw new IllegalArgumentException(
5277 this.bind("configure.unsupportedOption", "-bootclasspath")); //$NON-NLS-1$ //$NON-NLS-2$
5278 if (extdirsClasspaths != null && extdirsClasspaths.size() > 0)
5279 throw new IllegalArgumentException(
5280 this.bind("configure.unsupportedOption", "-extdirs")); //$NON-NLS-1$ //$NON-NLS-2$
5281 if (endorsedDirClasspaths != null && endorsedDirClasspaths.size() > 0)
5282 throw new IllegalArgumentException(
5283 this.bind("configure.unsupportedOption", "-endorseddirs")); //$NON-NLS-1$ //$NON-NLS-2$
5284 }
5285 long jdkLevel = Util.getJDKLevel(getJavaHome());
5286 if (jdkLevel < ClassFileConstants.JDK9 && this.releaseVersion != null) {
5287 throw new IllegalArgumentException(
5288 this.bind("configure.unsupportedReleaseOption")); //$NON-NLS-1$
5289 }
5290 return jdkLevel;
5291 }
5292 protected void validateOptions(boolean didSpecifyCompliance) {
5293 if (didSpecifyCompliance) {
5294 String version = this.options.get(CompilerOptions.OPTION_Compliance);
5295 if (this.releaseVersion != null) {
5296 throw new IllegalArgumentException(
5297 this.bind("configure.unsupportedWithRelease", version));//$NON-NLS-1$
5298 }
5299 if (CompilerOptions.VERSION_1_3.equals(version)) {
5300 if (!this.didSpecifySource) this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
5301 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
5302 } else if (CompilerOptions.VERSION_1_4.equals(version)) {
5303 if (this.didSpecifySource) {
5304 Object source = this.options.get(CompilerOptions.OPTION_Source);
5305 if (CompilerOptions.VERSION_1_3.equals(source)) {
5306 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
5307 } else if (CompilerOptions.VERSION_1_4.equals(source)) {
5308 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5309 }
5310 } else {
5311 this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
5312 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_2);
5313 }
5314 } else if (CompilerOptions.VERSION_1_5.equals(version)) {
5315 if (this.didSpecifySource) {
5316 Object source = this.options.get(CompilerOptions.OPTION_Source);
5317 if (CompilerOptions.VERSION_1_3.equals(source)
5318 || CompilerOptions.VERSION_1_4.equals(source)) {
5319 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5320 } else if (CompilerOptions.VERSION_1_5.equals(source)) {
5321 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
5322 }
5323 } else {
5324 this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
5325 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
5326 }
5327 } else if (CompilerOptions.VERSION_1_6.equals(version)) {
5328 if (this.didSpecifySource) {
5329 Object source = this.options.get(CompilerOptions.OPTION_Source);
5330 if (CompilerOptions.VERSION_1_3.equals(source)
5331 || CompilerOptions.VERSION_1_4.equals(source)) {
5332 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5333 } else if (CompilerOptions.VERSION_1_5.equals(source)
5334 || CompilerOptions.VERSION_1_6.equals(source)) {
5335 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
5336 }
5337 } else {
5338 this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
5339 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
5340 }
5341 } else if (CompilerOptions.VERSION_1_7.equals(version)) {
5342 if (this.didSpecifySource) {
5343 Object source = this.options.get(CompilerOptions.OPTION_Source);
5344 if (CompilerOptions.VERSION_1_3.equals(source)
5345 || CompilerOptions.VERSION_1_4.equals(source)) {
5346 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5347 } else if (CompilerOptions.VERSION_1_5.equals(source)
5348 || CompilerOptions.VERSION_1_6.equals(source)) {
5349 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
5350 } else if (CompilerOptions.VERSION_1_7.equals(source)) {
5351 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
5352 }
5353 } else {
5354 this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7);
5355 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
5356 }
5357 } else if (CompilerOptions.VERSION_1_8.equals(version)) {
5358 if (this.didSpecifySource) {
5359 Object source = this.options.get(CompilerOptions.OPTION_Source);
5360 if (CompilerOptions.VERSION_1_3.equals(source)
5361 || CompilerOptions.VERSION_1_4.equals(source)) {
5362 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5363 } else if (CompilerOptions.VERSION_1_5.equals(source)
5364 || CompilerOptions.VERSION_1_6.equals(source)) {
5365 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
5366 } else if (CompilerOptions.VERSION_1_7.equals(source)) {
5367 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
5368 } else if (CompilerOptions.VERSION_1_8.equals(source)) {
5369 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
5370 }
5371 } else {
5372 this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
5373 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
5374 }
5375 } else if (CompilerOptions.VERSION_9.equals(version)) {
5376 if (this.didSpecifySource) {
5377 Object source = this.options.get(CompilerOptions.OPTION_Source);
5378 if (CompilerOptions.VERSION_1_3.equals(source)
5379 || CompilerOptions.VERSION_1_4.equals(source)) {
5380 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5381 } else if (CompilerOptions.VERSION_1_5.equals(source)
5382 || CompilerOptions.VERSION_1_6.equals(source)) {
5383 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
5384 } else if (CompilerOptions.VERSION_1_7.equals(source)) {
5385 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
5386 } else if (CompilerOptions.VERSION_1_8.equals(source)) {
5387 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
5388 } else if (CompilerOptions.VERSION_9.equals(source)) {
5389 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
5390 }
5391 } else {
5392 this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
5393 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
5394 }
5395 } else if (CompilerOptions.VERSION_10.equals(version)) {
5396 if (this.didSpecifySource) {
5397 Object source = this.options.get(CompilerOptions.OPTION_Source);
5398 if (CompilerOptions.VERSION_1_3.equals(source)
5399 || CompilerOptions.VERSION_1_4.equals(source)) {
5400 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5401 } else if (CompilerOptions.VERSION_1_5.equals(source)
5402 || CompilerOptions.VERSION_1_6.equals(source)) {
5403 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
5404 } else if (CompilerOptions.VERSION_1_7.equals(source)) {
5405 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
5406 } else if (CompilerOptions.VERSION_1_8.equals(source)) {
5407 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
5408 } else if (CompilerOptions.VERSION_9.equals(source)) {
5409 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
5410 } else if (CompilerOptions.VERSION_10.equals(source)) {
5411 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_10);
5412 }
5413 } else {
5414 this.options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_10);
5415 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_10);
5416 }
5417 } else {
5418 if (!this.didSpecifyTarget) {
5419 if (this.didSpecifySource) {
5420 String source = this.options.get(CompilerOptions.OPTION_Source);
5421 if (CompilerOptions.VERSION_1_3.equals(source)
5422 || CompilerOptions.VERSION_1_4.equals(source)) {
5423 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5424 } else if (CompilerOptions.VERSION_1_5.equals(source)
5425 || CompilerOptions.VERSION_1_6.equals(source)) {
5426 this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
5427 } else {
5428 // 1.3 is the lowest version that can be specified as -source
5429 // The following check will ensure '0' is ignored.
5430 if (CompilerOptions.versionToJdkLevel(source) >= ClassFileConstants.JDK1_7)
5431 this.options.put(CompilerOptions.OPTION_TargetPlatform, source);
5432 }
5433 } else {
5434 if (CompilerOptions.versionToJdkLevel(version) > ClassFileConstants.JDK10) {
5435 this.options.put(CompilerOptions.OPTION_Source, version);
5436 this.options.put(CompilerOptions.OPTION_TargetPlatform, version);
5437 }
5438 }
5439 }
5440 }
5441
5442 } else if (this.didSpecifySource) {
5443 String version = this.options.get(CompilerOptions.OPTION_Source);
5444 // default is source 1.3 target 1.2 and compliance 1.4
5445 if (CompilerOptions.VERSION_1_4.equals(version)) {
5446 if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
5447 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
5448 } else if (CompilerOptions.VERSION_1_5.equals(version)) {
5449 if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
5450 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
5451 } else if (CompilerOptions.VERSION_1_6.equals(version)) {
5452 if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
5453 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
5454 } else if (CompilerOptions.VERSION_1_7.equals(version)) {
5455 if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_7);
5456 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
5457 } else if (CompilerOptions.VERSION_1_8.equals(version)) {
5458 if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8);
5459 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
5460 } else if (CompilerOptions.VERSION_9.equals(version)) {
5461 if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_9);
5462 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
5463 } else if (CompilerOptions.VERSION_10.equals(version)) {
5464 if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_10);
5465 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_10);
5466 } else {
5467 if (CompilerOptions.versionToJdkLevel(version) > ClassFileConstants.JDK10) {
5468 if (!didSpecifyCompliance) this.options.put(CompilerOptions.OPTION_Compliance, version);
5469 if (!this.didSpecifyTarget) this.options.put(CompilerOptions.OPTION_TargetPlatform, version);
5470 }
5471 }
5472 }
5473
5474 final String sourceVersion = this.options.get(CompilerOptions.OPTION_Source);
5475 if (this.complianceLevel == 0) {
5476 final String compliance = this.options.get(CompilerOptions.OPTION_Compliance);
5477 this.complianceLevel = CompilerOptions.versionToJdkLevel(compliance);
5478 }
5479 if (sourceVersion.equals(CompilerOptions.VERSION_10)
5480 && this.complianceLevel < ClassFileConstants.JDK10) {
5481 // compliance must be 10 if source is 10
5482 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_10)); //$NON-NLS-1$
5483 } else if (sourceVersion.equals(CompilerOptions.VERSION_9)
5484 && this.complianceLevel < ClassFileConstants.JDK9) {
5485 // compliance must be 9 if source is 9
5486 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_9)); //$NON-NLS-1$
5487 } else if (sourceVersion.equals(CompilerOptions.VERSION_1_8)
5488 && this.complianceLevel < ClassFileConstants.JDK1_8) {
5489 // compliance must be 1.8 if source is 1.8
5490 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_8)); //$NON-NLS-1$
5491 } else if (sourceVersion.equals(CompilerOptions.VERSION_1_7)
5492 && this.complianceLevel < ClassFileConstants.JDK1_7) {
5493 // compliance must be 1.7 if source is 1.7
5494 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_7)); //$NON-NLS-1$
5495 } else if (sourceVersion.equals(CompilerOptions.VERSION_1_6)
5496 && this.complianceLevel < ClassFileConstants.JDK1_6) {
5497 // compliance must be 1.6 if source is 1.6
5498 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
5499 } else if (sourceVersion.equals(CompilerOptions.VERSION_1_5)
5500 && this.complianceLevel < ClassFileConstants.JDK1_5) {
5501 // compliance must be 1.5 if source is 1.5
5502 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
5503 } else if (sourceVersion.equals(CompilerOptions.VERSION_1_4)
5504 && this.complianceLevel < ClassFileConstants.JDK1_4) {
5505 // compliance must be 1.4 if source is 1.4
5506 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
5507 } else {
5508 long ver = CompilerOptions.versionToJdkLevel(sourceVersion);
5509 if(this.complianceLevel < ver)
5510 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForSource", this.options.get(CompilerOptions.OPTION_Compliance), sourceVersion)); //$NON-NLS-1$
5511 }
5512 if (this.enablePreview && this.complianceLevel != ClassFileConstants.getLatestJDKLevel()) {
5513 throw new IllegalArgumentException(this.bind("configure.unsupportedPreview")); //$NON-NLS-1$
5514 }
5515
5516 // check and set compliance/source/target compatibilities
5517 if (this.didSpecifyTarget) {
5518 final String targetVersion = this.options.get(CompilerOptions.OPTION_TargetPlatform);
5519 // tolerate jsr14 target
5520 if (CompilerOptions.VERSION_JSR14.equals(targetVersion)) {
5521 // expecting source >= 1.5
5522 if (CompilerOptions.versionToJdkLevel(sourceVersion) < ClassFileConstants.JDK1_5) {
5523 throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForGenericSource", targetVersion, sourceVersion)); //$NON-NLS-1$
5524 }
5525 } else if (CompilerOptions.VERSION_CLDC1_1.equals(targetVersion)) {
5526 if (this.didSpecifySource && CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4) {
5527 throw new IllegalArgumentException(this.bind("configure.incompatibleSourceForCldcTarget", targetVersion, sourceVersion)); //$NON-NLS-1$
5528 }
5529 if (this.complianceLevel >= ClassFileConstants.JDK1_5) {
5530 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForCldcTarget", targetVersion, sourceVersion)); //$NON-NLS-1$
5531 }
5532 } else {
5533 // target must be 1.8 if source is 1.8
5534 if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_8
5535 && CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_8){
5536 throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", targetVersion, CompilerOptions.VERSION_1_8)); //$NON-NLS-1$
5537 }
5538 // target must be 1.7 if source is 1.7
5539 if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_7
5540 && CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_7){
5541 throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", targetVersion, CompilerOptions.VERSION_1_7)); //$NON-NLS-1$
5542 }
5543 // target must be 1.6 if source is 1.6
5544 if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_6
5545 && CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_6){
5546 throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", targetVersion, CompilerOptions.VERSION_1_6)); //$NON-NLS-1$
5547 }
5548 // target must be 1.5 if source is 1.5
5549 if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_5
5550 && CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_5){
5551 throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", targetVersion, CompilerOptions.VERSION_1_5)); //$NON-NLS-1$
5552 }
5553 // target must be 1.4 if source is 1.4
5554 if (CompilerOptions.versionToJdkLevel(sourceVersion) >= ClassFileConstants.JDK1_4
5555 && CompilerOptions.versionToJdkLevel(targetVersion) < ClassFileConstants.JDK1_4){
5556 throw new IllegalArgumentException(this.bind("configure.incompatibleTargetForSource", targetVersion, CompilerOptions.VERSION_1_4)); //$NON-NLS-1$
5557 }
5558 // target cannot be greater than compliance level
5559 if (this.complianceLevel < CompilerOptions.versionToJdkLevel(targetVersion)){
5560 throw new IllegalArgumentException(this.bind("configure.incompatibleComplianceForTarget", this.options.get(CompilerOptions.OPTION_Compliance), targetVersion)); //$NON-NLS-1$
5561 }
5562 }
5563 }
5564 }
5565 }
5566