1 19 20 package org.netbeans.modules.java.source.builder; 21 22 import com.sun.source.tree.CompilationUnitTree; 23 import com.sun.tools.javac.api.JavacTaskImpl; 24 import com.sun.tools.javac.parser.EndPosParser; 25 import org.netbeans.api.java.source.query.CommentHandler; 26 import org.netbeans.modules.java.source.engine.RootTree; 27 import org.netbeans.modules.java.source.engine.BuildProgress; 28 import org.netbeans.modules.java.source.engine.ElapsedTimer; 29 import org.netbeans.modules.java.source.builder.DefaultSourceFileFilter; 30 import org.netbeans.modules.java.source.engine.ReattributionException; 31 import org.netbeans.modules.java.source.save.SourceBuffer; 32 import org.netbeans.modules.java.source.builder.SourceFileList; 33 import org.netbeans.modules.java.source.builder.SourceFileFilter; 34 import com.sun.tools.javac.comp.*; 35 import com.sun.tools.javac.code.Symbol.*; 36 import com.sun.tools.javac.jvm.ClassReader; 37 import com.sun.tools.javac.parser.Parser; 38 import com.sun.tools.javac.tree.*; 39 import com.sun.tools.javac.tree.JCTree.*; 40 import com.sun.tools.javac.util.*; 41 import java.io.*; 42 import java.util.ArrayList ; 43 import java.util.Collections ; 44 import java.util.logging.*; 45 import javax.tools.JavaCompiler; 46 import javax.tools.JavaFileManager; 47 import javax.tools.JavaFileObject; 48 import javax.tools.StandardJavaFileManager; 49 import javax.tools.ToolProvider; 50 import org.netbeans.api.java.source.ClasspathInfo; 51 52 57 public final class Builder implements ClassReader.SourceCompleter { 58 private Log log; 59 private Context context; 60 private Enter enter; 61 private TreeMaker make; 62 private CommentHandlerService comments; 63 private Parser.Factory parserFactory; 64 private Scanner.Factory scannerFactory; 65 private ASTService trees; 66 private String encoding; 67 private String [] sourcePaths; 68 private BuildProgress progressMonitor; 69 private int nfiles; 70 private JavaFileManager fileManager; 71 72 static final Logger logger = Logger.getLogger("org.netbeans.modules.java.source"); 73 static boolean dumpAST = Boolean.getBoolean("jackpot.dump.ast"); 74 75 83 public int build() throws Exception { 84 ElapsedTimer timer = new ElapsedTimer(); 85 try { 86 progressMonitor.buildStarted(); 87 progressMonitor.sourceExpansionStarting(); 88 String [] filenames = SourceFileList.findFiles(sourcePaths, sourceFileFilter); 89 nfiles = filenames.length; 90 progressMonitor.sourceExpansionFinished(); 91 if (nfiles == 0) 92 return 0; compile(List.from(filenames)); 94 } finally { 95 close(); 96 timer.stop(); 97 progressMonitor.buildFinished(errorCount(), warningCount(), timer.getElapsedMilliseconds()); 98 progressMonitor = null; 99 } 100 return errorCount(); 101 } 102 103 113 Builder(JavacTaskImpl task, String [] sourcePaths, BuildProgress progress) { 114 context = task.getContext(); 115 this.sourcePaths = sourcePaths; 116 this.progressMonitor = progress; 117 log = Log.instance(context); 118 enter = (Enter)Enter.instance(context); 119 enter.setBuildProgress(progress); 120 make = TreeMaker.instance(context); 121 comments = CommentHandlerService.instance(context); 122 parserFactory = ParserFactory.instance(context); 123 scannerFactory = (Scanner.Factory)Scanner.Factory.instance(context); 124 trees = ASTService.instance(context); 125 fileManager = context.get(JavaFileManager.class); 126 assert this.fileManager instanceof StandardJavaFileManager; 127 } 128 129 static JavacTaskImpl createJavacTask(String sourcepath, String classpath, String bootclasspath, String sourceLevel, String encoding) { 130 ArrayList <String > options = new ArrayList <String >(); 131 options.add("-XDbackgroundCompilation"); options.add("-XDcompilePolicy=attr"); options.add("-source"); if (sourceLevel == null) 135 sourceLevel = "1.5"; 136 options.add(sourceLevel); 137 options.add("-classpath"); 138 options.add(classpath); 139 if (bootclasspath != null) { 140 options.add("-bootclasspath"); 141 options.add(bootclasspath); 142 } 143 if (encoding != null && encoding.length() > 0) { 144 options.add("-encoding"); 145 options.add(encoding); 146 } 147 String maxInt = Integer.toString(Integer.MAX_VALUE); 148 options.add("-Xmaxerrs"); 149 options.add(maxInt); 150 151 ClassLoader orig = Thread.currentThread().getContextClassLoader(); 152 try { 153 Thread.currentThread().setContextClassLoader(ClasspathInfo.class.getClassLoader()); 156 JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 157 JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, options, null, Collections.<JavaFileObject>emptySet()); 158 Enter.register(task.getContext()); 159 return task; 160 } finally { 161 Thread.currentThread().setContextClassLoader(orig); 162 } 163 } 164 165 public int errorCount() { 166 return log.nerrors; 167 } 168 169 public int warningCount() { 170 return log.nwarnings; 171 } 172 173 public int sourcefileCount() { 174 return nfiles; 175 } 176 177 private boolean hasBeenUsed = false; 178 179 protected List<ClassSymbol> compile(List<String > filenames) throws Exception { 180 assert !hasBeenUsed : "attempt to reuse Builder"; 181 hasBeenUsed = true; 182 183 ListBuffer<ClassSymbol> classes = new ListBuffer<ClassSymbol>(); 184 try { 185 progressMonitor.setTotalSourceFiles(filenames.size()); 187 ListBuffer<CompilationUnitTree> trees = new ListBuffer<CompilationUnitTree>(); 188 for (JavaFileObject jfo : ((StandardJavaFileManager)fileManager).getJavaFileObjectsFromStrings(filenames)) { 189 trees.append(parse(jfo)); 190 progressMonitor.fileParsed(); 191 } 192 progressMonitor.parsingFinished(); 193 194 List<CompilationUnitTree> treeList = trees.toList(); 195 if (dumpAST) 196 dumpTrees(treeList, comments, "parse"); 197 198 if (errorCount() == 0) 200 attributeTrees(context, treeList, progressMonitor); 201 202 if (dumpAST) 203 dumpTrees(treeList, comments, "attr"); 204 } catch (Abort ex) { 205 } 206 207 return classes.toList(); 208 } 209 210 215 static void attributeTrees(Context context, java.util.List <CompilationUnitTree> roots, 216 BuildProgress progressMonitor) throws ReattributionException { 217 218 Log log = Log.instance(context); 219 Enter enter = (Enter)Enter.instance(context); 220 Todo todo = Todo.instance(context); 221 ASTService model = ASTService.instance(context); 222 model.setRoot(new RootTree(roots)); 223 224 progressMonitor.setTotalTrees(roots.size()); 226 ListBuffer<JCCompilationUnit> buf = new ListBuffer<JCCompilationUnit>(); 227 for (CompilationUnitTree t : roots) 228 buf.append((JCCompilationUnit)t); 229 try { 230 enter.main(buf.toList()); 231 } catch (IllegalArgumentException e) { 232 log.error(e.getLocalizedMessage()); 233 } 234 progressMonitor.enterFinished(); 235 236 if (log.nerrors == 0) { 237 progressMonitor.setTotalClasses(todo.length()); 238 Attr attr = Attr.instance(context); 239 while (todo.nonEmpty()) { 240 Env<AttrContext> env = todo.next(); 241 JavaFileObject classname = env.enclClass.sym.sourcefile; 242 log.useSource(classname); 243 try { 244 attr.attribClass(env.tree.pos(), env.enclClass.sym); 245 } catch (AssertionError e) { 246 System.err.println("Problem attributing " + env.toplevel.sourcefile); 248 } 249 progressMonitor.classAttributed(); 250 } 251 progressMonitor.attributionFinished(); 252 } 253 } 254 255 protected void close() { 256 } 257 258 261 protected JCCompilationUnit parse(JavaFileObject fileobject) { 262 try { 263 return parse(fileobject, fileobject.openInputStream()); 264 } catch (IOException e) { 265 log.error(Position.NOPOS, 266 "error.reading.file", fileobject, e); 267 } 268 return make.TopLevel(List.<JCAnnotation>nil(), null, List.<JCTree>nil()); 269 } 270 271 275 protected JCCompilationUnit parse(JavaFileObject filename, InputStream input) { 276 JavaFileObject prev = log.useSource(filename); 277 JCCompilationUnit tree = make.TopLevel(List.<JCAnnotation>nil(), null, List.<JCTree>nil()); 278 tree.sourcefile = filename; 279 if (input != null) { 280 try { 281 SourceBuffer sbuf = encoding != null ? 282 new SourceBuffer(input, encoding) : new SourceBuffer(input); 283 input.close(); 284 BufferRunQueue runs = new BufferRunQueue(); 285 Scanner scanner = (Scanner)scannerFactory.newScanner(sbuf, runs); 286 Parser parser = parserFactory.newParser(scanner, false, true); 287 tree = parser.compilationUnit(); 288 tree.sourcefile = filename; 289 if (tree.endPositions != null) 290 trees.setEndPosTable(filename, tree.endPositions); 291 tree.lineMap = scanner.getLineMap(); 292 comments.mapComments(tree, sbuf, runs); 293 } catch (IOException e) { 294 log.error(Position.NOPOS, 295 "error.reading.file", filename, e); 296 } 297 } 298 log.useSource(prev); 299 return tree; 300 } 301 302 310 public void complete(ClassSymbol c) throws CompletionFailure { 311 JCCompilationUnit tree; 312 JavaFileObject filename = c.classfile; 313 JavaFileObject prev = log.useSource(filename); 314 try { 315 tree = parse(filename); 316 } finally { 317 log.useSource(prev); 318 } 319 enter.complete(List.of(tree), c); 320 if (enter.getEnv(c) == null) { 321 String msg = log.getLocalizedString("file.doesnt.contain.class", 322 c.fullname); 323 throw new ClassReader.BadClassFile(c, filename, msg); 324 } 325 } 326 327 private void reportErrors() { 328 int errCount = errorCount(); 329 String errCountResource = 330 "count." + ((errCount == 1) ? "error" : "error.plural"); 331 Log.printLines(log.errWriter, 332 log.getLocalizedString(errCountResource, 333 Integer.toString(errCount))); 334 String warnCountResource = 335 "count." + ((errCount == 1) ? "warn" : "warn.plural"); 336 Log.printLines(log.errWriter, 337 log.getLocalizedString(warnCountResource, 338 Integer.toString(errCount))); 339 log.errWriter.flush(); 340 } 341 342 static void dumpTrees(java.util.List <CompilationUnitTree> trees, CommentHandler comments, String directory) { 343 logger.fine("dumping trees"); 344 File dumpDir = makeDumpDirectory(directory); 345 for (CompilationUnitTree tl : trees) { 346 File src = new File(tl.getSourceFile().toUri().getPath()); 347 File f = new File(dumpDir, src.getName()); 348 try { 349 FileOutputStream fout = new FileOutputStream(f); 350 PrintStream out = new PrintStream(new BufferedOutputStream(fout)); 351 DumpAST.dump(tl, comments, out); 352 out.flush(); 353 fout.close(); 354 } catch (IOException e) { 355 System.err.println("failed writing " + f.getPath() + ": " + e); 356 } 357 } 358 } 359 360 private static File makeDumpDirectory(String directory) { 361 File dir; 362 File tmp = null; 363 try { 364 tmp = File.createTempFile("HOHO", null); 365 dir = new File(tmp.getParentFile(), "jackpot-" + directory); 366 } catch(IOException ioe) { 367 dir = new File("/tmp/jackpot-" + directory); 368 } finally { 369 if (tmp != null) 370 tmp.delete(); 371 } 372 dir.mkdirs(); 373 return dir; 374 } 375 376 379 public static final SourceFileFilter sourceFileFilter = 380 new DefaultSourceFileFilter() { 381 public boolean acceptFile(String name) { 382 return super.acceptFile(name) && (name.endsWith(".java")); 383 } 384 public boolean acceptDirectory(String name) { 385 return super.acceptDirectory(name) && !name.equals("junk"); 386 } 387 }; 388 389 392 public static class ParserFactory extends Parser.Factory { 393 public static Parser.Factory instance(Context context) { 394 Parser.Factory instance = context.get(parserFactoryKey); 395 if (instance == null) 396 instance = new ParserFactory(context); 397 return instance; 398 } 399 400 protected ParserFactory(Context context) { 401 super(context); 402 } 403 404 public Parser newParser(Scanner S, 405 boolean keepDocComments, boolean genEndPos) { 406 return new EndPosParser(this, S, keepDocComments) { 407 protected StringBuffer foldStrings(JCTree tree) { 408 return null; 410 } 411 }; 412 } 413 } 414 } 415 | Popular Tags |