compilationunit.java
来自「Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业」· Java 代码 · 共 1,012 行 · 第 1/3 页
JAVA
1,012 行
ClassNode cn = (ClassNode) suClassesIter.next();
if (!first) {
message.append(", ");
} else {
first=false;
}
message.append(cn.getName());
}
}
getErrorCollector().addErrorAndContinue(
new SimpleMessage(message.toString(),CompilationUnit.this)
);
iter.remove();
}
}
}
};
/**
* Runs classgen() on a single ClassNode.
*/
private PrimaryClassNodeOperation classgen = new PrimaryClassNodeOperation() {
public boolean needSortedInput() {
return true;
}
public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
//
// Run the Verifier on the outer class
//
try {
verifier.visitClass(classNode);
} catch (GroovyRuntimeException rpe) {
ASTNode node = rpe.getNode();
getErrorCollector().addError(
new SyntaxException(rpe.getMessage(),null,node.getLineNumber(),node.getColumnNumber()),
source
);
}
LabelVerifier lv = new LabelVerifier(source);
lv.visitClass(classNode);
ClassCompletionVerifier completionVerifier = new ClassCompletionVerifier(source);
completionVerifier.visitClass(classNode);
// because the class may be generated even if a error was found
// and that class may have an invalid format we fail here if needed
getErrorCollector().failIfErrors();
//
// Prep the generator machinery
//
ClassVisitor visitor = createClassVisitor();
String sourceName = (source == null ? classNode.getModule().getDescription() : source.getName());
// only show the file name and its extension like javac does in its stacktraces rather than the full path
// also takes care of both \ and / depending on the host compiling environment
if (sourceName != null)
sourceName = sourceName.substring(Math.max(sourceName.lastIndexOf('\\'), sourceName.lastIndexOf('/')) + 1);
ClassGenerator generator = new AsmClassGenerator(context, visitor, classLoader, sourceName);
//
// Run the generation and create the class (if required)
//
generator.visitClass(classNode);
byte[] bytes = ((ClassWriter) visitor).toByteArray();
generatedClasses.add(new GroovyClass(classNode.getName(), bytes));
//
// Handle any callback that's been set
//
if (CompilationUnit.this.classgenCallback != null) {
classgenCallback.call(visitor, classNode);
}
//
// Recurse for inner classes
//
LinkedList innerClasses = generator.getInnerClasses();
while (!innerClasses.isEmpty()) {
classgen.call(source, context, (ClassNode) innerClasses.removeFirst());
}
}
};
protected ClassVisitor createClassVisitor() {
return new ClassWriter(true);
}
//---------------------------------------------------------------------------
// PHASE HANDLING
/**
* Updates the phase marker on all sources.
*/
protected void mark() throws CompilationFailedException {
applyToSourceUnits(mark);
}
/**
* Marks a single SourceUnit with the current phase,
* if it isn't already there yet.
*/
private SourceUnitOperation mark = new SourceUnitOperation() {
public void call(SourceUnit source) throws CompilationFailedException {
if (source.phase < phase) {
source.gotoPhase(phase);
}
if (source.phase == phase && phaseComplete && !source.phaseComplete) {
source.completePhase();
}
}
};
//---------------------------------------------------------------------------
// LOOP SIMPLIFICATION FOR SourceUnit OPERATIONS
/**
* An callback interface for use in the applyToSourceUnits loop driver.
*/
public static abstract class SourceUnitOperation {
public abstract void call(SourceUnit source) throws CompilationFailedException;
}
/**
* A loop driver for applying operations to all SourceUnits.
* Automatically skips units that have already been processed
* through the current phase.
*/
public void applyToSourceUnits(SourceUnitOperation body) throws CompilationFailedException {
Iterator keys = names.iterator();
while (keys.hasNext()) {
String name = (String) keys.next();
SourceUnit source = (SourceUnit) sources.get(name);
if ( (source.phase < phase) || (source.phase == phase && !source.phaseComplete)) {
try {
body.call(source);
} catch (CompilationFailedException e) {
throw e;
} catch (Exception e) {
GroovyBugError gbe = new GroovyBugError(e);
changeBugText(gbe,source);
throw gbe;
} catch (GroovyBugError e) {
changeBugText(e,source);
throw e;
}
}
}
getErrorCollector().failIfErrors();
}
//---------------------------------------------------------------------------
// LOOP SIMPLIFICATION FOR PRIMARY ClassNode OPERATIONS
/**
* An callback interface for use in the applyToSourceUnits loop driver.
*/
public static abstract class PrimaryClassNodeOperation {
public abstract void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException;
public boolean needSortedInput(){
return false;
}
}
public static abstract class GroovyClassOperation {
public abstract void call(GroovyClass gclass) throws CompilationFailedException;
}
private List getPrimaryClassNodes(boolean sort) {
ArrayList unsorted = new ArrayList();
Iterator modules = this.ast.getModules().iterator();
while (modules.hasNext()) {
ModuleNode module = (ModuleNode) modules.next();
Iterator classNodes = module.getClasses().iterator();
while (classNodes.hasNext()) {
ClassNode classNode = (ClassNode) classNodes.next();
unsorted.add(classNode);
}
}
if(sort==false) return unsorted;
int[] indexClass = new int[unsorted.size()];
int[] indexInterface = new int[unsorted.size()];
{
int i = 0;
for (Iterator iter = unsorted.iterator(); iter.hasNext(); i++) {
ClassNode node = (ClassNode) iter.next();
int count = 0;
ClassNode element = node;
while (element!=null){
count++;
element = element.getSuperClass();
}
if (node.isInterface()) {
indexInterface[i] = count;
indexClass[i] = -1;
} else {
indexClass[i] = count;
indexInterface[i] = -1;
}
}
}
List sorted = getSorted(indexInterface,unsorted);
sorted.addAll(getSorted(indexClass,unsorted));
return sorted;
}
private List getSorted(int[] index, List unsorted) {
ArrayList sorted = new ArrayList(unsorted.size());
int start = 0;
for (int i=0; i<unsorted.size(); i++) {
int min = -1;
for (int j=0; j<unsorted.size(); j++) {
if (index[j]==-1) continue;
if (min==-1) {
min = j;
} else if (index[j]<index[min]) {
min = j;
}
}
if (min==-1) break;
sorted.add(unsorted.get(min));
index[min] = -1;
}
return sorted;
}
/**
* A loop driver for applying operations to all primary ClassNodes in
* our AST. Automatically skips units that have already been processed
* through the current phase.
*/
public void applyToPrimaryClassNodes(PrimaryClassNodeOperation body) throws CompilationFailedException {
Iterator classNodes = getPrimaryClassNodes(body.needSortedInput()).iterator();
while (classNodes.hasNext()) {
SourceUnit context=null;
try {
ClassNode classNode = (ClassNode) classNodes.next();
context = classNode.getModule().getContext();
if (context == null || context.phase <= phase) {
body.call(context, new GeneratorContext(this.ast), classNode);
}
} catch (CompilationFailedException e) {
// fall thorugh, getErrorREporter().failIfErrors() will triger
} catch (NullPointerException npe){
throw npe;
} catch (GroovyBugError e) {
changeBugText(e,context);
throw e;
} catch (Exception e) {
// check the exception for a nested compilation exception
ErrorCollector nestedCollector = null;
for (Throwable next = e.getCause(); next!=e && next!=null; next=next.getCause()) {
if (!(next instanceof MultipleCompilationErrorsException)) continue;
MultipleCompilationErrorsException mcee = (MultipleCompilationErrorsException) next;
nestedCollector = mcee.collector;
break;
}
if (nestedCollector!=null) {
getErrorCollector().addCollectorContents(nestedCollector);
} else {
getErrorCollector().addError(new ExceptionMessage(e,configuration.getDebug(),this));
}
}
}
getErrorCollector().failIfErrors();
}
public void applyToGeneratedGroovyClasses(GroovyClassOperation body) throws CompilationFailedException {
if (this.phase != Phases.OUTPUT && !(this.phase == Phases.CLASS_GENERATION && this.phaseComplete)) {
throw new GroovyBugError("CompilationUnit not ready for output(). Current phase="+getPhaseDescription());
}
boolean failures = false;
Iterator iterator = this.generatedClasses.iterator();
while (iterator.hasNext()) {
//
// Get the class and calculate its filesystem name
//
GroovyClass gclass = (GroovyClass) iterator.next();
try {
body.call(gclass);
} catch (CompilationFailedException e) {
// fall thorugh, getErrorREporter().failIfErrors() will triger
} catch (NullPointerException npe){
throw npe;
} catch (GroovyBugError e) {
changeBugText(e,null);
throw e;
} catch (Exception e) {
GroovyBugError gbe = new GroovyBugError(e);
throw gbe;
}
}
getErrorCollector().failIfErrors();
}
private void changeBugText(GroovyBugError e, SourceUnit context) {
e.setBugText("exception in phase '"+getPhaseDescription()+"' in source unit '"+((context!=null)?context.getName():"?")+"' "+e.getBugText());
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?