@Override public void process(CompilationUnitDeclaration cud, int i) { super.process(cud, i); ClassFile[] classFiles = cud.compilationResult().getClassFiles(); Map<ClassFile, CompiledClass> results = new LinkedHashMap<ClassFile, CompiledClass>(); for (ClassFile classFile : classFiles) { createCompiledClass(classFile, results); } List<CompiledClass> compiledClasses = new ArrayList<CompiledClass>(results.values()); addBinaryTypes(compiledClasses); ICompilationUnit icu = cud.compilationResult().compilationUnit; Adapter adapter = (Adapter) icu; CompilationUnitBuilder builder = adapter.getBuilder(); // TODO this code was added for the arquillian gwt extension if (cud.types != null) { for (TypeDeclaration type : cud.types) { if (type.methods != null) { if (isAnnotationPresent(RunWith.class.getSimpleName(), type.annotations)) { Set<AbstractMethodDeclaration> filteredMethods = new HashSet<AbstractMethodDeclaration>(); boolean match = false; for (AbstractMethodDeclaration decl : type.methods) { if (decl.annotations != null) { // TODO make this configurable if ((isAnnotationPresent(RunAsGwtClient.class.getSimpleName(), decl.annotations) || isAnnotationPresent( RunAsGwtClient.class.getSimpleName(), type.annotations)) && !isAnnotationPresent(Deployment.class.getSimpleName(), decl.annotations)) { filteredMethods.add(decl); } else { match = true; System.out.println("Ignoring non-translatable method:\n" + decl.toString()); } } } if (match) { type.methods = filteredMethods.toArray(new AbstractMethodDeclaration[filteredMethods.size()]); } } } } } processor.process(builder, cud, compiledClasses); }
/** Process a compilation unit already parsed and build. */ public void process(CompilationUnitDeclaration unit, int i) { this.lookupEnvironment.unitBeingCompleted = unit; long parseStart = System.currentTimeMillis(); this.parser.getMethodBodies(unit); long resolveStart = System.currentTimeMillis(); this.stats.parseTime += resolveStart - parseStart; // fault in fields & methods if (unit.scope != null) unit.scope.faultInTypes(); // verify inherited methods if (unit.scope != null) unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier()); // type checking unit.resolve(); long analyzeStart = System.currentTimeMillis(); this.stats.resolveTime += analyzeStart - resolveStart; // No need of analysis or generation of code if statements are not required if (!this.options.ignoreMethodBodies) unit.analyseCode(); // flow analysis long generateStart = System.currentTimeMillis(); this.stats.analyzeTime += generateStart - analyzeStart; if (!this.options.ignoreMethodBodies) unit.generateCode(); // code generation // reference info if (this.options.produceReferenceInfo && unit.scope != null) unit.scope.storeDependencyInfo(); // finalize problems (suppressWarnings) unit.finalizeProblems(); this.stats.generateTime += System.currentTimeMillis() - generateStart; // refresh the total number of units known at this stage unit.compilationResult.totalUnitsKnown = this.totalUnits; this.lookupEnvironment.unitBeingCompleted = null; }
/** * Add an additional compilation unit into the loop -> build compilation unit declarations, their * bindings and record their results. */ public void accept(ICompilationUnit sourceUnit, AccessRestriction accessRestriction) { // Switch the current policy and compilation result for this unit to the requested one. CompilationResult unitResult = new CompilationResult( sourceUnit, this.totalUnits, this.totalUnits, this.options.maxProblemsPerUnit); unitResult.checkSecondaryTypes = true; try { if (this.options.verbose) { String count = String.valueOf(this.totalUnits + 1); this.out.println( Messages.bind( Messages.compilation_request, new String[] {count, count, new String(sourceUnit.getFileName())})); } // diet parsing for large collection of unit CompilationUnitDeclaration parsedUnit; if (this.totalUnits < this.parseThreshold) { parsedUnit = this.parser.parse(sourceUnit, unitResult); } else { parsedUnit = this.parser.dietParse(sourceUnit, unitResult); } parsedUnit.bits |= ASTNode.IsImplicitUnit; // initial type binding creation this.lookupEnvironment.buildTypeBindings(parsedUnit, accessRestriction); addCompilationUnit(sourceUnit, parsedUnit); // binding resolution this.lookupEnvironment.completeTypeBindings(parsedUnit); } catch (AbortCompilationUnit e) { // at this point, currentCompilationUnitResult may not be sourceUnit, but some other // one requested further along to resolve sourceUnit. if (unitResult.compilationUnit == sourceUnit) { // only report once this.requestor.acceptResult(unitResult.tagAsAccepted()); } else { throw e; // want to abort enclosing request to compile } } }
@Override public void process( CompilationUnitBuilder builder, CompilationUnitDeclaration cud, List<CompiledClass> compiledClasses) { builder .setClasses(compiledClasses) .setTypes(Collections.<JDeclaredType>emptyList()) .setDependencies(new Dependencies()) .setJsniMethods(Collections.<JsniMethod>emptyList()) .setMethodArgs(new MethodArgNamesLookup()) .setProblems(cud.compilationResult().getProblems()); results.add(builder.build()); }
/** * Internal API used to resolve a given compilation unit. Can run a subset of the compilation * process */ public CompilationUnitDeclaration resolve( CompilationUnitDeclaration unit, ICompilationUnit sourceUnit, boolean verifyMethods, boolean analyzeCode, boolean generateCode) { try { if (unit == null) { // build and record parsed units this.parseThreshold = 0; // will request a full parse beginToCompile(new ICompilationUnit[] {sourceUnit}); // process all units (some more could be injected in the loop by the lookup environment) unit = this.unitsToProcess[0]; } else { // initial type binding creation this.lookupEnvironment.buildTypeBindings(unit, null /*no access restriction*/); // binding resolution this.lookupEnvironment.completeTypeBindings(); } this.lookupEnvironment.unitBeingCompleted = unit; this.parser.getMethodBodies(unit); if (unit.scope != null) { // fault in fields & methods unit.scope.faultInTypes(); if (unit.scope != null && verifyMethods) { // http://dev.eclipse.org/bugs/show_bug.cgi?id=23117 // verify inherited methods unit.scope.verifyMethods(this.lookupEnvironment.methodVerifier()); } // type checking unit.resolve(); // flow analysis if (analyzeCode) unit.analyseCode(); // code generation if (generateCode) unit.generateCode(); // finalize problems (suppressWarnings) unit.finalizeProblems(); } if (this.unitsToProcess != null) this.unitsToProcess[0] = null; // release reference to processed unit declaration this.requestor.acceptResult(unit.compilationResult.tagAsAccepted()); return unit; } catch (AbortCompilation e) { this.handleInternalException(e, unit); return unit == null ? this.unitsToProcess[0] : unit; } catch (Error e) { this.handleInternalException(e, unit, null); throw e; // rethrow } catch (RuntimeException e) { this.handleInternalException(e, unit, null); throw e; // rethrow } finally { // leave this.lookupEnvironment.unitBeingCompleted set to the unit, until another unit is // resolved // other calls to dom can cause classpath errors to be detected, resulting in AbortCompilation // exceptions // No reset is performed there anymore since, // within the CodeAssist (or related tools), // the compiler may be called *after* a call // to this resolve(...) method. And such a call // needs to have a compiler with a non-empty // environment. // this.reset(); } }
/** * General API -> compile each of supplied files -> recompile any required types for which we have * an incomplete principle structure */ public void compile(ICompilationUnit[] sourceUnits) { this.stats.startTime = System.currentTimeMillis(); // GROOVY start // sort the sourceUnits - java first! might be temporary, hmmm if (this.options.buildGroovyFiles == 2) { int groovyFileIndex = -1; // System.out.println("before"); // for (int u=0,max=sourceUnits.length;u<max;u++) { // System.out.println(sourceUnits[u].getFileName()); // } for (int u = 0, max = sourceUnits.length; u < max; u++) { char[] fn = sourceUnits[u].getFileName(); boolean isDotJava = fn[fn.length - 1] == 'a'; // a means .java if (isDotJava) { if (groovyFileIndex != -1) { // swap them! ICompilationUnit swap = sourceUnits[groovyFileIndex]; sourceUnits[groovyFileIndex] = sourceUnits[u]; sourceUnits[u] = swap; // find the next .groovy file after the groovyFileIndex (worst case it will be 'u') int newGroovyFileIndex = -1; for (int g = groovyFileIndex; g <= u; g++) { char[] fn2 = sourceUnits[g].getFileName(); boolean isDotGroovy = fn2[fn2.length - 1] == 'm'; // ZALUUM if (isDotGroovy) { newGroovyFileIndex = g; break; } } groovyFileIndex = newGroovyFileIndex; } } else { if (groovyFileIndex == -1) { groovyFileIndex = u; } } } // System.out.println("after"); // for (int u=0,max=sourceUnits.length;u<max;u++) { // System.out.println(sourceUnits[u].getFileName()); // } } // GROOVY end CompilationUnitDeclaration unit = null; ProcessTaskManager processingTask = null; try { // build and record parsed units reportProgress(Messages.compilation_beginningToCompile); if (this.annotationProcessorManager == null) { beginToCompile(sourceUnits); } else { ICompilationUnit[] originalUnits = (ICompilationUnit[]) sourceUnits.clone(); // remember source units in case a source type collision occurs try { beginToCompile(sourceUnits); processAnnotations(); if (!this.options.generateClassFiles) { // -proc:only was set on the command line return; } } catch (SourceTypeCollisionException e) { reset(); // a generated type was referenced before it was created // the compiler either created a MissingType or found a BinaryType for it // so add the processor's generated files & start over, // but remember to only pass the generated files to the annotation processor int originalLength = originalUnits.length; int newProcessedLength = e.newAnnotationProcessorUnits.length; ICompilationUnit[] combinedUnits = new ICompilationUnit[originalLength + newProcessedLength]; System.arraycopy(originalUnits, 0, combinedUnits, 0, originalLength); System.arraycopy( e.newAnnotationProcessorUnits, 0, combinedUnits, originalLength, newProcessedLength); this.annotationProcessorStartIndex = originalLength; compile(combinedUnits); return; } } if (this.useSingleThread) { // process all units (some more could be injected in the loop by the lookup environment) for (int i = 0; i < this.totalUnits; i++) { unit = this.unitsToProcess[i]; reportProgress( Messages.bind(Messages.compilation_processing, new String(unit.getFileName()))); try { if (this.options.verbose) this.out.println( Messages.bind( Messages.compilation_process, new String[] { String.valueOf(i + 1), String.valueOf(this.totalUnits), new String(this.unitsToProcess[i].getFileName()) })); process(unit, i); } finally { // cleanup compilation unit result unit.cleanUp(); } this.unitsToProcess[i] = null; // release reference to processed unit declaration reportWorked(1, i); this.stats.lineCount += unit.compilationResult.lineSeparatorPositions.length; long acceptStart = System.currentTimeMillis(); this.requestor.acceptResult(unit.compilationResult.tagAsAccepted()); this.stats.generateTime += System.currentTimeMillis() - acceptStart; // record accept time as part of generation if (this.options.verbose) this.out.println( Messages.bind( Messages.compilation_done, new String[] { String.valueOf(i + 1), String.valueOf(this.totalUnits), new String(unit.getFileName()) })); } } else { processingTask = new ProcessTaskManager(this); int acceptedCount = 0; // process all units (some more could be injected in the loop by the lookup environment) // the processTask can continue to process units until its fixed sized cache is full then it // must wait // for this this thread to accept the units as they appear (it only waits if no units are // available) while (true) { try { unit = processingTask.removeNextUnit(); // waits if no units are in the processed queue } catch (Error e) { unit = processingTask.unitToProcess; throw e; } catch (RuntimeException e) { unit = processingTask.unitToProcess; throw e; } if (unit == null) break; reportWorked(1, acceptedCount++); this.stats.lineCount += unit.compilationResult.lineSeparatorPositions.length; this.requestor.acceptResult(unit.compilationResult.tagAsAccepted()); if (this.options.verbose) this.out.println( Messages.bind( Messages.compilation_done, new String[] { String.valueOf(acceptedCount), String.valueOf(this.totalUnits), new String(unit.getFileName()) })); } } } catch (AbortCompilation e) { this.handleInternalException(e, unit); } catch (Error e) { this.handleInternalException(e, unit, null); throw e; // rethrow } catch (RuntimeException e) { this.handleInternalException(e, unit, null); throw e; // rethrow } finally { if (processingTask != null) { processingTask.shutdown(); processingTask = null; } reset(); this.annotationProcessorStartIndex = 0; this.stats.endTime = System.currentTimeMillis(); } if (this.options.verbose) { if (this.totalUnits > 1) { this.out.println( Messages.bind(Messages.compilation_units, String.valueOf(this.totalUnits))); } else { this.out.println(Messages.bind(Messages.compilation_unit, String.valueOf(this.totalUnits))); } } }
public ArrayList<String> collectApiRefs(final CompilationUnitDeclaration cud) { final Set<String> apiRefs = new HashSet<String>(); class DependencyVisitor extends TypeRefVisitor { public DependencyVisitor() { super(cud); } @Override public boolean visit(Argument arg, BlockScope scope) { // Adapted from {@link Argument#traverse}. // Don't visit annotations. if (arg.type != null) { arg.type.traverse(this, scope); } return false; } @Override public boolean visit(Argument arg, ClassScope scope) { // Adapted from {@link Argument#traverse}. // Don't visit annotations. if (arg.type != null) { arg.type.traverse(this, scope); } return false; } @Override public boolean visit(Block block, BlockScope scope) { assert false : "Error in DepedencyVisitor; should never visit a block"; return false; } @Override public boolean visit(Clinit clinit, ClassScope scope) { return false; } @Override public boolean visit(ConstructorDeclaration ctor, ClassScope scope) { if (ctor.typeParameters != null) { int typeParametersLength = ctor.typeParameters.length; for (int i = 0; i < typeParametersLength; i++) { ctor.typeParameters[i].traverse(this, ctor.scope); } } traverse(ctor); return false; } @Override public boolean visit(FieldDeclaration fieldDeclaration, MethodScope scope) { // Don't visit javadoc. // Don't visit annotations. if (fieldDeclaration.type != null) { fieldDeclaration.type.traverse(this, scope); } // Don't visit initialization. return false; } @Override public boolean visit(Initializer initializer, MethodScope scope) { return false; } @Override public boolean visit(MethodDeclaration meth, ClassScope scope) { if (meth.typeParameters != null) { int typeParametersLength = meth.typeParameters.length; for (int i = 0; i < typeParametersLength; i++) { meth.typeParameters[i].traverse(this, meth.scope); } } if (meth.returnType != null) { meth.returnType.traverse(this, meth.scope); } traverse(meth); return false; } @Override public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) { traverse(typeDeclaration); return false; } @Override public boolean visit(TypeDeclaration typeDeclaration, CompilationUnitScope scope) { traverse(typeDeclaration); return false; } @Override protected void onBinaryTypeRef( BinaryTypeBinding referencedType, CompilationUnitDeclaration unitOfReferrer, Expression expression) { if (!String.valueOf(referencedType.getFileName()).endsWith(".java")) { // ignore binary-only annotations return; } addReference(referencedType); } @Override protected void onTypeRef( SourceTypeBinding referencedType, CompilationUnitDeclaration unitOfReferrer) { addReference(referencedType); } private void addReference(ReferenceBinding referencedType) { String binaryName = CharOperation.toString(referencedType.compoundName); apiRefs.add(BinaryName.toSourceName(binaryName)); } /** Adapted from {@link MethodDeclaration#traverse}. */ private void traverse(AbstractMethodDeclaration meth) { // Don't visit javadoc. // Don't visit annotations. if (meth.arguments != null) { int argumentLength = meth.arguments.length; for (int i = 0; i < argumentLength; i++) { meth.arguments[i].traverse(this, meth.scope); } } if (meth.thrownExceptions != null) { int thrownExceptionsLength = meth.thrownExceptions.length; for (int i = 0; i < thrownExceptionsLength; i++) { meth.thrownExceptions[i].traverse(this, meth.scope); } } // Don't visit method bodies. } /** Adapted from {@link TypeDeclaration#traverse}. */ private void traverse(TypeDeclaration type) { // Don't visit javadoc. // Don't visit annotations. if (type.superclass != null) { type.superclass.traverse(this, type.scope); } if (type.superInterfaces != null) { int length = type.superInterfaces.length; for (int i = 0; i < length; i++) { type.superInterfaces[i].traverse(this, type.scope); } } if (type.typeParameters != null) { int length = type.typeParameters.length; for (int i = 0; i < length; i++) { type.typeParameters[i].traverse(this, type.scope); } } if (type.memberTypes != null) { int length = type.memberTypes.length; for (int i = 0; i < length; i++) { type.memberTypes[i].traverse(this, type.scope); } } if (type.fields != null) { int length = type.fields.length; for (int i = 0; i < length; i++) { FieldDeclaration field; if ((field = type.fields[i]).isStatic()) { field.traverse(this, type.staticInitializerScope); } else { field.traverse(this, type.initializerScope); } } } if (type.methods != null) { int length = type.methods.length; for (int i = 0; i < length; i++) { type.methods[i].traverse(this, type.scope); } } } } DependencyVisitor visitor = new DependencyVisitor(); cud.traverse(visitor, cud.scope); ArrayList<String> result = new ArrayList<String>(apiRefs); Collections.sort(result); return result; }