Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AnnotationSuppressor now resolves Full Qualified Annotation Names without type solving #4570

Merged
merged 12 commits into from Feb 23, 2022

Conversation

BraisGabin
Copy link
Member

@BraisGabin BraisGabin commented Feb 6, 2022

This was way more difficult than I expected. Please, review this PR commit by commit.

The more complex type of annotations are like this @com.dagger.Component.Factory. We have a part that is package and another part that are class names. But it's not clear when one ends and one the other ends. This is importan because when we find for matches for this type of annotations we should allow:

  • @com.dagger.Component.Factory
  • @Component.Factory if import com.dagger.Component is present
  • @Factory if import com.dagger.Component.Factory is present

But we should not allow @dagger.Component.Factory, because that's another annotation different. It can't be @com.dagger.Component.Factory. All this cases is what makes this code complex and that force me to have all those tests.

fixes #4355
fixes #4356

@BraisGabin BraisGabin added this to the 1.20.0 milestone Feb 6, 2022
@codecov
Copy link

codecov bot commented Feb 6, 2022

Codecov Report

Merging #4570 (30ce1c7) into main (1e406db) will increase coverage by 84.56%.
The diff coverage is 93.75%.

Impacted file tree graph

@@             Coverage Diff             @@
##             main    #4570       +/-   ##
===========================================
+ Coverage        0   84.56%   +84.56%     
- Complexity      0     3340     +3340     
===========================================
  Files           0      481      +481     
  Lines           0    11186    +11186     
  Branches        0     2038     +2038     
===========================================
+ Hits            0     9459     +9459     
- Misses          0      697      +697     
- Partials        0     1030     +1030     
Impacted Files Coverage Δ
...ch/detekt/core/suppressors/AnnotationSuppressor.kt 94.44% <80.00%> (ø)
...gitlab/arturbosch/detekt/api/AnnotationExcluder.kt 91.89% <91.42%> (ø)
...ub/detekt/psi/internal/FullQualifiedNameGuesser.kt 90.00% <92.30%> (ø)
...bosch/detekt/rules/complexity/LongParameterList.kt 85.71% <100.00%> (ø)
...tlab/arturbosch/detekt/rules/bugs/LateinitUsage.kt 92.59% <100.00%> (ø)
...etekt/rules/style/FunctionOnlyReturningConstant.kt 95.74% <100.00%> (ø)
...sch/detekt/rules/style/UnnecessaryAbstractClass.kt 87.50% <100.00%> (ø)
...tlab/arturbosch/detekt/rules/style/UseDataClass.kt 81.08% <100.00%> (ø)
...lin/io/github/detekt/tooling/api/spec/RulesSpec.kt 100.00% <0.00%> (ø)
...h/detekt/formatting/wrappers/SpacingAroundComma.kt 100.00% <0.00%> (ø)
... and 479 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1e406db...30ce1c7. Read the comment docs.

@cortinico
Copy link
Member

This was way more difficult than I expected. Please, review this PR commit by commit.

I went through them and I lack the relevant context as I haven't really touched this part of the codebase in a while. The code looks good and well tested. Generally, I think we're good to go with the heuristic you suggested.

@@ -39,13 +39,16 @@ class FullQualifiedNameGuesser internal constructor(
if (packageName != null) {
add("$packageName.$name")
}
if (name.first().isLowerCase()) {
Copy link
Member

Choose a reason for hiding this comment

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

What's the reason for this check?

Copy link
Member

Choose a reason for hiding this comment

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

For that reason we use a heuristic here: If the first character is lower case we assume it's a package name. Therefore I think this is to handle cases like dagger\..*. First uppercase indicates a class name and Component\..* would not be a valid case.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry @schalkms, I didn't see this comment before.

Yes the reason was that heuristic... but now that I think about that I'm not sure if this class needs to know about this. We could assume that any string that we can't match with an import could be a FullQualifiedName. But I don't know if that's better or worse... That's the issue with this mixed behaviour. The "general use cases" are easy to manage but all this edge cases are really difficult to manage because we can't know for sure.

@schalkms
Copy link
Member

The drawback of having this mixed implementation for enabled and disabled type resolution is the complexity of the code. However, for now, I don't know a better solution.

@3flex
Copy link
Member

3flex commented Feb 11, 2022

The drawback of having this mixed implementation for enabled and disabled type resolution is the complexity of the code

Agree. This approach will lead to significant maintenance if for every rule or feature that's improved by using type resolution we have to also support users who choose not to use type resolution.

Is the real issue that type resolution is too difficult to use correctly? What can we do here to avoid introducing this complexity to our code?

@BraisGabin
Copy link
Member Author

Is the real issue that type resolution is too difficult to use correctly? What can we do here to avoid introducing this complexity to our code?

As far as I know the main issue is the performance. We should rework our gradle plugin to make it type solve first.

@cortinico
Copy link
Member

As far as I know the main issue is the performance

This ☝️ . We have users running detekt on pre-commit hooks. Enabling TR for them is a no-go as they'll end up impacting the development loop for a lot of engineers.

I think we should keep the current feature set for non-TR enabled project and add new features that are working with TR only.

The problem in this PR/Linked issues was that, by implementing a more advanced annotation suppressor, we actually broke the experience for users on non-TR project.

@cortinico
Copy link
Member

Anything missing from this PR? I'd like to kickoff a RC1 as soon as this is merged 👍

@cortinico cortinico added the notable changes Marker for notable changes in the changelog label Feb 19, 2022
@BraisGabin
Copy link
Member Author

This is ready to merge for me. But, is this a notable change or just a bug fix?

Copy link
Member

@chao2zhang chao2zhang left a comment

Choose a reason for hiding this comment

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

lgtm! Thank you for adding those test cases and that really helped me to understand

@@ -39,13 +39,16 @@ class FullQualifiedNameGuesser internal constructor(
if (packageName != null) {
add("$packageName.$name")
}
if (name.first().isLowerCase()) {
Copy link
Member

Choose a reason for hiding this comment

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

For that reason we use a heuristic here: If the first character is lower case we assume it's a package name. Therefore I think this is to handle cases like dagger\..*. First uppercase indicates a class name and Component\..* would not be a valid case.

BraisGabin and others added 2 commits February 21, 2022 09:23
…/FullQualifiedNameGuesserSpec.kt

Co-authored-by: M Schalk <30376729+schalkms@users.noreply.github.com>
@cortinico
Copy link
Member

This is ready to merge for me. But, is this a notable change or just a bug fix?

It's a notable change that we fixed a regression in the latest stable (imho this would have been point-release worthy, we skipped that so let's at least mention this on top of the release notes).

@BraisGabin BraisGabin merged commit dd80d61 into main Feb 23, 2022
@BraisGabin BraisGabin deleted the improve-annotation-suppresor branch February 23, 2022 23:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
notable changes Marker for notable changes in the changelog suppressors
Projects
None yet
6 participants