1 11 12 package org.eclipse.jdt.apt.core.internal.env; 13 14 import java.io.BufferedInputStream ; 15 import java.io.IOException ; 16 import java.io.InputStream ; 17 import java.io.InputStreamReader ; 18 import java.util.*; 19 20 import org.eclipse.core.resources.IFile; 21 import org.eclipse.core.resources.IMarker; 22 import org.eclipse.core.resources.IWorkspace; 23 import org.eclipse.core.resources.IWorkspaceRunnable; 24 import org.eclipse.core.runtime.CoreException; 25 import org.eclipse.core.runtime.IProgressMonitor; 26 import org.eclipse.core.runtime.IStatus; 27 import org.eclipse.jdt.apt.core.env.Phase; 28 import org.eclipse.jdt.apt.core.internal.AptPlugin; 29 import org.eclipse.jdt.apt.core.internal.declaration.EclipseMirrorObject; 30 import org.eclipse.jdt.apt.core.internal.declaration.TypeDeclarationImpl; 31 import org.eclipse.jdt.apt.core.internal.env.MessagerImpl.Severity; 32 import org.eclipse.jdt.apt.core.internal.util.Factory; 33 import org.eclipse.jdt.apt.core.internal.util.Visitors.AnnotatedNodeVisitor; 34 import org.eclipse.jdt.apt.core.internal.util.Visitors.AnnotationVisitor; 35 import org.eclipse.jdt.core.ICompilationUnit; 36 import org.eclipse.jdt.core.IJavaProject; 37 import org.eclipse.jdt.core.JavaCore; 38 import org.eclipse.jdt.core.compiler.CategorizedProblem; 39 import org.eclipse.jdt.core.compiler.BuildContext; 40 import org.eclipse.jdt.core.dom.*; 41 import com.sun.mirror.apt.Filer; 42 import com.sun.mirror.declaration.AnnotationTypeDeclaration; 43 import com.sun.mirror.declaration.PackageDeclaration; 44 import com.sun.mirror.declaration.TypeDeclaration; 45 46 public class BuildEnv extends AbstractCompilationEnv 47 { 48 private boolean _hasRaisedErrors = false; 49 50 private final BuildFilerImpl _filer; 51 52 56 private Set<String > _typeDependencies = new HashSet<String >(); 57 58 62 private boolean _batchMode = false; 64 69 private BuildContext[] _filesWithAnnotation = null; 70 71 75 private BuildContext[] _additionFiles = null; 76 83 private CompilationUnit[] _astRoots = null; 84 private List<MarkerInfo> _markerInfos = null; 85 86 94 BuildEnv( 95 final BuildContext[] filesWithAnnotations, 96 final BuildContext[] additionalFiles, 97 final IJavaProject javaProj) { 98 99 super(null, null, javaProj, Phase.BUILD); 100 _filer = new BuildFilerImpl(this); 101 _filesWithAnnotation = filesWithAnnotations; 102 _additionFiles = additionalFiles; 103 _problems = new ArrayList<APTProblem>(); 104 _markerInfos = new ArrayList<MarkerInfo>(); 105 106 if (AptPlugin.DEBUG_COMPILATION_ENV) AptPlugin.trace( 107 "constructed " + this + " for " + _filesWithAnnotation.length + " files"); } 109 110 public Filer getFiler() 111 { 112 checkValid(); 113 return _filer; 114 } 115 public PackageDeclaration getPackage(String name) 116 { 117 checkValid(); 118 return super.getPackage(name); 119 } 120 121 public TypeDeclaration getTypeDeclaration(String name) 122 { 123 checkValid(); 124 TypeDeclaration decl = super.getTypeDeclaration(name); 125 126 if (!_batchMode) 127 addTypeDependency(name); 128 129 return decl; 130 } 131 132 136 public boolean hasRaisedErrors(){ 137 return _hasRaisedErrors; 138 } 139 140 public static InputStreamReader getFileReader( final IFile file ) throws IOException , CoreException { 141 return new InputStreamReader (getInputStream(file), file.getCharset()); 142 } 143 144 public static InputStream getInputStream( final IFile file ) throws IOException , CoreException { 145 return new BufferedInputStream (file.getContents()); 146 } 147 148 152 public boolean hasGeneratedClassFiles(){ return _filer.hasGeneratedClassFile(); } 153 154 161 public void close(){ 162 if( isClosed() ) 163 return; 164 _markerInfos = null; 165 _astRoot = null; 166 _file = null; 167 _astRoots = null; 168 _filesWithAnnotation = null; 169 _problems = null; 170 _modelCompUnit2astCompUnit.clear(); 171 _hasRaisedErrors = false; 172 super.close(); 173 } 174 175 184 void addMessage(IFile resource, 185 int start, 186 int end, 187 Severity severity, 188 String msg, 189 int line, 190 String [] arguments) 191 { 192 checkValid(); 193 194 if( resource == null ) 195 resource = getFile(); 196 197 _hasRaisedErrors |= severity == MessagerImpl.Severity.ERROR; 198 199 if ( severity == Severity.INFO) { 201 StringBuilder sb = new StringBuilder (); 202 sb.append("Informational message reported by annotation processor:\n"); sb.append(msg); 204 sb.append("\n"); if (resource != null) { 206 sb.append("Resource="); sb.append(resource.getName()); 208 sb.append("; "); } 210 sb.append("starting offset="); sb.append(start); 212 sb.append("; ending offset="); sb.append(end); 214 sb.append("; line="); sb.append(line); 216 if (arguments != null) { 217 sb.append("; arguments:"); for (String s : arguments) { 219 sb.append("\n"); sb.append(s); 221 } 222 } 223 else { 224 sb.append("\n"); } 226 IStatus status = AptPlugin.createInfoStatus(null, sb.toString()); 227 AptPlugin.log(status); 228 return; 229 } 230 231 if( resource == null ){ 232 assert _batchMode : "not in batch mode but don't know about current resource"; addMarker(start, end, severity, msg, line, arguments); 234 } 235 else 236 addProblem(resource, start, end, severity, msg, line, arguments); 237 } 238 239 private void addProblem( 240 IFile resource, 241 int start, 242 int end, 243 Severity severity, 244 String msg, 245 int line, 246 String [] arguments) 247 { 248 249 APTProblem problem = createProblem(resource, start, end, severity, msg, line, arguments); 250 _problems.add(problem); 251 } 252 253 private void addMarker( 254 int start, 255 int end, 256 Severity severity, 257 String msg, 258 int line, 259 String [] arguments) 260 { 261 262 _markerInfos.add(new MarkerInfo(start, end, severity, msg, line)); 264 } 265 266 public Map<String , AnnotationTypeDeclaration> getAnnotationTypes() 267 { 268 checkValid(); 269 assert _astRoot != null && _file != null && !_batchMode : 270 "operation not available under batch mode."; return super.getAnnotationTypes(); 272 } 273 274 283 public Map<String , AnnotationTypeDeclaration> getAllAnnotationTypes( 284 final Map<BuildContext, Set<AnnotationTypeDeclaration>> file2Annotations) { 285 286 checkValid(); 287 if( _filesWithAnnotation == null ) 288 return getAnnotationTypes(); 289 290 final List<Annotation> instances = new ArrayList<Annotation>(); 291 final Map<String , AnnotationTypeDeclaration> decls = 292 new HashMap<String , AnnotationTypeDeclaration>(); 293 final AnnotationVisitor visitor = new AnnotationVisitor(instances); 294 for( int astIndex=0, len=_astRoots.length; astIndex<len; astIndex++ ){ 295 if( _astRoots == null || _astRoots[astIndex] == null ) 296 System.err.println(); 297 _astRoots[astIndex].accept(visitor); 298 final Set<AnnotationTypeDeclaration> perFileAnnos = new HashSet<AnnotationTypeDeclaration>(); 299 300 for (int instanceIndex=0, size = instances.size(); instanceIndex < size; instanceIndex++) { 301 final Annotation instance = instances.get(instanceIndex); 302 final ITypeBinding annoType = instance.resolveTypeBinding(); 303 if (annoType == null) 304 continue; 305 final TypeDeclarationImpl decl = 306 Factory.createReferenceType(annoType, this); 307 if (decl.kind() == EclipseMirrorObject.MirrorKind.TYPE_ANNOTATION){ 308 final AnnotationTypeDeclaration annoDecl = (AnnotationTypeDeclaration)decl; 309 decls.put(annoDecl.getQualifiedName(), annoDecl); 310 perFileAnnos.add(annoDecl); 311 } 312 } 313 if( file2Annotations != null && !perFileAnnos.isEmpty() ) 314 file2Annotations.put(_filesWithAnnotation[astIndex], perFileAnnos); 315 visitor.reset(); 316 } 317 318 return decls; 319 } 320 321 324 public Set<String > getTypeDependencies() { return _typeDependencies; } 325 326 331 public void beginBatchProcessing(){ 332 if( _phase != Phase.BUILD ) 333 throw new IllegalStateException ("No batch processing outside build."); 335 if( _batchMode ) return; 336 checkValid(); 337 338 _batchMode = true; 339 _file = null; 340 _astRoot = null; 341 } 342 343 public void completedBatchProcessing(){ 344 postMarkers(); 345 completedProcessing(); 346 } 347 348 void createASTs(BuildContext[] cpResults){ 349 final int len = cpResults.length; 350 final ICompilationUnit[] units = new ICompilationUnit[len]; 351 for( int i=0; i<len; i++ ){ 352 units[i] = JavaCore.createCompilationUnitFrom(cpResults[i].getFile()); 355 } 356 createASTs(_javaProject, units, _requestor = new CallbackRequestor(units)); 357 } 358 359 public void beginFileProcessing(BuildContext result){ 360 if( result == null ) 361 throw new IllegalStateException ("missing compilation result"); _batchMode = false; 363 final IFile file = result.getFile(); 364 if( file.equals(_file) ) return; 366 367 _astRoot = null; 368 _file = null; 369 370 if( _filesWithAnnotation != null ){ 372 for( int i=0, len=_filesWithAnnotation.length; i<len; i++ ){ 373 if( file.equals(_filesWithAnnotation[i].getFile()) ){ 374 _file = file; 375 _astRoot = _astRoots[i]; 376 } 377 } 378 } 379 380 if( _file == null || _astRoot == null) 381 throw new IllegalStateException ( 382 "file " + file.getName() + 384 " is not in the list to be processed."); } 386 387 public void completedFileProcessing(){ 388 completedProcessing(); 389 } 390 391 @Override 392 protected void completedProcessing(){ 393 _problems.clear(); 394 _typeDependencies.clear(); 395 super.completedProcessing(); 396 } 397 398 public List<? extends CategorizedProblem> getProblems(){ 399 if( !_problems.isEmpty() ) 400 EnvUtil.updateProblemLength(_problems, getAstCompilationUnit()); 401 return _problems; 402 } 403 404 public CompilationUnit getAST() 406 { 407 if( _batchMode ) 408 return null; 409 return _astRoot; 410 } 411 412 public void addTypeDependency(final String fullyQualifiedTypeName ) 413 { 414 if(!_batchMode){ 415 _typeDependencies.add( fullyQualifiedTypeName ); 416 } 417 } 418 420 425 @SuppressWarnings ("unchecked") 426 protected List<AbstractTypeDeclaration> searchLocallyForTypeDeclarations() 427 { 428 if( !_batchMode ) 429 return super.searchLocallyForTypeDeclarations(); 430 final List<AbstractTypeDeclaration> typeDecls = new ArrayList<AbstractTypeDeclaration>(); 431 for( int i=0, len=_astRoots.length; i<len; i++ ) 432 typeDecls.addAll( _astRoots[i].types() ); 433 434 getTypeDeclarationsFromAdditionFiles(typeDecls); 435 436 return typeDecls; 437 } 438 439 @SuppressWarnings ("unchecked") 440 private void getTypeDeclarationsFromAdditionFiles(List<AbstractTypeDeclaration> typeDecls){ 441 if( _additionFiles == null || _additionFiles.length == 0 ) return; 442 443 final int len = _additionFiles.length; 444 final ICompilationUnit[] units = new ICompilationUnit[len]; 445 for( int i=0; i<len; i++ ){ 446 units[i] = JavaCore.createCompilationUnitFrom(_additionFiles[i].getFile()); 449 } 450 BaseRequestor r = new BaseRequestor(units); 451 createASTs(_javaProject, units, r); 452 453 CompilationUnit[] asts = r.asts; 454 for( CompilationUnit ast : asts ){ 455 if( ast != null ){ 456 typeDecls.addAll( ast.types() ); 457 } 458 } 459 } 460 461 protected Map<ASTNode, List<Annotation>> getASTNodesWithAnnotations() 462 { 463 if( !_batchMode ) 464 return super.getASTNodesWithAnnotations(); 465 final Map<ASTNode, List<Annotation>> astNode2Anno = new HashMap<ASTNode, List<Annotation>>(); 466 final AnnotatedNodeVisitor visitor = new AnnotatedNodeVisitor(astNode2Anno); 467 for( int i=0, len=_astRoots.length; i<len; i++ ) 468 _astRoots[i].accept( visitor ); 469 return astNode2Anno; 470 } 471 472 protected IFile getFileForNode(final ASTNode node) 473 { 474 if( !_batchMode ) 475 return super.getFileForNode(node); 476 final CompilationUnit curAST = (CompilationUnit)node.getRoot(); 477 for( int i=0, len=_astRoots.length; i<len; i++ ){ 478 if( _astRoots[i] == curAST ) 479 return _filesWithAnnotation[i].getFile(); 480 } 481 throw new IllegalStateException (); 482 } 483 484 491 protected CompilationUnit searchLocallyForBinding(final IBinding binding) 492 { 493 if( !_batchMode ) 494 return super.searchLocallyForBinding(binding); 495 496 for( int i=0, len=_astRoots.length; i<len; i++ ){ 497 ASTNode node = _astRoots[i].findDeclaringNode(binding); 498 if( node != null) 499 return _astRoots[i]; 500 } 501 return null; 502 } 503 504 511 protected IFile searchLocallyForIFile(final IBinding binding) 512 { 513 if( !_batchMode ) 514 return super.searchLocallyForIFile(binding); 515 516 for( int i=0, len=_astRoots.length; i<len; i++ ){ 517 ASTNode node = _astRoots[i].findDeclaringNode(binding); 518 if( node != null) 519 return _filesWithAnnotation[i].getFile(); 520 } 521 return null; 522 } 523 524 530 public CompilationUnit getASTFrom(final IFile file) 531 { 532 if( file == null ) 533 return null; 534 else if( file.equals(_file) ) 535 return _astRoot; 536 else if( _astRoots != null ){ 537 for( int i=0, len=_filesWithAnnotation.length; i<len; i++ ){ 538 if( file.equals(_filesWithAnnotation[i].getFile()) ) 539 return _astRoots[i]; 540 } 541 } 542 return null; 543 } 544 545 550 protected AST getCurrentDietAST(){ 551 552 if( _astRoot != null ) 553 return _astRoot.getAST(); 554 else{ 555 if( _astRoots == null ) 556 throw new IllegalStateException ("no AST is available"); return _astRoots[0].getAST(); 558 } 559 } 560 561 void postMarkers() 562 { 563 if( _markerInfos == null || _markerInfos.size() == 0 ) 564 return; 565 try{ 568 final IWorkspaceRunnable runnable = new IWorkspaceRunnable(){ 569 public void run(IProgressMonitor monitor) 570 { 571 for( MarkerInfo markerInfo : _markerInfos ){ 572 try{ 573 final IMarker marker = _javaProject.getProject().createMarker(AptPlugin.APT_BATCH_PROCESSOR_PROBLEM_MARKER); 574 markerInfo.copyIntoMarker(marker); 575 } 576 catch(CoreException e){ 577 AptPlugin.log(e, "Failure posting markers"); } 579 } 580 } 581 }; 582 IWorkspace ws = _javaProject.getProject().getWorkspace(); 583 ws.run(runnable, null); 584 } 585 catch(CoreException e){ 586 AptPlugin.log(e, "Failed to post markers"); } 588 finally{ 589 _markerInfos.clear(); 590 } 591 } 592 593 public BuildContext[] getFilesWithAnnotation() 594 { 595 return _filesWithAnnotation; 596 } 597 598 public BuildContext[] getFilesWithoutAnnotation() 599 { 600 return _additionFiles; 601 } 602 603 private class CallbackRequestor extends BaseRequestor { 604 CallbackRequestor(ICompilationUnit[] parseUnits) { 605 super(parseUnits); 606 } 607 public void acceptBinding(String bindingKey, IBinding binding) { 608 _astRoots = asts; 611 _callback.run(BuildEnv.this); 612 } 613 } 614 615 } 616 | Popular Tags |