Java源码示例:org.codehaus.groovy.classgen.Verifier
示例1
public void compileToDir(ScriptSource source, ClassLoader classLoader, File classesDir,
Transformer transformer, Class<? extends Script> scriptBaseClass, Verifier verifier) {
Clock clock = new Clock();
GFileUtils.deleteDirectory(classesDir);
GFileUtils.mkdirs(classesDir);
CompilerConfiguration configuration = createBaseCompilerConfiguration(scriptBaseClass);
configuration.setTargetDirectory(classesDir);
try {
compileScript(source, classLoader, configuration, classesDir, transformer, verifier);
} catch (GradleException e) {
GFileUtils.deleteDirectory(classesDir);
throw e;
}
logger.debug("Timing: Writing script to cache at {} took: {}", classesDir.getAbsolutePath(),
clock.getTime());
}
示例2
public <T extends Script> Class<? extends T> compile(ScriptSource source, ClassLoader classLoader, Transformer transformer, Class<T> scriptBaseClass, Verifier verifier) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("source.filename", source.getFileName());
properties.put("source.hash", HashUtil.createCompactMD5(source.getResource().getText()));
String cacheName = String.format("scripts/%s/%s/%s", source.getClassName(), scriptBaseClass.getSimpleName(), transformer.getId());
PersistentCache cache = cacheRepository.cache(cacheName)
.withProperties(properties)
.withValidator(validator)
.withDisplayName(String.format("%s class cache for %s", transformer.getId(), source.getDisplayName()))
.withInitializer(new ProgressReportingInitializer(progressLoggerFactory, new CacheInitializer(source, classLoader, transformer, verifier, scriptBaseClass)))
.open();
// This isn't quite right. The cache will be closed at the end of the build, releasing the shared lock on the classes. Instead, the cache for a script should be
// closed once we no longer require the script classes. This may be earlier than the end of the current build, or it may used across multiple builds
caches.add(cache);
File classesDir = classesDir(cache);
return scriptCompilationHandler.loadFromDir(source, classLoader, classesDir, scriptBaseClass);
}
示例3
public void compileToDir(ScriptSource source, ClassLoader classLoader, File classesDir,
Transformer transformer, Class<? extends Script> scriptBaseClass, Verifier verifier) {
Clock clock = new Clock();
GFileUtils.deleteDirectory(classesDir);
GFileUtils.mkdirs(classesDir);
CompilerConfiguration configuration = createBaseCompilerConfiguration(scriptBaseClass);
configuration.setTargetDirectory(classesDir);
try {
compileScript(source, classLoader, configuration, classesDir, transformer, verifier);
} catch (GradleException e) {
GFileUtils.deleteDirectory(classesDir);
throw e;
}
logger.debug("Timing: Writing script to cache at {} took: {}", classesDir.getAbsolutePath(),
clock.getTime());
}
示例4
public <T extends Script> Class<? extends T> compile(ScriptSource source, ClassLoader classLoader, Transformer transformer, Class<T> scriptBaseClass, Verifier verifier) {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("source.filename", source.getFileName());
properties.put("source.hash", HashUtil.createCompactMD5(source.getResource().getText()));
String cacheName = String.format("scripts/%s/%s/%s", source.getClassName(), scriptBaseClass.getSimpleName(), transformer.getId());
PersistentCache cache = cacheRepository.cache(cacheName)
.withProperties(properties)
.withValidator(validator)
.withDisplayName(String.format("%s class cache for %s", transformer.getId(), source.getDisplayName()))
.withInitializer(new ProgressReportingInitializer(progressLoggerFactory, new CacheInitializer(source, classLoader, transformer, verifier, scriptBaseClass)))
.open();
// This isn't quite right. The cache will be closed at the end of the build, releasing the shared lock on the classes. Instead, the cache for a script should be
// closed once we no longer require the script classes. This may be earlier than the end of the current build, or it may used across multiple builds
caches.add(cache);
File classesDir = classesDir(cache);
return scriptCompilationHandler.loadFromDir(source, classLoader, classesDir, scriptBaseClass);
}
示例5
@Override
public void visitPropertyExpression(final PropertyExpression exp) {
// TODO: spread
if (exp.getObjectExpression() instanceof VariableExpression && ((VariableExpression) exp.getObjectExpression()).isThisExpression() &&
exp.getProperty() instanceof ConstantExpression && classNode.getSetterMethod("set" + Verifier.capitalize((String) ((ConstantExpression) exp.getProperty()).getValue()), false) != null) {
makeNode("attribute", new Runnable() {
@Override
public void run() {
loc(exp);
visit(exp.getObjectExpression());
visit(exp.getProperty());
literal(exp.isSafe());
}
});
} else {
makeNode("property", new Runnable() {
@Override
public void run() {
loc(exp);
visit(exp.getObjectExpression());
visit(exp.getProperty());
literal(exp.isSafe());
}
});
}
}
示例6
public <T extends Script> Class<? extends T> compile(ScriptSource source, ClassLoader classLoader, Transformer transformer, Class<T> scriptBaseClass, Verifier verifier) {
List<Object> key = Arrays.asList(source.getClassName(), classLoader, transformer.getId(), scriptBaseClass.getName());
Class<?> c = cachedClasses.get(key);
if (c == null) {
c = scriptClassCompiler.compile(source, classLoader, transformer, scriptBaseClass, verifier);
cachedClasses.put(key, c);
}
return c.asSubclass(scriptBaseClass);
}
示例7
private CacheInitializer(ScriptSource source, ClassLoader classLoader, Transformer transformer, Verifier verifier, Class<? extends Script> scriptBaseClass) {
this.source = source;
this.classLoader = classLoader;
this.transformer = transformer;
this.verifier = verifier;
this.scriptBaseClass = scriptBaseClass;
}
示例8
private static Expression revertType(Expression val, ClassNode returnWrapperType) {
ConstantExpression ce = (ConstantExpression) val;
if (ClassHelper.Character_TYPE.equals(returnWrapperType) && ClassHelper.STRING_TYPE.equals(val.getType())) {
return configure(val, Verifier.transformToPrimitiveConstantIfPossible((ConstantExpression) val));
}
ClassNode valWrapperType = ClassHelper.getWrapper(val.getType());
if (ClassHelper.Integer_TYPE.equals(valWrapperType)) {
Integer i = (Integer) ce.getValue();
if (ClassHelper.Character_TYPE.equals(returnWrapperType)) {
return configure(val, new ConstantExpression((char) i.intValue(), true));
}
if (ClassHelper.Short_TYPE.equals(returnWrapperType)) {
return configure(val, new ConstantExpression(i.shortValue(), true));
}
if (ClassHelper.Byte_TYPE.equals(returnWrapperType)) {
return configure(val, new ConstantExpression(i.byteValue(), true));
}
}
if (ClassHelper.BigDecimal_TYPE.equals(valWrapperType)) {
BigDecimal bd = (BigDecimal) ce.getValue();
if (ClassHelper.Float_TYPE.equals(returnWrapperType)) {
return configure(val, new ConstantExpression(bd.floatValue(), true));
}
if (ClassHelper.Double_TYPE.equals(returnWrapperType)) {
return configure(val, new ConstantExpression(bd.doubleValue(), true));
}
}
return null;
}
示例9
/**
* get the time stamp of a class
* NOTE: copied from GroovyClassLoader
*/
private static long getTimeStamp(ClassNode cls) {
if (!(cls instanceof DecompiledClassNode)) {
return Verifier.getTimestamp(cls.getTypeClass());
}
return ((DecompiledClassNode) cls).getCompilationTimeStamp();
}
示例10
private static void addSetterIfNeeded(DelegateDescription delegate, PropertyNode prop, String name, boolean allNames) {
String setterName = "set" + Verifier.capitalize(name);
if ((prop.getModifiers() & ACC_FINAL) == 0
&& delegate.owner.getSetterMethod(setterName) == null && delegate.owner.getProperty(name) == null
&& !shouldSkipPropertyMethod(name, setterName, delegate.excludes, delegate.includes, allNames)) {
addGeneratedMethod(delegate.owner, setterName,
ACC_PUBLIC,
ClassHelper.VOID_TYPE,
params(new Parameter(GenericsUtils.nonGeneric(prop.getType()), "value")),
null,
assignS(propX(delegate.getOp, name), varX("value"))
);
}
}
示例11
private static void addGetterIfNeeded(DelegateDescription delegate, PropertyNode prop, String name, boolean allNames) {
boolean isPrimBool = prop.getOriginType().equals(ClassHelper.boolean_TYPE);
// do a little bit of pre-work since Groovy compiler hasn't added property accessors yet
boolean willHaveGetAccessor = true;
boolean willHaveIsAccessor = isPrimBool;
String suffix = Verifier.capitalize(name);
if (isPrimBool) {
ClassNode cNode = prop.getDeclaringClass();
if (cNode.getGetterMethod("is" + suffix) != null && cNode.getGetterMethod("get" + suffix) == null)
willHaveGetAccessor = false;
if (cNode.getGetterMethod("get" + suffix) != null && cNode.getGetterMethod("is" + suffix) == null)
willHaveIsAccessor = false;
}
Reference<Boolean> ownerWillHaveGetAccessor = new Reference<Boolean>();
Reference<Boolean> ownerWillHaveIsAccessor = new Reference<Boolean>();
extractAccessorInfo(delegate.owner, name, ownerWillHaveGetAccessor, ownerWillHaveIsAccessor);
for (String prefix : new String[]{"get", "is"}) {
String getterName = prefix + suffix;
if ((prefix.equals("get") && willHaveGetAccessor && !ownerWillHaveGetAccessor.get()
|| prefix.equals("is") && willHaveIsAccessor && !ownerWillHaveIsAccessor.get())
&& !shouldSkipPropertyMethod(name, getterName, delegate.excludes, delegate.includes, allNames)) {
addGeneratedMethod(delegate.owner, getterName,
ACC_PUBLIC,
GenericsUtils.nonGeneric(prop.getType()),
Parameter.EMPTY_ARRAY,
null,
returnS(propX(delegate.getOp, name)));
}
}
}
示例12
private static void extractAccessorInfo(ClassNode owner, String name, Reference<Boolean> willHaveGetAccessor, Reference<Boolean> willHaveIsAccessor) {
String suffix = Verifier.capitalize(name);
boolean hasGetAccessor = owner.getGetterMethod("get" + suffix) != null;
boolean hasIsAccessor = owner.getGetterMethod("is" + suffix) != null;
PropertyNode prop = owner.getProperty(name);
willHaveGetAccessor.set(hasGetAccessor || (prop != null && !hasIsAccessor));
willHaveIsAccessor.set(hasIsAccessor || (prop != null && !hasGetAccessor && prop.getOriginType().equals(ClassHelper.boolean_TYPE)));
}
示例13
public long getCompilationTimeStamp() {
if (classData.fields != null) {
for (FieldStub field : classData.fields) {
if (Modifier.isStatic(field.accessModifiers)) {
Long timestamp = Verifier.getTimestampFromFieldName(field.fieldName);
if (timestamp != null) {
return timestamp;
}
}
}
}
return Long.MAX_VALUE;
}
示例14
protected void addFieldsAndGettersForLocalVariables(final InnerClassNode answer, final Parameter[] localVariableParams) {
for (Parameter param : localVariableParams) {
String paramName = param.getName();
ClassNode type = param.getType();
VariableExpression initialValue = new VariableExpression(paramName);
initialValue.setAccessedVariable(param);
initialValue.setUseReferenceDirectly(true);
ClassNode realType = type;
type = ClassHelper.makeReference();
param.setType(ClassHelper.makeReference());
FieldNode paramField = answer.addField(paramName, ACC_PRIVATE | ACC_SYNTHETIC, type, initialValue);
paramField.setOriginType(ClassHelper.getWrapper(param.getOriginType()));
paramField.setHolder(true);
String methodName = Verifier.capitalize(paramName);
// let's add a getter & setter
Expression fieldExp = new FieldExpression(paramField);
markAsGenerated(answer,
answer.addMethod(
"get" + methodName,
ACC_PUBLIC,
realType.getPlainNodeReference(),
Parameter.EMPTY_ARRAY,
ClassNode.EMPTY_ARRAY,
new ReturnStatement(fieldExp)),
true);
}
}
示例15
private FastPathData writeGuards(final StatementMeta meta, final ASTNode node) {
if (fastPathBlocked || controller.isFastPath() || meta == null || !meta.optimize) return null;
controller.getAcg().onLineNumber(node, null);
MethodVisitor mv = controller.getMethodVisitor();
FastPathData fastPathData = new FastPathData();
Label slowPath = new Label();
for (int i = 0, n = guards.length; i < n; i += 1) {
if (meta.involvedTypes[i]) {
guards[i].call(mv);
mv.visitJumpInsn(IFEQ, slowPath);
}
}
// meta class check with boolean holder
MethodNode mn = controller.getMethodNode();
if (mn != null) {
mv.visitFieldInsn(GETSTATIC, controller.getInternalClassName(), Verifier.STATIC_METACLASS_BOOL, "Z");
mv.visitJumpInsn(IFNE, slowPath);
}
// standard metaclass check
disabledStandardMetaClass.call(mv);
mv.visitJumpInsn(IFNE, slowPath);
// other guards here
mv.visitJumpInsn(GOTO, fastPathData.pathStart);
mv.visitLabel(slowPath);
return fastPathData;
}
示例16
public <T extends Script> Class<? extends T> compile(ScriptSource source, ClassLoader classLoader, Transformer transformer, Class<T> scriptBaseClass, Verifier verifier) {
List<Object> key = Arrays.asList(source.getClassName(), classLoader, transformer.getId(), scriptBaseClass.getName());
Class<?> c = cachedClasses.get(key);
if (c == null) {
c = scriptClassCompiler.compile(source, classLoader, transformer, scriptBaseClass, verifier);
cachedClasses.put(key, c);
}
return c.asSubclass(scriptBaseClass);
}
示例17
private CacheInitializer(ScriptSource source, ClassLoader classLoader, Transformer transformer, Verifier verifier, Class<? extends Script> scriptBaseClass) {
this.source = source;
this.classLoader = classLoader;
this.transformer = transformer;
this.verifier = verifier;
this.scriptBaseClass = scriptBaseClass;
}
示例18
private void fixupVariableReferencesInGeneratedMethods(ClassNode node) {
for (MethodNode m : node.getMethods()) {
if (Boolean.TRUE.equals(m.getNodeMetaData(Verifier.DEFAULT_PARAMETER_GENERATED))) {
MethodCallExpression mce = findMethodCallExpressionInLastStatementOfBody(m);
if (mce != null) {
for (Expression arg : ((TupleExpression)mce.getArguments()).getExpressions()) {
if (arg instanceof CastExpression) {
Expression castedExpr = ((CastExpression) arg).getExpression();
if (castedExpr instanceof VariableExpression) {
VariableExpression varExpr = (VariableExpression) castedExpr;
if (varExpr.getAccessedVariable() == null) {
varExpr.setAccessedVariable(varExpr);
} else {
LOGGER.log(Level.FINE, "Variable {0} in method call arguments already had an initial expression", varExpr);
}
} else {
// The initial expressions are inlined directly into the arguments in the
// MethodCallExpression, so if this isn't a variable expression, we just ignore it.
}
} else {
LOGGER.log(Level.FINE, "Unexpected expression in method call arguments in {0}: {1}", new Object[]{ m, arg });
}
}
}
}
}
}
示例19
public ScriptCompiler setVerifier(Verifier verifier) {
this.verifier = verifier;
return this;
}
示例20
void compileToDir(ScriptSource source, ClassLoader classLoader, File scriptCacheDir, Transformer transformer,
Class<? extends Script> scriptBaseClass, Verifier verifier);
示例21
public CustomCompilationUnit(CompilerConfiguration compilerConfiguration, CodeSource codeSource, Verifier customVerifier, ScriptSource source, GroovyClassLoader groovyClassLoader) {
super(compilerConfiguration, codeSource, groovyClassLoader);
this.source = source;
this.verifier = customVerifier;
}
示例22
public <T extends Script> Class<? extends T> compile(ScriptSource source, ClassLoader classLoader, Transformer transformer, Class<T> scriptBaseClass, Verifier verifier) {
if (source.getResource().getText().matches("\\s*")) {
return emptyScriptGenerator.generate(scriptBaseClass);
}
return compiler.compile(source, classLoader, transformer, scriptBaseClass, verifier);
}
示例23
@Override
public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
new OptimizerVisitor(CompilationUnit.this).visitClass(classNode, source); // GROOVY-4272: repositioned from static import visitor
//
// Run the Verifier on the outer class
//
GroovyClassVisitor visitor = new Verifier();
try {
visitor.visitClass(classNode);
} catch (RuntimeParserException rpe) {
getErrorCollector().addError(new SyntaxException(rpe.getMessage(), rpe.getNode()), source);
}
visitor = new LabelVerifier(source);
visitor.visitClass(classNode);
visitor = new InstanceOfVerifier() {
@Override
protected SourceUnit getSourceUnit() {
return source;
}
};
visitor.visitClass(classNode);
visitor = new ClassCompletionVerifier(source);
visitor.visitClass(classNode);
visitor = new ExtendedVerifier(source);
visitor.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 classVisitor = 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);
}
//
// Run the generation and create the class (if required)
//
visitor = new AsmClassGenerator(source, context, classVisitor, sourceName);
visitor.visitClass(classNode);
byte[] bytes = ((ClassWriter) classVisitor).toByteArray();
getClasses().add(new GroovyClass(classNode.getName(), bytes));
//
// Handle any callback that's been set
//
Optional.ofNullable(getClassgenCallback())
.ifPresent(callback -> callback.call(classVisitor, classNode));
//
// Recurse for inner classes
//
LinkedList<ClassNode> innerClasses = ((AsmClassGenerator) visitor).getInnerClasses();
while (!innerClasses.isEmpty()) {
classgen.call(source, context, innerClasses.removeFirst());
}
}
示例24
@Override
protected void loadArguments(final List<Expression> argumentList, final Parameter[] para) {
if (para.length == 0) return;
ClassNode lastParaType = para[para.length - 1].getOriginType();
AsmClassGenerator acg = controller.getAcg();
TypeChooser typeChooser = controller.getTypeChooser();
OperandStack operandStack = controller.getOperandStack();
int argumentListSize = argumentList.size();
ClassNode lastArgType = argumentListSize > 0 ?
typeChooser.resolveType(argumentList.get(argumentListSize -1), controller.getClassNode()) : null;
if (lastParaType.isArray()
&& ((argumentListSize > para.length)
|| ((argumentListSize == (para.length - 1)) && !lastParaType.equals(lastArgType))
|| ((argumentListSize == para.length && lastArgType!=null && !lastArgType.isArray())
&& (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(lastArgType,lastParaType.getComponentType())))
|| ClassHelper.GSTRING_TYPE.equals(lastArgType) && ClassHelper.STRING_TYPE.equals(lastParaType.getComponentType()))
) {
int stackLen = operandStack.getStackLength() + argumentListSize;
MethodVisitor mv = controller.getMethodVisitor();
controller.setMethodVisitor(mv);
// varg call
// first parameters as usual
for (int i = 0; i < para.length - 1; i += 1) {
visitArgument(argumentList.get(i), para[i].getType());
}
// last parameters wrapped in an array
List<Expression> lastParams = new ArrayList<>();
for (int i = para.length - 1; i < argumentListSize; i += 1) {
lastParams.add(argumentList.get(i));
}
ArrayExpression array = new ArrayExpression(lastParaType.getComponentType(), lastParams);
array.visit(acg);
// adjust stack length
while (operandStack.getStackLength() < stackLen) {
operandStack.push(ClassHelper.OBJECT_TYPE);
}
if (argumentListSize == para.length - 1) {
operandStack.remove(1);
}
} else if (argumentListSize == para.length) {
for (int i = 0; i < argumentListSize; i++) {
visitArgument(argumentList.get(i), para[i].getType());
}
} else {
// method call with default arguments
ClassNode classNode = controller.getClassNode();
Expression[] arguments = new Expression[para.length];
for (int i = 0, j = 0, n = para.length; i < n; i += 1) {
Parameter curParam = para[i];
ClassNode curParamType = curParam.getType();
Expression curArg = j < argumentListSize ? argumentList.get(j) : null;
Expression initialExpression = curParam.getNodeMetaData(StaticTypesMarker.INITIAL_EXPRESSION);
if (initialExpression == null && curParam.hasInitialExpression())
initialExpression = curParam.getInitialExpression();
if (initialExpression == null && curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION) != null) {
initialExpression = curParam.getNodeMetaData(Verifier.INITIAL_EXPRESSION);
}
ClassNode curArgType = curArg == null ? null : typeChooser.resolveType(curArg, classNode);
if (initialExpression != null && !compatibleArgumentType(curArgType, curParamType)) {
// use default expression
arguments[i] = initialExpression;
} else {
arguments[i] = curArg;
j += 1;
}
}
for (int i = 0, n = arguments.length; i < n; i += 1) {
visitArgument(arguments[i], para[i].getType());
}
}
}
示例25
private void printField(PrintWriter out, FieldNode fieldNode, boolean isInterface) {
if ((fieldNode.getModifiers() & Opcodes.ACC_PRIVATE) != 0) return;
printAnnotations(out, fieldNode);
if (!isInterface) {
printModifiers(out, fieldNode.getModifiers());
}
ClassNode type = fieldNode.getType();
printType(out, type);
out.print(" ");
out.print(fieldNode.getName());
if (isInterface || (fieldNode.getModifiers() & Opcodes.ACC_FINAL) != 0) {
out.print(" = ");
Expression valueExpr = fieldNode.getInitialValueExpression();
if (valueExpr instanceof ConstantExpression) {
valueExpr = Verifier.transformToPrimitiveConstantIfPossible((ConstantExpression) valueExpr);
}
if (valueExpr instanceof ConstantExpression
&& fieldNode.isStatic() && fieldNode.isFinal()
&& ClassHelper.isStaticConstantInitializerType(valueExpr.getType())
&& valueExpr.getType().equals(fieldNode.getType())) {
// GROOVY-5150 : Initialize value with a dummy constant so that Java cross compiles correctly
if (ClassHelper.STRING_TYPE.equals(valueExpr.getType())) {
out.print(formatString(valueExpr.getText()));
} else if (ClassHelper.char_TYPE.equals(valueExpr.getType())) {
out.print("'"+valueExpr.getText()+"'");
} else {
ClassNode constantType = valueExpr.getType();
out.print('(');
printType(out, type);
out.print(") ");
out.print(valueExpr.getText());
if (ClassHelper.Long_TYPE.equals(ClassHelper.getWrapper(constantType))) out.print('L');
}
} else if (ClassHelper.isPrimitiveType(type)) {
String val = type == ClassHelper.boolean_TYPE ? "false" : "0";
out.print("new " + ClassHelper.getWrapper(type) + "((" + type + ")" + val + ")");
} else {
out.print("null");
}
}
out.println(";");
}
示例26
public ScriptCompiler setVerifier(Verifier verifier) {
this.verifier = verifier;
return this;
}
示例27
void compileToDir(ScriptSource source, ClassLoader classLoader, File scriptCacheDir, Transformer transformer,
Class<? extends Script> scriptBaseClass, Verifier verifier);
示例28
public CustomCompilationUnit(CompilerConfiguration compilerConfiguration, CodeSource codeSource, Verifier customVerifier, ScriptSource source, GroovyClassLoader groovyClassLoader) {
super(compilerConfiguration, codeSource, groovyClassLoader);
this.source = source;
this.verifier = customVerifier;
}
示例29
public <T extends Script> Class<? extends T> compile(ScriptSource source, ClassLoader classLoader, Transformer transformer, Class<T> scriptBaseClass, Verifier verifier) {
if (source.getResource().getText().matches("\\s*")) {
return emptyScriptGenerator.generate(scriptBaseClass);
}
return compiler.compile(source, classLoader, transformer, scriptBaseClass, verifier);
}
示例30
@Override
public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) {
if (classNode.isInterface()) {
return; // not touching interfaces
}
this.sourceUnit = source;
this.classNode = classNode;
// Removes all initial expressions for methods and constructors and generates overloads for all variants.
new InitialExpressionExpander().expandInitialExpressions(classNode);
try {
for (FieldNode field : new ArrayList<>(classNode.getFields())) {
visitNontransformedField(field);
}
for (MethodNode method : new ArrayList<>(classNode.getMethods())) {
visitMethod(method);
}
processConstructors(classNode);
for (Statement statement : new ArrayList<>(classNode.getObjectInitializerStatements())) {
visitNontransformedStatement(statement);
}
classNode.addInterface(SERIALIZABLE_TYPE);
// groovy puts timestamp of compilation into a class file, causing serialVersionUID to change.
// this tends to be undesirable for CPS involving persistence.
// set the timestamp to some bogus value will prevent Verifier from adding a field that encodes
// timestamp in the field name
// see http://stackoverflow.com/questions/15310136/neverhappen-variable-in-compiled-classes
if (classNode.getField(Verifier.__TIMESTAMP) == null) {
classNode.addField(Verifier.__TIMESTAMP, Modifier.STATIC | Modifier.PRIVATE, ClassHelper.long_TYPE,
new ConstantExpression(0L));
}
classNode.addAnnotation(new AnnotationNode(WORKFLOW_TRANSFORMED_TYPE));
} finally {
this.sourceUnit = null;
this.classNode = null;
this.parent = null;
}
}