org.codehaus.groovy.ast.decompiled.MemberSignatureParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of groovy Show documentation
Show all versions of groovy Show documentation
Groovy: A powerful, dynamic language for the JVM
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.codehaus.groovy.ast.decompiled;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.GenericsType;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
import java.util.List;
import java.util.Map;
import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
/**
* Utility methods for lazy class loading
*/
class MemberSignatureParser {
static MethodNode createMethodNode(final AsmReferenceResolver resolver, MethodStub method) {
GenericsType[] typeParameters = null;
Type[] argumentTypes = Type.getArgumentTypes(method.desc);
final ClassNode[] parameterTypes = new ClassNode[argumentTypes.length];
for (int i = 0; i < argumentTypes.length; i++) {
parameterTypes[i] = resolver.resolveType(argumentTypes[i]);
}
final ClassNode[] exceptions = new ClassNode[method.exceptions.length];
for (int i = 0; i < method.exceptions.length; i++) {
exceptions[i] = resolver.resolveClass(AsmDecompiler.fromInternalName(method.exceptions[i]));
}
final ClassNode[] returnType = {resolver.resolveType(Type.getReturnType(method.desc))};
if (method.signature != null) {
FormalParameterParser v = new FormalParameterParser(resolver) {
int paramIndex = 0;
@Override
public SignatureVisitor visitParameterType() {
return new TypeSignatureParser(resolver) {
@Override
void finished(ClassNode result) {
parameterTypes[paramIndex] = applyErasure(result, parameterTypes[paramIndex]);
paramIndex++;
}
};
}
@Override
public SignatureVisitor visitReturnType() {
return new TypeSignatureParser(resolver) {
@Override
void finished(ClassNode result) {
returnType[0] = applyErasure(result, returnType[0]);
}
};
}
int exceptionIndex = 0;
@Override
public SignatureVisitor visitExceptionType() {
return new TypeSignatureParser(resolver) {
@Override
void finished(ClassNode result) {
exceptions[exceptionIndex] = applyErasure(result, exceptions[exceptionIndex]);
exceptionIndex++;
}
};
}
};
new SignatureReader(method.signature).accept(v);
typeParameters = v.getTypeParameters();
}
Parameter[] parameters = new Parameter[parameterTypes.length];
List parameterNames = method.parameterNames;
for (int i = 0; i < parameterTypes.length; i++) {
String parameterName = "param" + i;
if (parameterNames != null && i < parameterNames.size()) {
String decompiledName = parameterNames.get(i);
if (decompiledName != null) {
parameterName = decompiledName;
}
}
parameters[i] = new Parameter(parameterTypes[i], parameterName);
}
if (method.parameterAnnotations != null) {
for (Map.Entry> entry : method.parameterAnnotations.entrySet()) {
for (AnnotationStub stub : entry.getValue()) {
AnnotationNode annotationNode = Annotations.createAnnotationNode(stub, resolver);
if (annotationNode != null) {
parameters[entry.getKey()].addAnnotation(annotationNode);
}
}
}
}
MethodNode result;
if ("".equals(method.methodName)) {
result = new ConstructorNode(method.accessModifiers, parameters, exceptions, null);
} else {
result = new MethodNode(method.methodName, method.accessModifiers, returnType[0], parameters, exceptions, null);
Object annDefault = method.annotationDefault;
if (annDefault != null) {
if (annDefault instanceof TypeWrapper) {
annDefault = resolver.resolveType(Type.getType(((TypeWrapper) annDefault).desc));
}
result.setCode(new ReturnStatement(new ConstantExpression(annDefault)));
result.setAnnotationDefault(true);
} else {
// Seems wrong but otherwise some tests fail (e.g. TestingASTTransformsTest)
result.setCode(new ReturnStatement(nullX()));
}
}
if (typeParameters != null && typeParameters.length > 0) {
result.setGenericsTypes(typeParameters);
}
return result;
}
private static ClassNode applyErasure(ClassNode genericType, ClassNode erasure) {
if (genericType.isArray() && erasure.isArray() && genericType.getComponentType().isGenericsPlaceHolder()) {
genericType.setRedirect(erasure);
genericType.getComponentType().setRedirect(erasure.getComponentType());
} else if (genericType.isGenericsPlaceHolder()) {
genericType.setRedirect(erasure);
}
return genericType;
}
static FieldNode createFieldNode(FieldStub field, AsmReferenceResolver resolver, DecompiledClassNode owner) {
final ClassNode[] type = {resolver.resolveType(Type.getType(field.desc))};
if (field.signature != null) {
new SignatureReader(field.signature).accept(new TypeSignatureParser(resolver) {
@Override
void finished(ClassNode result) {
type[0] = applyErasure(result, type[0]);
}
});
}
ConstantExpression value = field.value == null ? null : new ConstantExpression(field.value);
return new FieldNode(field.fieldName, field.accessModifiers, type[0], owner, value);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy