Skip to content

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

Merged
jsotuyod merged 4 commits intopmd:mainfrom
adangel:issue-5293
Nov 7, 2024
Merged

[java] Fix #5293: Parse number of type parameters eagerly#5309
jsotuyod merged 4 commits intopmd:mainfrom
adangel:issue-5293

Conversation

@adangel
Copy link
Copy Markdown
Member

@adangel adangel commented Nov 4, 2024

Describe the PR

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.

Related issues

Ready?

  • Added unit tests for fixed bug/feature
  • Passing all unit tests
  • Complete build ./mvnw clean verify passes (checked automatically by github actions)
  • Added (in-code) documentation (if needed)

- Improve logging for Parselock

Refs pmd#5293
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.
@adangel adangel added this to the 7.8.0 milestone Nov 4, 2024

@Override
public boolean isGeneric() {
public int getTypeParameterCount() {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We implement getTypeParameterCount() explicitly for ClassStub (the default impl would call signature.getTypeParameters().size() which would trigger the full parsing of the signature).

Note: the default impl of isGeneric() is good enough and uses just the type parameter count. So, no need to override it here.

this.names = new Names(internalName);

this.parseLock = new ParseLock() {
// note to devs: to debug the parsing logic you might have
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The toString() method in ClassStub already as a comment about avoiding full parsing logic in debug mode. So, this comment is not necessary anymore here.

protected abstract boolean postCondition();

protected abstract boolean isGeneric();
protected abstract int getTypeParameterCount();
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Each GenericSigBase impl must provide a implementation for getTypeParameterCount()

super(ctx);
super(ctx, "LazyClassSignature:" + ctx.getInternalName() + "[" + signature + "]");
this.signature = signature;
this.typeParameterCount = GenericTypeParameterCounter.determineTypeParameterCount(this.signature);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we parse partially the signature already to determine the type parameter count. That way, we know the number of types, without the need to know the exact types of the type parameters.

return signature != null && TypeParamsParser.hasTypeParams(signature);
protected int getTypeParameterCount() {
// note: no ensureParsed() needed, the type parameters are counted eagerly
return typeParameterCount;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: you can easily recreate the bug by adding ensureParsed() here...

@ghost
Copy link
Copy Markdown

ghost commented Nov 4, 2024

1 Message
📖 Compared to main:
This changeset changes 0 violations,
introduces 0 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Download full report as build artifact
Compared to main:
This changeset changes 0 violations,
introduces 0 new violations, 0 new errors and 0 new configuration errors,
removes 0 violations, 0 errors and 0 configuration errors.
Download full report as build artifact

Generated by 🚫 Danger

@jsotuyod jsotuyod added in:pmd-internals Affects PMD's internals in:type-resolution Affects the type resolution code labels Nov 7, 2024
@jsotuyod jsotuyod merged commit fe88498 into pmd:main Nov 7, 2024
@jsotuyod
Copy link
Copy Markdown
Member

jsotuyod commented Nov 7, 2024

Amazing effort!

Comment on lines +79 to +83
@Override
public boolean isGeneric() {
parseLock.ensureParsed();
return signature.isGeneric();
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw. I have no idea, why adding this method would reintroduce the deadlock. At least, the test seems to detect this, in case we accidentally add the deadlock again...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in:pmd-internals Affects PMD's internals in:type-resolution Affects the type resolution code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[java] Deadlock when executing PMD in multiple threads

2 participants