From eff7903b563ab9f6c9fabf910251683e15c12b93 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 15 Dec 2011 03:04:21 +0400 Subject: [PATCH] dummy implementation of method type parameters reader and refactoring --- .../jet/codegen/BothSignatureWriter.java | 13 +++- .../jetbrains/jet/codegen/ClosureCodegen.java | 4 +- .../jet/codegen/FunctionCodegen.java | 3 + .../codegen/ImplementationBodyCodegen.java | 2 +- .../jetbrains/jet/codegen/JetTypeMapper.java | 16 ++-- .../jet/codegen/JvmMethodSignature.java | 9 ++- .../resolve/java/JavaDescriptorResolver.java | 71 ++++++++++++++++- .../jet/lang/resolve/java/StdlibNames.java | 3 +- stdlib/src/jet/typeinfo/JetMethod.java | 6 ++ .../org/jetbrains/jet/rt/TypeInfoParser.java | 78 ++++++++++--------- .../jet/rt/signature/JetSignatureAdapter.java | 7 +- .../JetSignatureExceptionsAdapter.java | 7 +- .../jet/rt/signature/JetSignatureReader.java | 8 +- .../jet/rt/signature/JetSignatureVisitor.java | 4 +- .../jet/rt/signature/JetSignatureWriter.java | 7 +- 15 files changed, 178 insertions(+), 60 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java index d83d838cb95..440d0587873 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java @@ -200,6 +200,10 @@ public class BothSignatureWriter { signatureVisitor().visitFormalTypeParameter(name); jetSignatureWriter.visitFormalTypeParameter(name, translateVariance(variance)); } + + public void writeFormalTypeParameterEnd() { + jetSignatureWriter.visitFormalTypeParameterEnd(); + } public void writerFormalTypeParametersStart() { checkTopLevel(); @@ -342,9 +346,9 @@ public class BothSignatureWriter { // TODO: return null if not generic return signatureWriter.toString(); } - + @NotNull - public List makeKotlinSignatures() { + public List makeKotlinParameterTypes() { checkState(State.METHOD_END); // TODO: return nulls if equal to #makeJavaString return kotlinParameterTypes; @@ -355,6 +359,11 @@ public class BothSignatureWriter { checkState(State.METHOD_END); return kotlinReturnType; } + + public String makeKotlinMethodTypeParameters() { + checkState(State.METHOD_END); + return kotlinClassParameters; + } @Nullable public String makeKotlinClassSignature() { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 75e3d28323a..6ace88a728b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -53,7 +53,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { public static CallableMethod asCallableMethod(FunctionDescriptor fd) { Method descriptor = erasedInvokeSignature(fd); String owner = getInternalClassName(fd); - final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null, null, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); + final CallableMethod result = new CallableMethod(owner, new JvmMethodSignature(descriptor, null, null, null, null), INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes())); if (fd.getReceiverParameter().exists()) { result.setNeedsReceiver(fd); } @@ -165,7 +165,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen { final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper()); FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state); - fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null, null, null), funDescriptor); + fc.generateMethod(body, new JvmMethodSignature(invokeSignature(funDescriptor), null, null, null, null), funDescriptor); return closureContext.outerWasUsed; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 27cea25ce10..001ff53bf88 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -93,6 +93,9 @@ public class FunctionCodegen { if (jvmSignature.getKotlinReturnType() != null) { av.visit(StdlibNames.JET_METHOD_RETURN_TYPE_FIELD, jvmSignature.getKotlinReturnType()); } + if (jvmSignature.getKotlinTypeParameter() != null) { + av.visit(StdlibNames.JET_METHOD_TYPE_PARAMETERS_FIELD, jvmSignature.getKotlinTypeParameter()); + } av.visitEnd(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index da2066e7623..1fe54ebc47f 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -323,7 +323,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } constructorMethod = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); - callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null, null, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.emptyList()); + callableMethod = new CallableMethod("", new JvmMethodSignature(constructorMethod, null, null, null, null) /* TODO */, Opcodes.INVOKESPECIAL, Collections.emptyList()); } else { callableMethod = typeMapper.mapToCallableMethod(constructorDescriptor, kind); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index 45344286ed0..0272124ec9b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -519,10 +519,12 @@ public class JetTypeMapper { } Method method = new Method(f.getName(), returnType, parameterTypes.toArray(new Type[parameterTypes.size()])); if (signatureVisitor == null) { - return new JvmMethodSignature(method, null, null, null); + return new JvmMethodSignature(method, null, null, null, null); } else { return new JvmMethodSignature(method, signatureVisitor.makeJavaString(), - signatureVisitor.makeKotlinSignatures(), signatureVisitor.makeKotlinReturnTypeSignature()); + signatureVisitor.makeKotlinMethodTypeParameters(), + signatureVisitor.makeKotlinParameterTypes(), + signatureVisitor.makeKotlinReturnTypeSignature()); } } @@ -568,6 +570,8 @@ public class JetTypeMapper { } } } + + signatureVisitor.writeFormalTypeParameterEnd(); } @@ -583,7 +587,7 @@ public class JetTypeMapper { } Type returnType = mapReturnType(f.getReturnType()); // TODO: proper generic signature - return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null, null, null); + return new JvmMethodSignature(new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()])), null, null, null, null); } @@ -608,7 +612,7 @@ public class JetTypeMapper { } // TODO: proper generic signature - return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null, null, null); + return new JvmMethodSignature(new Method(name, returnType, params.toArray(new Type[params.size()])), null, null, null, null); } @Nullable @@ -638,7 +642,7 @@ public class JetTypeMapper { params.add(mapType(inType)); // TODO: proper generic signature - return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null, null, null); + return new JvmMethodSignature(new Method(name, Type.VOID_TYPE, params.toArray(new Type[params.size()])), null, null, null, null); } private JvmMethodSignature mapConstructorSignature(ConstructorDescriptor descriptor, List valueParameterTypes) { @@ -660,7 +664,7 @@ public class JetTypeMapper { } Method method = new Method("", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()])); - return new JvmMethodSignature(method, null, null, null); // TODO: generics signature + return new JvmMethodSignature(method, null, null, null, null); // TODO: generics signature } public CallableMethod mapToCallableMethod(ConstructorDescriptor descriptor, OwnerKind kind) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodSignature.java b/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodSignature.java index 6eda7035501..2deac1ab39b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodSignature.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JvmMethodSignature.java @@ -14,14 +14,15 @@ public class JvmMethodSignature { private final Method asmMethod; /** Null when we don't care about type parameters */ private final String genericsSignature; - // TODO: type parameters + private final String kotlinTypeParameter; private final List kotlinParameterTypes; private final String kotlinReturnType; public JvmMethodSignature(@NotNull Method asmMethod, @Nullable String genericsSignature, - @Nullable List kotlinParameterTypes, @Nullable String kotlinReturnType) { + @Nullable String kotlinTypeParameters, @Nullable List kotlinParameterTypes, @Nullable String kotlinReturnType) { this.asmMethod = asmMethod; this.genericsSignature = genericsSignature; + this.kotlinTypeParameter = kotlinTypeParameters; this.kotlinParameterTypes = kotlinParameterTypes; this.kotlinReturnType = kotlinReturnType; } @@ -34,6 +35,10 @@ public class JvmMethodSignature { return genericsSignature; } + public String getKotlinTypeParameter() { + return kotlinTypeParameter; + } + public List getKotlinParameterTypes() { return kotlinParameterTypes; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 473600d3bb3..9be475af778 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -8,6 +8,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; +import jet.typeinfo.TypeInfoVariance; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -16,6 +17,9 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.plugin.JetFileType; +import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; +import org.jetbrains.jet.rt.signature.JetSignatureReader; +import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import java.util.*; @@ -503,8 +507,7 @@ public class JavaDescriptorResolver { method.getName() ); methodDescriptorCache.put(method, functionDescriptorImpl); - List typeParameters = makeUninitializedTypeParameters(functionDescriptorImpl, method.getTypeParameters()); - initializeTypeParameters(method); + List typeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl); functionDescriptorImpl.initialize( null, DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), @@ -522,6 +525,70 @@ public class JavaDescriptorResolver { return substitutedFunctionDescriptor; } + private List resolveMethodTypeParameters(PsiMethod method, FunctionDescriptorImpl functionDescriptorImpl) { + for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) { + if (annotation.getQualifiedName().equals(StdlibNames.JET_METHOD_CLASS)) { + PsiLiteralExpression attributeValue = (PsiLiteralExpression) annotation.findAttributeValue(StdlibNames.JET_METHOD_TYPE_PARAMETERS_FIELD); + if (attributeValue != null) { + String typeParametersString = (String) attributeValue.getValue(); + if (typeParametersString != null) { + return resolveMethodTypeParametersFromJetSignature(typeParametersString, functionDescriptorImpl); + } + } + } + } + + List typeParameters = makeUninitializedTypeParameters(functionDescriptorImpl, method.getTypeParameters()); + initializeTypeParameters(method); + return typeParameters; + } + + private List resolveMethodTypeParametersFromJetSignature(String jetSignature, final FunctionDescriptor functionDescriptor) { + final List r = new ArrayList(); + new JetSignatureReader(jetSignature).acceptFormalTypeParametersOnly(new JetSignatureExceptionsAdapter() { + @Override + public JetSignatureVisitor visitFormalTypeParameter(final String name, TypeInfoVariance variance) { + + return new JetSignatureExceptionsAdapter() { + int index = 0; + + @Override + public JetSignatureVisitor visitClassBound() { + return new JetTypeJetSignatureReader(JavaDescriptorResolver.this, semanticServices.getJetSemanticServices().getStandardLibrary()) { + @Override + protected void done(@NotNull JetType jetType) { + // TODO + } + }; + } + + @Override + public JetSignatureVisitor visitInterfaceBound() { + return new JetTypeJetSignatureReader(JavaDescriptorResolver.this, semanticServices.getJetSemanticServices().getStandardLibrary()) { + @Override + protected void done(@NotNull JetType jetType) { + // TODO + } + }; + } + + @Override + public void visitFormalTypeParameterEnd() { + TypeParameterDescriptor typeParameter = TypeParameterDescriptor.createForFurtherModification( + functionDescriptor, + Collections.emptyList(), // TODO: wrong + true, // TODO: wrong + Variance.INVARIANT, // TOOD: wrong + name, + ++index); + r.add(typeParameter); + } + }; + } + }); + return r; + } + private JetType makeReturnType(PsiType returnType, PsiMethod method) { boolean changeNullable = false; boolean nullable = true; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java index c6223502385..6e3e8abeb34 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/StdlibNames.java @@ -27,7 +27,8 @@ public class StdlibNames { public static final String JET_METHOD_NULLABLE_RETURN_TYPE_FIELD = "nullableReturnType"; public static final String JET_METHOD_RETURN_TYPE_FIELD = "returnType"; - + public static final String JET_METHOD_TYPE_PARAMETERS_FIELD = "typeParameters"; + public static final String JET_OBJECT_INTERNAL = "jet/JetObject"; public static final String JET_OBJECT_CLASS = "jet.JetObject"; diff --git a/stdlib/src/jet/typeinfo/JetMethod.java b/stdlib/src/jet/typeinfo/JetMethod.java index b057014caf2..8bca6f9db5a 100644 --- a/stdlib/src/jet/typeinfo/JetMethod.java +++ b/stdlib/src/jet/typeinfo/JetMethod.java @@ -22,6 +22,12 @@ public @interface JetMethod { */ JetTypeProjection[] returnTypeProjections() default {}; + /** + * Serialized method type parameters. + * @return + */ + String typeParameters() default ""; + /** * @return is this type returnTypeNullable */ diff --git a/stdlib/src/org/jetbrains/jet/rt/TypeInfoParser.java b/stdlib/src/org/jetbrains/jet/rt/TypeInfoParser.java index 1a3b67a3d2e..78fa32782e4 100644 --- a/stdlib/src/org/jetbrains/jet/rt/TypeInfoParser.java +++ b/stdlib/src/org/jetbrains/jet/rt/TypeInfoParser.java @@ -71,52 +71,56 @@ class TypeInfoParser { signature.varNames = new HashMap(); signature.superTypes = new ArrayList(); new JetSignatureReader(annotationValue).accept(new JetSignatureExceptionsAdapter() { - int varIndex = 0; @Override - public void visitFormalTypeParameter(String name, final TypeInfoVariance variance) { + public JetSignatureVisitor visitFormalTypeParameter(final String name, final TypeInfoVariance variance) { - final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, signature.variables.size()); - - signature.varNames.put(name, signature.variables.size()); - TypeInfoProjection typeInfoProjection = new TypeInfoProjection() { - @Override - public TypeInfoVariance getVariance() { - return variance; - } - - @Override - public TypeInfo getType() { - return typeInfoVar; - } - - @Override - public String toString() { - return typeInfoVar.toString(); - } - }; - - signature.variables.add(typeInfoProjection); - // TODO: supers // TODO: nullability - } - @Override - public JetSignatureVisitor visitClassBound() { - return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) { + return new JetSignatureExceptionsAdapter() { @Override - protected void done(TypeInfo typeInfo) { - // TODO + public JetSignatureVisitor visitClassBound() { + return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) { + @Override + protected void done(TypeInfo typeInfo) { + // TODO + } + }; } - }; - } - @Override - public JetSignatureVisitor visitInterfaceBound() { - return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) { @Override - protected void done(TypeInfo typeInfo) { - // TODO + public JetSignatureVisitor visitInterfaceBound() { + return new SignatureParserJetSignatureAdapter(signature.klazz.getClassLoader(), signature) { + @Override + protected void done(TypeInfo typeInfo) { + // TODO + } + }; + } + + @Override + public void visitFormalTypeParameterEnd() { + final TypeInfoVar typeInfoVar = new TypeInfoVar(signature, signature.variables.size()); + + signature.varNames.put(name, signature.variables.size()); + TypeInfoProjection typeInfoProjection = new TypeInfoProjection() { + @Override + public TypeInfoVariance getVariance() { + return variance; + } + + @Override + public TypeInfo getType() { + return typeInfoVar; + } + + @Override + public String toString() { + return typeInfoVar.toString(); + } + }; + + signature.variables.add(typeInfoProjection); } }; } diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureAdapter.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureAdapter.java index 3366e3b410f..5d9878b3110 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureAdapter.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureAdapter.java @@ -7,7 +7,12 @@ import jet.typeinfo.TypeInfoVariance; */ public class JetSignatureAdapter implements JetSignatureVisitor { @Override - public void visitFormalTypeParameter(String name, TypeInfoVariance variance) { + public JetSignatureVisitor visitFormalTypeParameter(String name, TypeInfoVariance variance) { + return this; + } + + @Override + public void visitFormalTypeParameterEnd() { } @Override diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureExceptionsAdapter.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureExceptionsAdapter.java index cca55b64951..1d6be28930f 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureExceptionsAdapter.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureExceptionsAdapter.java @@ -7,7 +7,12 @@ import jet.typeinfo.TypeInfoVariance; */ public class JetSignatureExceptionsAdapter implements JetSignatureVisitor { @Override - public void visitFormalTypeParameter(String name, TypeInfoVariance variance) { + public JetSignatureVisitor visitFormalTypeParameter(String name, TypeInfoVariance variance) { + throw new IllegalStateException(); + } + + @Override + public void visitFormalTypeParameterEnd() { throw new IllegalStateException(); } diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureReader.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureReader.java index 49624917f09..a163c8c6d4d 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureReader.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureReader.java @@ -59,17 +59,19 @@ public class JetSignatureReader { if (end < 0) { throw new IllegalStateException(); } - v.visitFormalTypeParameter(signature.substring(pos, end), variance); + JetSignatureVisitor parameterVisitor = v.visitFormalTypeParameter(signature.substring(pos, end), variance); pos = end + 1; c = signature.charAt(pos); if (c == 'L' || c == '[' || c == 'T' || c == '?') { - pos = parseType(signature, pos, v.visitClassBound()); + pos = parseType(signature, pos, parameterVisitor.visitClassBound()); } while ((c = signature.charAt(pos++)) == ':') { - pos = parseType(signature, pos, v.visitInterfaceBound()); + pos = parseType(signature, pos, parameterVisitor.visitInterfaceBound()); } + + parameterVisitor.visitFormalTypeParameterEnd(); } while (c != '>'); } else { pos = 0; diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVisitor.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVisitor.java index ee7bfc3e2d1..2a16f087c1c 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVisitor.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVisitor.java @@ -30,7 +30,9 @@ public interface JetSignatureVisitor { * * @param name the name of the formal parameter. */ - void visitFormalTypeParameter(String name, TypeInfoVariance variance); + JetSignatureVisitor visitFormalTypeParameter(String name, TypeInfoVariance variance); + + void visitFormalTypeParameterEnd(); /** * Visits the class bound of the last visited formal type parameter. diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureWriter.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureWriter.java index 9bd16db1c52..9db334ccefb 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureWriter.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureWriter.java @@ -43,7 +43,7 @@ public class JetSignatureWriter implements JetSignatureVisitor { // ------------------------------------------------------------------------ @Override - public void visitFormalTypeParameter(final String name, TypeInfoVariance variance) { + public JetSignatureVisitor visitFormalTypeParameter(final String name, TypeInfoVariance variance) { if (!hasFormals) { hasFormals = true; buf.append('<'); @@ -62,6 +62,11 @@ public class JetSignatureWriter implements JetSignatureVisitor { } buf.append(name); buf.append(':'); + return this; + } + + @Override + public void visitFormalTypeParameterEnd() { } @Override