| /* |
| * 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.*; |
| 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; |
| |
| /** |
| * @author Peter Gromov |
| */ |
| 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]; |
| for (int i = 0; i < parameterTypes.length; i++) { |
| parameters[i] = new Parameter(parameterTypes[i], "param" + i); |
| } |
| |
| if (method.parameterAnnotations != null) { |
| for (Map.Entry<Integer, List<AnnotationStub>> 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 ("<init>".equals(method.methodName)) { |
| result = new ConstructorNode(method.accessModifiers, parameters, exceptions, null); |
| } else { |
| result = new MethodNode(method.methodName, method.accessModifiers, returnType[0], parameters, exceptions, null); |
| if (method.annotationDefault != null) { |
| result.setCode(new ReturnStatement(new ConstantExpression(method.annotationDefault))); |
| result.setAnnotationDefault(true); |
| } else { |
| // Seems wrong but otherwise some tests fail (e.g. TestingASTTransformsTest) |
| result.setCode(new ReturnStatement(ConstantExpression.NULL)); |
| } |
| |
| } |
| if (typeParameters != null && typeParameters.length > 0) { |
| result.setGenericsTypes(typeParameters); |
| } |
| return result; |
| } |
| |
| private static ClassNode applyErasure(ClassNode genericType, ClassNode erasure) { |
| 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]); |
| } |
| }); |
| } |
| return new FieldNode(field.fieldName, field.accessModifiers, type[0], owner, null); |
| } |
| } |
| |