21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.api;
27
28 import java.io.IOException;
29 import java.nio.CharBuffer;
30 import java.util.*;
31 import java.util.concurrent.Callable;
32 import java.util.concurrent.atomic.AtomicBoolean;
33
34 import javax.annotation.processing.Processor;
35 import javax.lang.model.element.Element;
36 import javax.lang.model.element.TypeElement;
37 import javax.tools.*;
38
39 import com.sun.source.tree.*;
40 import com.sun.tools.javac.code.*;
41 import com.sun.tools.javac.code.Symbol.ClassSymbol;
42 import com.sun.tools.javac.comp.*;
43 import com.sun.tools.javac.file.BaseFileManager;
44 import com.sun.tools.javac.main.*;
45 import com.sun.tools.javac.main.JavaCompiler;
46 import com.sun.tools.javac.parser.Parser;
47 import com.sun.tools.javac.parser.ParserFactory;
48 import com.sun.tools.javac.processing.AnnotationProcessingError;
49 import com.sun.tools.javac.tree.*;
50 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
51 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
52 import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
53 import com.sun.tools.javac.tree.JCTree.Tag;
54 import com.sun.tools.javac.util.*;
55 import com.sun.tools.javac.util.DefinedBy.Api;
56 import com.sun.tools.javac.util.List;
57 import com.sun.tools.javac.util.Log.PrefixKind;
58 import com.sun.tools.javac.util.Log.WriterKind;
59
60 /**
61 * Provides access to functionality specific to the JDK Java Compiler, javac.
62 *
63 * <p><b>This is NOT part of any supported API.
64 * If you write code that depends on this, you do so at your own
65 * risk. This code and its internal interfaces are subject to change
66 * or deletion without notice.</b></p>
67 *
68 * @author Peter von der Ahé
69 * @author Jonathan Gibbons
70 */
71 public class JavacTaskImpl extends BasicJavacTask {
72 private final Arguments args;
73 private JavaCompiler compiler;
74 private JavaFileManager fileManager;
75 private Locale locale;
76 private Map<JavaFileObject, JCCompilationUnit> notYetEntered;
77 private ListBuffer<Env<AttrContext>> genList;
78 private final AtomicBoolean used = new AtomicBoolean();
79 private Iterable<? extends Processor> processors;
80 private ListBuffer<String> addModules = new ListBuffer<>();
81
82 protected JavacTaskImpl(Context context) {
83 super(context, true);
84 args = Arguments.instance(context);
85 fileManager = context.get(JavaFileManager.class);
86 }
87
88 @Override @DefinedBy(Api.COMPILER)
89 public Boolean call() {
90 return doCall().isOK();
91 }
92
93 /* Internal version of call exposing Main.Result. */
94 public Main.Result doCall() {
95 try {
96 return handleExceptions(() -> {
97 prepareCompiler(false);
98 if (compiler.errorCount() > 0)
99 return Main.Result.ERROR;
100 compiler.compile(args.getFileObjects(), args.getClassNames(), processors, addModules);
101 return (compiler.errorCount() > 0) ? Main.Result.ERROR : Main.Result.OK; // FIXME?
102 }, Main.Result.SYSERR, Main.Result.ABNORMAL);
103 } finally {
104 try {
105 cleanup();
121 }
122 }
123
124 @Override @DefinedBy(Api.COMPILER)
125 public void setProcessors(Iterable<? extends Processor> processors) {
126 Objects.requireNonNull(processors);
127 // not mt-safe
128 if (used.get())
129 throw new IllegalStateException();
130 this.processors = processors;
131 }
132
133 @Override @DefinedBy(Api.COMPILER)
134 public void setLocale(Locale locale) {
135 if (used.get())
136 throw new IllegalStateException();
137 this.locale = locale;
138 }
139
140 private <T> T handleExceptions(Callable<T> c, T sysErrorResult, T abnormalErrorResult) {
141 try {
142 return c.call();
143 } catch (FatalError ex) {
144 Log log = Log.instance(context);
145 Options options = Options.instance(context);
146 log.printRawLines(ex.getMessage());
147 if (ex.getCause() != null && options.isSet("dev")) {
148 ex.getCause().printStackTrace(log.getWriter(WriterKind.NOTICE));
149 }
150 return sysErrorResult;
151 } catch (AnnotationProcessingError | ClientCodeException e) {
152 // AnnotationProcessingError is thrown from JavacProcessingEnvironment,
153 // to forward errors thrown from an annotation processor
154 // ClientCodeException is thrown from ClientCodeWrapper,
155 // to forward errors thrown from user-supplied code for Compiler API
156 // as specified by javax.tools.JavaCompiler#getTask
157 // and javax.tools.JavaCompiler.CompilationTask#call
158 throw new RuntimeException(e.getCause());
159 } catch (PropagatedException e) {
160 throw e.getCause();
161 } catch (IllegalStateException e) {
162 throw e;
163 } catch (Exception | Error ex) {
164 // Nasty. If we've already reported an error, compensate
165 // for buggy compiler error recovery by swallowing thrown
166 // exceptions.
167 if (compiler == null || compiler.errorCount() == 0
168 || Options.instance(context).isSet("dev")) {
169 Log log = Log.instance(context);
170 log.printLines(PrefixKind.JAVAC, "msg.bug", JavaCompiler.version());
171 ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
172 }
173 return abnormalErrorResult;
174 }
175 }
176
177 private void prepareCompiler(boolean forParse) {
178 if (used.getAndSet(true)) {
179 if (compiler == null)
180 throw new PropagatedException(new IllegalStateException());
181 } else {
182 args.validate();
183
184 //initialize compiler's default locale
185 context.put(Locale.class, locale);
186
187 // hack
188 JavacMessages messages = context.get(JavacMessages.messagesKey);
189 if (messages != null && !messages.getCurrentLocale().equals(locale))
190 messages.setCurrentLocale(locale);
191
192 initPlugins(args.getPluginOpts());
193 initDocLint(args.getDocLintOpts());
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.javac.api;
27
28 import java.io.IOException;
29 import java.nio.CharBuffer;
30 import java.util.*;
31 import java.util.concurrent.Callable;
32 import java.util.concurrent.atomic.AtomicBoolean;
33
34 import javax.annotation.processing.Processor;
35 import javax.lang.model.element.Element;
36 import javax.lang.model.element.TypeElement;
37 import javax.tools.*;
38
39 import com.sun.source.tree.*;
40 import com.sun.tools.javac.code.*;
41 import com.sun.tools.javac.code.DeferredCompletionFailureHandler.Handler;
42 import com.sun.tools.javac.code.Symbol.ClassSymbol;
43 import com.sun.tools.javac.comp.*;
44 import com.sun.tools.javac.file.BaseFileManager;
45 import com.sun.tools.javac.main.*;
46 import com.sun.tools.javac.main.JavaCompiler;
47 import com.sun.tools.javac.parser.Parser;
48 import com.sun.tools.javac.parser.ParserFactory;
49 import com.sun.tools.javac.processing.AnnotationProcessingError;
50 import com.sun.tools.javac.tree.*;
51 import com.sun.tools.javac.tree.JCTree.JCClassDecl;
52 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
53 import com.sun.tools.javac.tree.JCTree.JCModuleDecl;
54 import com.sun.tools.javac.tree.JCTree.Tag;
55 import com.sun.tools.javac.util.*;
56 import com.sun.tools.javac.util.DefinedBy.Api;
57 import com.sun.tools.javac.util.List;
58 import com.sun.tools.javac.util.Log.PrefixKind;
59 import com.sun.tools.javac.util.Log.WriterKind;
60
61 /**
62 * Provides access to functionality specific to the JDK Java Compiler, javac.
63 *
64 * <p><b>This is NOT part of any supported API.
65 * If you write code that depends on this, you do so at your own
66 * risk. This code and its internal interfaces are subject to change
67 * or deletion without notice.</b></p>
68 *
69 * @author Peter von der Ahé
70 * @author Jonathan Gibbons
71 */
72 public class JavacTaskImpl extends BasicJavacTask {
73 private final Arguments args;
74 private JavaCompiler compiler;
75 private JavaFileManager fileManager;
76 private DeferredCompletionFailureHandler dcfh;
77 private Locale locale;
78 private Map<JavaFileObject, JCCompilationUnit> notYetEntered;
79 private ListBuffer<Env<AttrContext>> genList;
80 private final AtomicBoolean used = new AtomicBoolean();
81 private Iterable<? extends Processor> processors;
82 private ListBuffer<String> addModules = new ListBuffer<>();
83
84 protected JavacTaskImpl(Context context) {
85 super(context, true);
86 args = Arguments.instance(context);
87 fileManager = context.get(JavaFileManager.class);
88 dcfh = DeferredCompletionFailureHandler.instance(context);
89 dcfh.setHandler(dcfh.userCodeHandler);
90 }
91
92 @Override @DefinedBy(Api.COMPILER)
93 public Boolean call() {
94 return doCall().isOK();
95 }
96
97 /* Internal version of call exposing Main.Result. */
98 public Main.Result doCall() {
99 try {
100 return handleExceptions(() -> {
101 prepareCompiler(false);
102 if (compiler.errorCount() > 0)
103 return Main.Result.ERROR;
104 compiler.compile(args.getFileObjects(), args.getClassNames(), processors, addModules);
105 return (compiler.errorCount() > 0) ? Main.Result.ERROR : Main.Result.OK; // FIXME?
106 }, Main.Result.SYSERR, Main.Result.ABNORMAL);
107 } finally {
108 try {
109 cleanup();
125 }
126 }
127
128 @Override @DefinedBy(Api.COMPILER)
129 public void setProcessors(Iterable<? extends Processor> processors) {
130 Objects.requireNonNull(processors);
131 // not mt-safe
132 if (used.get())
133 throw new IllegalStateException();
134 this.processors = processors;
135 }
136
137 @Override @DefinedBy(Api.COMPILER)
138 public void setLocale(Locale locale) {
139 if (used.get())
140 throw new IllegalStateException();
141 this.locale = locale;
142 }
143
144 private <T> T handleExceptions(Callable<T> c, T sysErrorResult, T abnormalErrorResult) {
145 Handler prevDeferredHandler = dcfh.setHandler(dcfh.javacCodeHandler);
146 try {
147 return c.call();
148 } catch (FatalError ex) {
149 Log log = Log.instance(context);
150 Options options = Options.instance(context);
151 log.printRawLines(ex.getMessage());
152 if (ex.getCause() != null && options.isSet("dev")) {
153 ex.getCause().printStackTrace(log.getWriter(WriterKind.NOTICE));
154 }
155 return sysErrorResult;
156 } catch (AnnotationProcessingError | ClientCodeException e) {
157 // AnnotationProcessingError is thrown from JavacProcessingEnvironment,
158 // to forward errors thrown from an annotation processor
159 // ClientCodeException is thrown from ClientCodeWrapper,
160 // to forward errors thrown from user-supplied code for Compiler API
161 // as specified by javax.tools.JavaCompiler#getTask
162 // and javax.tools.JavaCompiler.CompilationTask#call
163 throw new RuntimeException(e.getCause());
164 } catch (PropagatedException e) {
165 throw e.getCause();
166 } catch (IllegalStateException e) {
167 throw e;
168 } catch (Exception | Error ex) {
169 // Nasty. If we've already reported an error, compensate
170 // for buggy compiler error recovery by swallowing thrown
171 // exceptions.
172 if (compiler == null || compiler.errorCount() == 0
173 || Options.instance(context).isSet("dev")) {
174 Log log = Log.instance(context);
175 log.printLines(PrefixKind.JAVAC, "msg.bug", JavaCompiler.version());
176 ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
177 }
178 return abnormalErrorResult;
179 } finally {
180 dcfh.setHandler(prevDeferredHandler);
181 }
182 }
183
184 private void prepareCompiler(boolean forParse) {
185 if (used.getAndSet(true)) {
186 if (compiler == null)
187 throw new PropagatedException(new IllegalStateException());
188 } else {
189 args.validate();
190
191 //initialize compiler's default locale
192 context.put(Locale.class, locale);
193
194 // hack
195 JavacMessages messages = context.get(JavacMessages.messagesKey);
196 if (messages != null && !messages.getCurrentLocale().equals(locale))
197 messages.setCurrentLocale(locale);
198
199 initPlugins(args.getPluginOpts());
200 initDocLint(args.getDocLintOpts());
|