Tue, 25 Sep 2012 13:11:05 -0700
7196464: upgrade JavaCompiler.shouldStopPolicy to accomodate policies in face of error and no error
Reviewed-by: mcimadamore
duke@1 | 1 | /* |
jjg@1210 | 2 | * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. |
duke@1 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
duke@1 | 4 | * |
duke@1 | 5 | * This code is free software; you can redistribute it and/or modify it |
duke@1 | 6 | * under the terms of the GNU General Public License version 2 only, as |
ohair@554 | 7 | * published by the Free Software Foundation. Oracle designates this |
duke@1 | 8 | * particular file as subject to the "Classpath" exception as provided |
ohair@554 | 9 | * by Oracle in the LICENSE file that accompanied this code. |
duke@1 | 10 | * |
duke@1 | 11 | * This code is distributed in the hope that it will be useful, but WITHOUT |
duke@1 | 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
duke@1 | 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
duke@1 | 14 | * version 2 for more details (a copy is included in the LICENSE file that |
duke@1 | 15 | * accompanied this code). |
duke@1 | 16 | * |
duke@1 | 17 | * You should have received a copy of the GNU General Public License version |
duke@1 | 18 | * 2 along with this work; if not, write to the Free Software Foundation, |
duke@1 | 19 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
duke@1 | 20 | * |
ohair@554 | 21 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
ohair@554 | 22 | * or visit www.oracle.com if you need additional information or have any |
ohair@554 | 23 | * questions. |
duke@1 | 24 | */ |
duke@1 | 25 | |
duke@1 | 26 | package com.sun.tools.javac.api; |
duke@1 | 27 | |
duke@1 | 28 | import java.io.File; |
duke@1 | 29 | import java.io.IOException; |
jjg@111 | 30 | import java.nio.CharBuffer; |
duke@1 | 31 | import java.util.*; |
duke@1 | 32 | import java.util.concurrent.atomic.AtomicBoolean; |
duke@1 | 33 | |
duke@1 | 34 | import javax.annotation.processing.Processor; |
duke@1 | 35 | import javax.lang.model.element.Element; |
duke@1 | 36 | import javax.lang.model.element.TypeElement; |
duke@1 | 37 | import javax.lang.model.type.TypeMirror; |
duke@1 | 38 | import javax.tools.*; |
duke@1 | 39 | |
duke@1 | 40 | import com.sun.source.tree.*; |
duke@1 | 41 | import com.sun.source.util.*; |
duke@1 | 42 | import com.sun.tools.javac.code.*; |
duke@1 | 43 | import com.sun.tools.javac.code.Symbol.*; |
duke@1 | 44 | import com.sun.tools.javac.comp.*; |
jjg@50 | 45 | import com.sun.tools.javac.file.JavacFileManager; |
duke@1 | 46 | import com.sun.tools.javac.main.*; |
jjg@1210 | 47 | import com.sun.tools.javac.main.JavaCompiler; |
duke@1 | 48 | import com.sun.tools.javac.model.*; |
duke@1 | 49 | import com.sun.tools.javac.parser.Parser; |
jjg@111 | 50 | import com.sun.tools.javac.parser.ParserFactory; |
duke@1 | 51 | import com.sun.tools.javac.tree.*; |
duke@1 | 52 | import com.sun.tools.javac.tree.JCTree.*; |
duke@1 | 53 | import com.sun.tools.javac.util.*; |
duke@1 | 54 | import com.sun.tools.javac.util.List; |
duke@1 | 55 | |
duke@1 | 56 | /** |
jjg@582 | 57 | * Provides access to functionality specific to the JDK Java Compiler, javac. |
duke@1 | 58 | * |
jjg@581 | 59 | * <p><b>This is NOT part of any supported API. |
duke@1 | 60 | * If you write code that depends on this, you do so at your own |
duke@1 | 61 | * risk. This code and its internal interfaces are subject to change |
duke@1 | 62 | * or deletion without notice.</b></p> |
duke@1 | 63 | * |
duke@1 | 64 | * @author Peter von der Ahé |
duke@1 | 65 | * @author Jonathan Gibbons |
duke@1 | 66 | */ |
jjg@1210 | 67 | public class JavacTaskImpl extends BasicJavacTask { |
jjg@946 | 68 | private ClientCodeWrapper ccw; |
duke@1 | 69 | private Main compilerMain; |
duke@1 | 70 | private JavaCompiler compiler; |
mcimadamore@136 | 71 | private Locale locale; |
duke@1 | 72 | private String[] args; |
jjh@1187 | 73 | private String[] classNames; |
duke@1 | 74 | private List<JavaFileObject> fileObjects; |
duke@1 | 75 | private Map<JavaFileObject, JCCompilationUnit> notYetEntered; |
duke@1 | 76 | private ListBuffer<Env<AttrContext>> genList; |
duke@1 | 77 | private AtomicBoolean used = new AtomicBoolean(); |
duke@1 | 78 | private Iterable<? extends Processor> processors; |
duke@1 | 79 | |
jjg@1097 | 80 | private Main.Result result = null; |
duke@1 | 81 | |
jjg@946 | 82 | JavacTaskImpl(Main compilerMain, |
duke@1 | 83 | String[] args, |
jjh@1187 | 84 | String[] classNames, |
duke@1 | 85 | Context context, |
duke@1 | 86 | List<JavaFileObject> fileObjects) { |
jjg@1210 | 87 | super(null, false); |
jjg@946 | 88 | this.ccw = ClientCodeWrapper.instance(context); |
duke@1 | 89 | this.compilerMain = compilerMain; |
duke@1 | 90 | this.args = args; |
jjh@1187 | 91 | this.classNames = classNames; |
duke@1 | 92 | this.context = context; |
duke@1 | 93 | this.fileObjects = fileObjects; |
mcimadamore@136 | 94 | setLocale(Locale.getDefault()); |
duke@1 | 95 | // null checks |
duke@1 | 96 | compilerMain.getClass(); |
duke@1 | 97 | args.getClass(); |
duke@1 | 98 | fileObjects.getClass(); |
duke@1 | 99 | } |
duke@1 | 100 | |
jjg@946 | 101 | JavacTaskImpl(Main compilerMain, |
duke@1 | 102 | Iterable<String> flags, |
duke@1 | 103 | Context context, |
duke@1 | 104 | Iterable<String> classes, |
duke@1 | 105 | Iterable<? extends JavaFileObject> fileObjects) { |
jjh@1187 | 106 | this(compilerMain, toArray(flags), toArray(classes), context, toList(fileObjects)); |
duke@1 | 107 | } |
duke@1 | 108 | |
jjh@1187 | 109 | static private String[] toArray(Iterable<String> iter) { |
duke@1 | 110 | ListBuffer<String> result = new ListBuffer<String>(); |
jjh@1187 | 111 | if (iter != null) |
jjh@1187 | 112 | for (String s : iter) |
jjh@1187 | 113 | result.append(s); |
duke@1 | 114 | return result.toArray(new String[result.length()]); |
duke@1 | 115 | } |
duke@1 | 116 | |
duke@1 | 117 | static private List<JavaFileObject> toList(Iterable<? extends JavaFileObject> fileObjects) { |
duke@1 | 118 | if (fileObjects == null) |
duke@1 | 119 | return List.nil(); |
duke@1 | 120 | ListBuffer<JavaFileObject> result = new ListBuffer<JavaFileObject>(); |
duke@1 | 121 | for (JavaFileObject fo : fileObjects) |
duke@1 | 122 | result.append(fo); |
duke@1 | 123 | return result.toList(); |
duke@1 | 124 | } |
duke@1 | 125 | |
duke@1 | 126 | public Boolean call() { |
duke@1 | 127 | if (!used.getAndSet(true)) { |
jjg@930 | 128 | initContext(); |
jjg@308 | 129 | notYetEntered = new HashMap<JavaFileObject, JCCompilationUnit>(); |
jjg@946 | 130 | compilerMain.setAPIMode(true); |
jjh@1187 | 131 | result = compilerMain.compile(args, classNames, context, fileObjects, processors); |
jjg@930 | 132 | cleanup(); |
jjg@1097 | 133 | return result.isOK(); |
duke@1 | 134 | } else { |
duke@1 | 135 | throw new IllegalStateException("multiple calls to method 'call'"); |
duke@1 | 136 | } |
duke@1 | 137 | } |
duke@1 | 138 | |
duke@1 | 139 | public void setProcessors(Iterable<? extends Processor> processors) { |
duke@1 | 140 | processors.getClass(); // null check |
duke@1 | 141 | // not mt-safe |
duke@1 | 142 | if (used.get()) |
duke@1 | 143 | throw new IllegalStateException(); |
duke@1 | 144 | this.processors = processors; |
duke@1 | 145 | } |
duke@1 | 146 | |
duke@1 | 147 | public void setLocale(Locale locale) { |
duke@1 | 148 | if (used.get()) |
duke@1 | 149 | throw new IllegalStateException(); |
mcimadamore@136 | 150 | this.locale = locale; |
duke@1 | 151 | } |
duke@1 | 152 | |
duke@1 | 153 | private void prepareCompiler() throws IOException { |
jjg@930 | 154 | if (used.getAndSet(true)) { |
jjg@930 | 155 | if (compiler == null) |
jjg@930 | 156 | throw new IllegalStateException(); |
jjg@930 | 157 | } else { |
jjg@930 | 158 | initContext(); |
duke@1 | 159 | compilerMain.setOptions(Options.instance(context)); |
jjg@1055 | 160 | compilerMain.filenames = new LinkedHashSet<File>(); |
jjh@1187 | 161 | Collection<File> filenames = compilerMain.processArgs(CommandLine.parse(args), classNames); |
duke@1 | 162 | if (!filenames.isEmpty()) |
jjg@1055 | 163 | throw new IllegalArgumentException("Malformed arguments " + toString(filenames, " ")); |
duke@1 | 164 | compiler = JavaCompiler.instance(context); |
duke@1 | 165 | compiler.keepComments = true; |
duke@1 | 166 | compiler.genEndPos = true; |
duke@1 | 167 | // NOTE: this value will be updated after annotation processing |
duke@1 | 168 | compiler.initProcessAnnotations(processors); |
duke@1 | 169 | notYetEntered = new HashMap<JavaFileObject, JCCompilationUnit>(); |
duke@1 | 170 | for (JavaFileObject file: fileObjects) |
duke@1 | 171 | notYetEntered.put(file, null); |
duke@1 | 172 | genList = new ListBuffer<Env<AttrContext>>(); |
duke@1 | 173 | // endContext will be called when all classes have been generated |
duke@1 | 174 | // TODO: should handle the case after each phase if errors have occurred |
duke@1 | 175 | args = null; |
jjh@1187 | 176 | classNames = null; |
duke@1 | 177 | } |
duke@1 | 178 | } |
duke@1 | 179 | |
jjg@1055 | 180 | <T> String toString(Iterable<T> items, String sep) { |
jjg@1055 | 181 | String currSep = ""; |
jjg@1055 | 182 | StringBuilder sb = new StringBuilder(); |
jjg@1055 | 183 | for (T item: items) { |
jjg@1055 | 184 | sb.append(currSep); |
jjg@1055 | 185 | sb.append(item.toString()); |
jjg@1055 | 186 | currSep = sep; |
jjg@1055 | 187 | } |
jjg@1055 | 188 | return sb.toString(); |
jjg@1055 | 189 | } |
jjg@1055 | 190 | |
jjg@930 | 191 | private void initContext() { |
jjg@1210 | 192 | context.put(JavacTask.class, this); |
mcimadamore@136 | 193 | //initialize compiler's default locale |
jjg@944 | 194 | context.put(Locale.class, locale); |
duke@1 | 195 | } |
duke@1 | 196 | |
jjg@930 | 197 | void cleanup() { |
jjg@930 | 198 | if (compiler != null) |
jjg@930 | 199 | compiler.close(); |
jjg@930 | 200 | compiler = null; |
jjg@930 | 201 | compilerMain = null; |
jjg@930 | 202 | args = null; |
jjh@1187 | 203 | classNames = null; |
jjg@930 | 204 | context = null; |
jjg@930 | 205 | fileObjects = null; |
jjg@930 | 206 | notYetEntered = null; |
duke@1 | 207 | } |
duke@1 | 208 | |
duke@1 | 209 | /** |
duke@1 | 210 | * Construct a JavaFileObject from the given file. |
duke@1 | 211 | * |
duke@1 | 212 | * <p><b>TODO: this method is useless here</b></p> |
duke@1 | 213 | * |
duke@1 | 214 | * @param file a file |
duke@1 | 215 | * @return a JavaFileObject from the standard file manager. |
duke@1 | 216 | */ |
duke@1 | 217 | public JavaFileObject asJavaFileObject(File file) { |
duke@1 | 218 | JavacFileManager fm = (JavacFileManager)context.get(JavaFileManager.class); |
duke@1 | 219 | return fm.getRegularFile(file); |
duke@1 | 220 | } |
duke@1 | 221 | |
duke@1 | 222 | /** |
duke@1 | 223 | * Parse the specified files returning a list of abstract syntax trees. |
duke@1 | 224 | * |
duke@1 | 225 | * @throws java.io.IOException TODO |
duke@1 | 226 | * @return a list of abstract syntax trees |
duke@1 | 227 | */ |
duke@1 | 228 | public Iterable<? extends CompilationUnitTree> parse() throws IOException { |
duke@1 | 229 | try { |
duke@1 | 230 | prepareCompiler(); |
duke@1 | 231 | List<JCCompilationUnit> units = compiler.parseFiles(fileObjects); |
duke@1 | 232 | for (JCCompilationUnit unit: units) { |
duke@1 | 233 | JavaFileObject file = unit.getSourceFile(); |
duke@1 | 234 | if (notYetEntered.containsKey(file)) |
duke@1 | 235 | notYetEntered.put(file, unit); |
duke@1 | 236 | } |
duke@1 | 237 | return units; |
duke@1 | 238 | } |
duke@1 | 239 | finally { |
duke@1 | 240 | parsed = true; |
duke@1 | 241 | if (compiler != null && compiler.log != null) |
duke@1 | 242 | compiler.log.flush(); |
duke@1 | 243 | } |
duke@1 | 244 | } |
duke@1 | 245 | |
duke@1 | 246 | private boolean parsed = false; |
duke@1 | 247 | |
duke@1 | 248 | /** |
duke@1 | 249 | * Translate all the abstract syntax trees to elements. |
duke@1 | 250 | * |
duke@1 | 251 | * @throws IOException TODO |
duke@1 | 252 | * @return a list of elements corresponding to the top level |
duke@1 | 253 | * classes in the abstract syntax trees |
duke@1 | 254 | */ |
duke@1 | 255 | public Iterable<? extends TypeElement> enter() throws IOException { |
duke@1 | 256 | return enter(null); |
duke@1 | 257 | } |
duke@1 | 258 | |
duke@1 | 259 | /** |
duke@1 | 260 | * Translate the given abstract syntax trees to elements. |
duke@1 | 261 | * |
duke@1 | 262 | * @param trees a list of abstract syntax trees. |
duke@1 | 263 | * @throws java.io.IOException TODO |
duke@1 | 264 | * @return a list of elements corresponding to the top level |
duke@1 | 265 | * classes in the abstract syntax trees |
duke@1 | 266 | */ |
duke@1 | 267 | public Iterable<? extends TypeElement> enter(Iterable<? extends CompilationUnitTree> trees) |
duke@1 | 268 | throws IOException |
duke@1 | 269 | { |
jjg@1090 | 270 | if (trees == null && notYetEntered != null && notYetEntered.isEmpty()) |
jjg@1090 | 271 | return List.nil(); |
jjg@1090 | 272 | |
duke@1 | 273 | prepareCompiler(); |
duke@1 | 274 | |
duke@1 | 275 | ListBuffer<JCCompilationUnit> roots = null; |
duke@1 | 276 | |
duke@1 | 277 | if (trees == null) { |
duke@1 | 278 | // If there are still files which were specified to be compiled |
duke@1 | 279 | // (i.e. in fileObjects) but which have not yet been entered, |
duke@1 | 280 | // then we make sure they have been parsed and add them to the |
duke@1 | 281 | // list to be entered. |
duke@1 | 282 | if (notYetEntered.size() > 0) { |
duke@1 | 283 | if (!parsed) |
duke@1 | 284 | parse(); // TODO would be nice to specify files needed to be parsed |
duke@1 | 285 | for (JavaFileObject file: fileObjects) { |
duke@1 | 286 | JCCompilationUnit unit = notYetEntered.remove(file); |
duke@1 | 287 | if (unit != null) { |
duke@1 | 288 | if (roots == null) |
duke@1 | 289 | roots = new ListBuffer<JCCompilationUnit>(); |
duke@1 | 290 | roots.append(unit); |
duke@1 | 291 | } |
duke@1 | 292 | } |
duke@1 | 293 | notYetEntered.clear(); |
duke@1 | 294 | } |
duke@1 | 295 | } |
duke@1 | 296 | else { |
duke@1 | 297 | for (CompilationUnitTree cu : trees) { |
duke@1 | 298 | if (cu instanceof JCCompilationUnit) { |
duke@1 | 299 | if (roots == null) |
duke@1 | 300 | roots = new ListBuffer<JCCompilationUnit>(); |
duke@1 | 301 | roots.append((JCCompilationUnit)cu); |
duke@1 | 302 | notYetEntered.remove(cu.getSourceFile()); |
duke@1 | 303 | } |
duke@1 | 304 | else |
duke@1 | 305 | throw new IllegalArgumentException(cu.toString()); |
duke@1 | 306 | } |
duke@1 | 307 | } |
duke@1 | 308 | |
duke@1 | 309 | if (roots == null) |
duke@1 | 310 | return List.nil(); |
duke@1 | 311 | |
duke@1 | 312 | try { |
duke@1 | 313 | List<JCCompilationUnit> units = compiler.enterTrees(roots.toList()); |
duke@1 | 314 | |
duke@1 | 315 | if (notYetEntered.isEmpty()) |
duke@1 | 316 | compiler = compiler.processAnnotations(units); |
duke@1 | 317 | |
duke@1 | 318 | ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>(); |
duke@1 | 319 | for (JCCompilationUnit unit : units) { |
jjg@695 | 320 | for (JCTree node : unit.defs) { |
jjg@1127 | 321 | if (node.hasTag(JCTree.Tag.CLASSDEF)) { |
jjg@695 | 322 | JCClassDecl cdef = (JCClassDecl) node; |
jjg@695 | 323 | if (cdef.sym != null) // maybe null if errors in anno processing |
jjg@695 | 324 | elements.append(cdef.sym); |
jjg@695 | 325 | } |
jjg@695 | 326 | } |
duke@1 | 327 | } |
duke@1 | 328 | return elements.toList(); |
duke@1 | 329 | } |
duke@1 | 330 | finally { |
duke@1 | 331 | compiler.log.flush(); |
duke@1 | 332 | } |
duke@1 | 333 | } |
duke@1 | 334 | |
duke@1 | 335 | /** |
duke@1 | 336 | * Complete all analysis. |
duke@1 | 337 | * @throws IOException TODO |
duke@1 | 338 | */ |
duke@1 | 339 | @Override |
duke@1 | 340 | public Iterable<? extends Element> analyze() throws IOException { |
duke@1 | 341 | return analyze(null); |
duke@1 | 342 | } |
duke@1 | 343 | |
duke@1 | 344 | /** |
duke@1 | 345 | * Complete all analysis on the given classes. |
duke@1 | 346 | * This can be used to ensure that all compile time errors are reported. |
duke@1 | 347 | * The classes must have previously been returned from {@link #enter}. |
duke@1 | 348 | * If null is specified, all outstanding classes will be analyzed. |
duke@1 | 349 | * |
duke@1 | 350 | * @param classes a list of class elements |
duke@1 | 351 | */ |
duke@1 | 352 | // This implementation requires that we open up privileges on JavaCompiler. |
duke@1 | 353 | // An alternative implementation would be to move this code to JavaCompiler and |
duke@1 | 354 | // wrap it here |
duke@1 | 355 | public Iterable<? extends Element> analyze(Iterable<? extends TypeElement> classes) throws IOException { |
duke@1 | 356 | enter(null); // ensure all classes have been entered |
duke@1 | 357 | |
duke@1 | 358 | final ListBuffer<Element> results = new ListBuffer<Element>(); |
duke@1 | 359 | try { |
duke@1 | 360 | if (classes == null) { |
duke@1 | 361 | handleFlowResults(compiler.flow(compiler.attribute(compiler.todo)), results); |
duke@1 | 362 | } else { |
duke@1 | 363 | Filter f = new Filter() { |
duke@1 | 364 | public void process(Env<AttrContext> env) { |
duke@1 | 365 | handleFlowResults(compiler.flow(compiler.attribute(env)), results); |
duke@1 | 366 | } |
duke@1 | 367 | }; |
duke@1 | 368 | f.run(compiler.todo, classes); |
duke@1 | 369 | } |
duke@1 | 370 | } finally { |
duke@1 | 371 | compiler.log.flush(); |
duke@1 | 372 | } |
duke@1 | 373 | return results; |
duke@1 | 374 | } |
duke@1 | 375 | // where |
jjg@70 | 376 | private void handleFlowResults(Queue<Env<AttrContext>> queue, ListBuffer<Element> elems) { |
jjg@70 | 377 | for (Env<AttrContext> env: queue) { |
duke@1 | 378 | switch (env.tree.getTag()) { |
jjg@1127 | 379 | case CLASSDEF: |
duke@1 | 380 | JCClassDecl cdef = (JCClassDecl) env.tree; |
duke@1 | 381 | if (cdef.sym != null) |
duke@1 | 382 | elems.append(cdef.sym); |
duke@1 | 383 | break; |
jjg@1127 | 384 | case TOPLEVEL: |
duke@1 | 385 | JCCompilationUnit unit = (JCCompilationUnit) env.tree; |
duke@1 | 386 | if (unit.packge != null) |
duke@1 | 387 | elems.append(unit.packge); |
duke@1 | 388 | break; |
duke@1 | 389 | } |
duke@1 | 390 | } |
jjg@70 | 391 | genList.addAll(queue); |
duke@1 | 392 | } |
duke@1 | 393 | |
duke@1 | 394 | |
duke@1 | 395 | /** |
duke@1 | 396 | * Generate code. |
duke@1 | 397 | * @throws IOException TODO |
duke@1 | 398 | */ |
duke@1 | 399 | @Override |
duke@1 | 400 | public Iterable<? extends JavaFileObject> generate() throws IOException { |
duke@1 | 401 | return generate(null); |
duke@1 | 402 | } |
duke@1 | 403 | |
duke@1 | 404 | /** |
duke@1 | 405 | * Generate code corresponding to the given classes. |
duke@1 | 406 | * The classes must have previously been returned from {@link #enter}. |
duke@1 | 407 | * If there are classes outstanding to be analyzed, that will be done before |
duke@1 | 408 | * any classes are generated. |
duke@1 | 409 | * If null is specified, code will be generated for all outstanding classes. |
duke@1 | 410 | * |
duke@1 | 411 | * @param classes a list of class elements |
duke@1 | 412 | */ |
duke@1 | 413 | public Iterable<? extends JavaFileObject> generate(Iterable<? extends TypeElement> classes) throws IOException { |
duke@1 | 414 | final ListBuffer<JavaFileObject> results = new ListBuffer<JavaFileObject>(); |
duke@1 | 415 | try { |
duke@1 | 416 | analyze(null); // ensure all classes have been parsed, entered, and analyzed |
duke@1 | 417 | |
duke@1 | 418 | if (classes == null) { |
jjg@70 | 419 | compiler.generate(compiler.desugar(genList), results); |
duke@1 | 420 | genList.clear(); |
duke@1 | 421 | } |
duke@1 | 422 | else { |
duke@1 | 423 | Filter f = new Filter() { |
duke@1 | 424 | public void process(Env<AttrContext> env) { |
jjg@70 | 425 | compiler.generate(compiler.desugar(ListBuffer.of(env)), results); |
duke@1 | 426 | } |
duke@1 | 427 | }; |
duke@1 | 428 | f.run(genList, classes); |
duke@1 | 429 | } |
duke@1 | 430 | if (genList.isEmpty()) { |
duke@1 | 431 | compiler.reportDeferredDiagnostics(); |
jjg@930 | 432 | cleanup(); |
duke@1 | 433 | } |
duke@1 | 434 | } |
duke@1 | 435 | finally { |
jjg@930 | 436 | if (compiler != null) |
jjg@930 | 437 | compiler.log.flush(); |
duke@1 | 438 | } |
duke@1 | 439 | return results; |
duke@1 | 440 | } |
duke@1 | 441 | |
duke@1 | 442 | public TypeMirror getTypeMirror(Iterable<? extends Tree> path) { |
duke@1 | 443 | // TODO: Should complete attribution if necessary |
duke@1 | 444 | Tree last = null; |
duke@1 | 445 | for (Tree node : path) |
duke@1 | 446 | last = node; |
duke@1 | 447 | return ((JCTree)last).type; |
duke@1 | 448 | } |
duke@1 | 449 | |
duke@1 | 450 | public JavacElements getElements() { |
duke@1 | 451 | if (context == null) |
duke@1 | 452 | throw new IllegalStateException(); |
duke@1 | 453 | return JavacElements.instance(context); |
duke@1 | 454 | } |
duke@1 | 455 | |
duke@1 | 456 | public JavacTypes getTypes() { |
duke@1 | 457 | if (context == null) |
duke@1 | 458 | throw new IllegalStateException(); |
duke@1 | 459 | return JavacTypes.instance(context); |
duke@1 | 460 | } |
duke@1 | 461 | |
duke@1 | 462 | public Iterable<? extends Tree> pathFor(CompilationUnitTree unit, Tree node) { |
duke@1 | 463 | return TreeInfo.pathFor((JCTree) node, (JCTree.JCCompilationUnit) unit).reverse(); |
duke@1 | 464 | } |
duke@1 | 465 | |
duke@1 | 466 | abstract class Filter { |
jjg@119 | 467 | void run(Queue<Env<AttrContext>> list, Iterable<? extends TypeElement> classes) { |
duke@1 | 468 | Set<TypeElement> set = new HashSet<TypeElement>(); |
duke@1 | 469 | for (TypeElement item: classes) |
duke@1 | 470 | set.add(item); |
duke@1 | 471 | |
jjg@119 | 472 | ListBuffer<Env<AttrContext>> defer = ListBuffer.<Env<AttrContext>>lb(); |
jjg@119 | 473 | while (list.peek() != null) { |
jjg@119 | 474 | Env<AttrContext> env = list.remove(); |
duke@1 | 475 | ClassSymbol csym = env.enclClass.sym; |
duke@1 | 476 | if (csym != null && set.contains(csym.outermostClass())) |
duke@1 | 477 | process(env); |
duke@1 | 478 | else |
jjg@119 | 479 | defer = defer.append(env); |
duke@1 | 480 | } |
duke@1 | 481 | |
jjg@119 | 482 | list.addAll(defer); |
duke@1 | 483 | } |
duke@1 | 484 | |
duke@1 | 485 | abstract void process(Env<AttrContext> env); |
duke@1 | 486 | } |
duke@1 | 487 | |
duke@1 | 488 | /** |
jjg@581 | 489 | * For internal use only. This method will be |
duke@1 | 490 | * removed without warning. |
duke@1 | 491 | */ |
duke@1 | 492 | public Context getContext() { |
duke@1 | 493 | return context; |
duke@1 | 494 | } |
duke@1 | 495 | |
duke@1 | 496 | /** |
jjg@581 | 497 | * For internal use only. This method will be |
duke@1 | 498 | * removed without warning. |
duke@1 | 499 | */ |
duke@1 | 500 | public void updateContext(Context newContext) { |
duke@1 | 501 | context = newContext; |
duke@1 | 502 | } |
duke@1 | 503 | |
duke@1 | 504 | /** |
jjg@581 | 505 | * For internal use only. This method will be |
duke@1 | 506 | * removed without warning. |
duke@1 | 507 | */ |
duke@1 | 508 | public Type parseType(String expr, TypeElement scope) { |
duke@1 | 509 | if (expr == null || expr.equals("")) |
duke@1 | 510 | throw new IllegalArgumentException(); |
duke@1 | 511 | compiler = JavaCompiler.instance(context); |
duke@1 | 512 | JavaFileObject prev = compiler.log.useSource(null); |
jjg@111 | 513 | ParserFactory parserFactory = ParserFactory.instance(context); |
duke@1 | 514 | Attr attr = Attr.instance(context); |
duke@1 | 515 | try { |
jjg@111 | 516 | CharBuffer buf = CharBuffer.wrap((expr+"\u0000").toCharArray(), 0, expr.length()); |
jjg@111 | 517 | Parser parser = parserFactory.newParser(buf, false, false, false); |
jjg@111 | 518 | JCTree tree = parser.parseType(); |
duke@1 | 519 | return attr.attribType(tree, (Symbol.TypeSymbol)scope); |
duke@1 | 520 | } finally { |
duke@1 | 521 | compiler.log.useSource(prev); |
duke@1 | 522 | } |
duke@1 | 523 | } |
duke@1 | 524 | |
duke@1 | 525 | } |