diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java index c5337cf773..15ae7b0535 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/ClassStub.java @@ -310,9 +310,9 @@ final class ClassStub implements JClassSymbol, AsmStub, AnnotationOwner { } @Override - public boolean isGeneric() { + public int getTypeParameterCount() { parseLock.ensureParsed(); - return signature.isGeneric(); + return signature.getTypeParameterCount(); } @Override diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/GenericSigBase.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/GenericSigBase.java index 8ee5f39aaa..eabeb13c5a 100644 --- a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/GenericSigBase.java +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/GenericSigBase.java @@ -81,7 +81,11 @@ abstract class GenericSigBase { protected abstract boolean postCondition(); - protected abstract boolean isGeneric(); + protected abstract int getTypeParameterCount(); + + protected boolean isGeneric() { + return getTypeParameterCount() > 0; + } public void setTypeParams(List tvars) { assert this.typeParameters == null : "Type params were already parsed for " + this; @@ -105,6 +109,7 @@ abstract class GenericSigBase { private static final String OBJECT_BOUND = ":" + OBJECT_SIG; private final @Nullable String signature; + private final int typeParameterCount; private @Nullable JClassType superType; private List superItfs; @@ -118,6 +123,7 @@ abstract class GenericSigBase { String[] interfaces) { super(ctx, "LazyClassSignature:" + ctx.getInternalName() + "[" + signature + "]"); this.signature = signature; + this.typeParameterCount = GenericTypeParameterCounter.determineTypeParameterCount(this.signature); this.rawItfs = CollectionUtil.map(interfaces, ctx.getResolver()::resolveFromInternalNameCannotFail); this.rawSuper = ctx.getResolver().resolveFromInternalNameCannotFail(superInternalName); @@ -157,8 +163,9 @@ abstract class GenericSigBase { } @Override - protected boolean isGeneric() { - return signature != null && TypeParamsParser.hasTypeParams(signature); + protected int getTypeParameterCount() { + // note: no ensureParsed() needed, the type parameters are counted eagerly + return typeParameterCount; } @Override @@ -206,6 +213,7 @@ abstract class GenericSigBase { static class LazyMethodType extends GenericSigBase implements TypeAnnotationReceiver { private final @NonNull String signature; + private final int typeParameterCount; private @Nullable TypeAnnotationSet receiverAnnotations; private List parameterTypes; @@ -235,6 +243,7 @@ abstract class GenericSigBase { boolean skipFirstParam) { super(ctx, "LazyMethodType:" + (genericSig != null ? genericSig : descriptor)); this.signature = genericSig != null ? genericSig : descriptor; + this.typeParameterCount = GenericTypeParameterCounter.determineTypeParameterCount(genericSig); // generic signatures already omit the synthetic param this.skipFirstParam = skipFirstParam && genericSig == null; this.rawExceptions = exceptions; @@ -288,8 +297,9 @@ abstract class GenericSigBase { @Override - protected boolean isGeneric() { - return TypeParamsParser.hasTypeParams(signature); + protected int getTypeParameterCount() { + // note: no ensureParsed() needed, the type parameters are counted eagerly + return typeParameterCount; } void setParameterTypes(List params) { diff --git a/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/GenericTypeParameterCounter.java b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/GenericTypeParameterCounter.java new file mode 100644 index 0000000000..28f309c43b --- /dev/null +++ b/pmd-java/src/main/java/net/sourceforge/pmd/lang/java/symbols/internal/asm/GenericTypeParameterCounter.java @@ -0,0 +1,36 @@ +/* + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ + +package net.sourceforge.pmd.lang.java.symbols.internal.asm; + +import org.objectweb.asm.signature.SignatureReader; +import org.objectweb.asm.signature.SignatureVisitor; + +class GenericTypeParameterCounter extends SignatureVisitor { + private int count; + + GenericTypeParameterCounter() { + super(AsmSymbolResolver.ASM_API_V); + } + + @Override + public void visitFormalTypeParameter(String name) { + count++; + } + + public int getCount() { + return count; + } + + static int determineTypeParameterCount(String signature) { + if (signature == null) { + return 0; + } + + SignatureReader signatureReader = new SignatureReader(signature); + GenericTypeParameterCounter counter = new GenericTypeParameterCounter(); + signatureReader.accept(counter); + return counter.getCount(); + } +}