1 /* 2 * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 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.lang.module.Configuration; 29 import java.lang.module.ModuleFinder; 30 import java.util.Collection; 31 import java.util.LinkedHashSet; 32 import java.util.Locale; 33 import java.util.Objects; 34 import java.util.ServiceLoader; 35 import java.util.Set; 36 37 import javax.annotation.processing.Processor; 38 import javax.lang.model.element.Element; 39 import javax.lang.model.type.TypeMirror; 40 import javax.lang.model.util.Elements; 41 import javax.lang.model.util.Types; 42 import javax.tools.JavaFileObject; 43 44 import com.sun.source.tree.CompilationUnitTree; 45 import com.sun.source.tree.Tree; 46 import com.sun.source.util.JavacTask; 47 import com.sun.source.util.ParameterNameProvider; 48 import com.sun.source.util.Plugin; 49 import com.sun.source.util.TaskListener; 50 import com.sun.tools.doclint.DocLint; 51 import com.sun.tools.javac.code.MissingInfoHandler; 52 import com.sun.tools.javac.main.JavaCompiler; 53 import com.sun.tools.javac.model.JavacElements; 54 import com.sun.tools.javac.model.JavacTypes; 55 import com.sun.tools.javac.platform.PlatformDescription; 56 import com.sun.tools.javac.platform.PlatformDescription.PluginInfo; 57 import com.sun.tools.javac.processing.JavacProcessingEnvironment; 58 import com.sun.tools.javac.resources.CompilerProperties.Errors; 59 import com.sun.tools.javac.resources.CompilerProperties.Warnings; 60 import com.sun.tools.javac.tree.JCTree; 61 import com.sun.tools.javac.util.Context; 62 import com.sun.tools.javac.util.DefinedBy; 63 import com.sun.tools.javac.util.DefinedBy.Api; 64 import com.sun.tools.javac.util.List; 65 import com.sun.tools.javac.util.Log; 66 import com.sun.tools.javac.util.ModuleHelper; 67 import com.sun.tools.javac.util.Options; 68 import com.sun.tools.javac.util.PropagatedException; 69 70 /** 71 * Provides basic functionality for implementations of JavacTask. 72 * 73 * <p><b>This is NOT part of any supported API. 74 * If you write code that depends on this, you do so at your own 75 * risk. This code and its internal interfaces are subject to change 76 * or deletion without notice.</b></p> 77 */ 78 public class BasicJavacTask extends JavacTask { 79 protected Context context; 80 protected Options options; 81 private TaskListener taskListener; 82 83 public static JavacTask instance(Context context) { 84 JavacTask instance = context.get(JavacTask.class); 85 if (instance == null) 86 instance = new BasicJavacTask(context, true); 87 return instance; 88 } 89 90 @SuppressWarnings("this-escape") 91 public BasicJavacTask(Context c, boolean register) { 92 context = c; 93 options = Options.instance(c); 94 if (register) 95 context.put(JavacTask.class, this); 96 } 97 98 @Override @DefinedBy(Api.COMPILER_TREE) 99 public Iterable<? extends CompilationUnitTree> parse() { 100 throw new IllegalStateException(); 101 } 102 103 @Override @DefinedBy(Api.COMPILER_TREE) 104 public Iterable<? extends Element> analyze() { 105 throw new IllegalStateException(); 106 } 107 108 @Override @DefinedBy(Api.COMPILER_TREE) 109 public Iterable<? extends JavaFileObject> generate() { 110 throw new IllegalStateException(); 111 } 112 113 @Override @DefinedBy(Api.COMPILER_TREE) 114 public void setTaskListener(TaskListener tl) { 115 MultiTaskListener mtl = MultiTaskListener.instance(context); 116 if (taskListener != null) 117 mtl.remove(taskListener); 118 if (tl != null) 119 mtl.add(tl); 120 taskListener = tl; 121 } 122 123 @Override @DefinedBy(Api.COMPILER_TREE) 124 public void addTaskListener(TaskListener taskListener) { 125 MultiTaskListener mtl = MultiTaskListener.instance(context); 126 mtl.add(taskListener); 127 } 128 129 @Override @DefinedBy(Api.COMPILER_TREE) 130 public void removeTaskListener(TaskListener taskListener) { 131 MultiTaskListener mtl = MultiTaskListener.instance(context); 132 mtl.remove(taskListener); 133 } 134 135 @Override 136 public void setParameterNameProvider(ParameterNameProvider handler) { 137 MissingInfoHandler.instance(context).setDelegate(handler); 138 } 139 140 public Collection<TaskListener> getTaskListeners() { 141 MultiTaskListener mtl = MultiTaskListener.instance(context); 142 return mtl.getTaskListeners(); 143 } 144 145 @Override @DefinedBy(Api.COMPILER_TREE) 146 public TypeMirror getTypeMirror(Iterable<? extends Tree> path) { 147 // TODO: Should complete attribution if necessary 148 Tree last = null; 149 for (Tree node : path) { 150 last = Objects.requireNonNull(node); 151 } 152 if (last == null) { 153 throw new IllegalArgumentException("empty path"); 154 } 155 return ((JCTree) last).type; 156 } 157 158 @Override @DefinedBy(Api.COMPILER_TREE) 159 public Elements getElements() { 160 if (context == null) 161 throw new IllegalStateException(); 162 return JavacElements.instance(context); 163 } 164 165 @Override @DefinedBy(Api.COMPILER_TREE) 166 public Types getTypes() { 167 if (context == null) 168 throw new IllegalStateException(); 169 return JavacTypes.instance(context); 170 } 171 172 @Override @DefinedBy(Api.COMPILER) 173 public void addModules(Iterable<String> moduleNames) { 174 throw new IllegalStateException(); 175 } 176 177 @Override @DefinedBy(Api.COMPILER) 178 public void setProcessors(Iterable<? extends Processor> processors) { 179 throw new IllegalStateException(); 180 } 181 182 @Override @DefinedBy(Api.COMPILER) 183 public void setLocale(Locale locale) { 184 throw new IllegalStateException(); 185 } 186 187 @Override @DefinedBy(Api.COMPILER) 188 public Boolean call() { 189 throw new IllegalStateException(); 190 } 191 192 /** 193 * For internal use only. 194 * This method will be removed without warning. 195 * @return the context 196 */ 197 public Context getContext() { 198 return context; 199 } 200 201 public void initPlugins(Set<List<String>> pluginOpts) { 202 PlatformDescription platformProvider = context.get(PlatformDescription.class); 203 204 if (platformProvider != null) { 205 for (PluginInfo<Plugin> pluginDesc : platformProvider.getPlugins()) { 206 java.util.List<String> options = 207 pluginDesc.getOptions().entrySet().stream() 208 .map(e -> e.getKey() + "=" + e.getValue()) 209 .toList(); 210 try { 211 initPlugin(pluginDesc.getPlugin(), options.toArray(new String[options.size()])); 212 } catch (RuntimeException ex) { 213 throw new PropagatedException(ex); 214 } 215 } 216 } 217 218 Set<List<String>> pluginsToCall = new LinkedHashSet<>(pluginOpts); 219 JavacProcessingEnvironment pEnv = JavacProcessingEnvironment.instance(context); 220 ServiceLoader<Plugin> sl = pEnv.getServiceLoader(Plugin.class); 221 Set<Plugin> autoStart = new LinkedHashSet<>(); 222 for (Plugin plugin : sl) { 223 if (plugin.autoStart()) { 224 autoStart.add(plugin); 225 } 226 for (List<String> p : pluginsToCall) { 227 if (plugin.getName().equals(p.head)) { 228 pluginsToCall.remove(p); 229 autoStart.remove(plugin); 230 try { 231 initPlugin(plugin, p.tail.toArray(new String[p.tail.size()])); 232 } catch (RuntimeException ex) { 233 throw new PropagatedException(ex); 234 } 235 break; 236 } 237 } 238 } 239 for (List<String> p : pluginsToCall) { 240 Log.instance(context).error(Errors.PluginNotFound(p.head)); 241 } 242 for (Plugin plugin : autoStart) { 243 try { 244 initPlugin(plugin, new String[0]); 245 } catch (RuntimeException ex) { 246 throw new PropagatedException(ex); 247 } 248 249 } 250 } 251 252 private void initPlugin(Plugin p, String... args) { 253 Module m = p.getClass().getModule(); 254 if (m.isNamed() && options.isSet("accessInternalAPI")) { 255 ModuleHelper.addExports(getClass().getModule(), m); 256 } 257 p.init(this, args); 258 } 259 260 public void initDocLint(List<String> docLintOpts) { 261 if (docLintOpts.isEmpty()) 262 return; 263 try { 264 DocLint.newDocLint().init(this, docLintOpts.toArray(new String[docLintOpts.size()])); 265 JavaCompiler.instance(context).keepComments = true; 266 } catch (IllegalStateException e) { 267 Log.instance(context).warning(Warnings.DoclintNotAvailable); 268 } 269 } 270 }