[java] Fix #5293: Parse number of type parameters eagerly

When creating a LazyClassSignature or LazyMethodType, make sure
to parse the number of type parameters eagerly, so that AstDisambiguationPass
can get this number without triggering additional parsing.
This commit is contained in:
Andreas Dangel 2024-11-04 10:40:32 +01:00
parent a1996554d8
commit 1ee6494429
No known key found for this signature in database
GPG Key ID: 93450DF2DF9A3FA3
3 changed files with 53 additions and 7 deletions

View File

@ -310,9 +310,9 @@ final class ClassStub implements JClassSymbol, AsmStub, AnnotationOwner {
} }
@Override @Override
public boolean isGeneric() { public int getTypeParameterCount() {
parseLock.ensureParsed(); parseLock.ensureParsed();
return signature.isGeneric(); return signature.getTypeParameterCount();
} }
@Override @Override

View File

@ -81,7 +81,11 @@ abstract class GenericSigBase<T extends JTypeParameterOwnerSymbol & AsmStub> {
protected abstract boolean postCondition(); protected abstract boolean postCondition();
protected abstract boolean isGeneric(); protected abstract int getTypeParameterCount();
protected boolean isGeneric() {
return getTypeParameterCount() > 0;
}
public void setTypeParams(List<JTypeVar> tvars) { public void setTypeParams(List<JTypeVar> tvars) {
assert this.typeParameters == null : "Type params were already parsed for " + this; assert this.typeParameters == null : "Type params were already parsed for " + this;
@ -105,6 +109,7 @@ abstract class GenericSigBase<T extends JTypeParameterOwnerSymbol & AsmStub> {
private static final String OBJECT_BOUND = ":" + OBJECT_SIG; private static final String OBJECT_BOUND = ":" + OBJECT_SIG;
private final @Nullable String signature; private final @Nullable String signature;
private final int typeParameterCount;
private @Nullable JClassType superType; private @Nullable JClassType superType;
private List<JClassType> superItfs; private List<JClassType> superItfs;
@ -118,6 +123,7 @@ abstract class GenericSigBase<T extends JTypeParameterOwnerSymbol & AsmStub> {
String[] interfaces) { String[] interfaces) {
super(ctx, "LazyClassSignature:" + ctx.getInternalName() + "[" + signature + "]"); super(ctx, "LazyClassSignature:" + ctx.getInternalName() + "[" + signature + "]");
this.signature = signature; this.signature = signature;
this.typeParameterCount = GenericTypeParameterCounter.determineTypeParameterCount(this.signature);
this.rawItfs = CollectionUtil.map(interfaces, ctx.getResolver()::resolveFromInternalNameCannotFail); this.rawItfs = CollectionUtil.map(interfaces, ctx.getResolver()::resolveFromInternalNameCannotFail);
this.rawSuper = ctx.getResolver().resolveFromInternalNameCannotFail(superInternalName); this.rawSuper = ctx.getResolver().resolveFromInternalNameCannotFail(superInternalName);
@ -157,8 +163,9 @@ abstract class GenericSigBase<T extends JTypeParameterOwnerSymbol & AsmStub> {
} }
@Override @Override
protected boolean isGeneric() { protected int getTypeParameterCount() {
return signature != null && TypeParamsParser.hasTypeParams(signature); // note: no ensureParsed() needed, the type parameters are counted eagerly
return typeParameterCount;
} }
@Override @Override
@ -206,6 +213,7 @@ abstract class GenericSigBase<T extends JTypeParameterOwnerSymbol & AsmStub> {
static class LazyMethodType extends GenericSigBase<ExecutableStub> implements TypeAnnotationReceiver { static class LazyMethodType extends GenericSigBase<ExecutableStub> implements TypeAnnotationReceiver {
private final @NonNull String signature; private final @NonNull String signature;
private final int typeParameterCount;
private @Nullable TypeAnnotationSet receiverAnnotations; private @Nullable TypeAnnotationSet receiverAnnotations;
private List<JTypeMirror> parameterTypes; private List<JTypeMirror> parameterTypes;
@ -235,6 +243,7 @@ abstract class GenericSigBase<T extends JTypeParameterOwnerSymbol & AsmStub> {
boolean skipFirstParam) { boolean skipFirstParam) {
super(ctx, "LazyMethodType:" + (genericSig != null ? genericSig : descriptor)); super(ctx, "LazyMethodType:" + (genericSig != null ? genericSig : descriptor));
this.signature = genericSig != null ? genericSig : descriptor; this.signature = genericSig != null ? genericSig : descriptor;
this.typeParameterCount = GenericTypeParameterCounter.determineTypeParameterCount(genericSig);
// generic signatures already omit the synthetic param // generic signatures already omit the synthetic param
this.skipFirstParam = skipFirstParam && genericSig == null; this.skipFirstParam = skipFirstParam && genericSig == null;
this.rawExceptions = exceptions; this.rawExceptions = exceptions;
@ -288,8 +297,9 @@ abstract class GenericSigBase<T extends JTypeParameterOwnerSymbol & AsmStub> {
@Override @Override
protected boolean isGeneric() { protected int getTypeParameterCount() {
return TypeParamsParser.hasTypeParams(signature); // note: no ensureParsed() needed, the type parameters are counted eagerly
return typeParameterCount;
} }
void setParameterTypes(List<JTypeMirror> params) { void setParameterTypes(List<JTypeMirror> params) {

View File

@ -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();
}
}