Skip to content

[RFC] [POC] - report missing classes#1371

Closed
adangel wants to merge 1 commit into
pmd:masterfrom
adangel:poc-report-missing-classes
Closed

[RFC] [POC] - report missing classes#1371
adangel wants to merge 1 commit into
pmd:masterfrom
adangel:poc-report-missing-classes

Conversation

@adangel

@adangel adangel commented Oct 6, 2018

Copy link
Copy Markdown
Member

This adds a PmdThreadContextHolder to have access to the report anywhere.

API is ugly and needs to be defined yet. The problem should be reported
as a configuration error rather than a processing error. But a
configuration error needs a rule and is unfortunately currently
ignored by the maven-pmd-plugin... (it doesn't end up in the report).

But in general, it works - the missing classes end up as processing
errors in the final report.

I probably missed some cases where we should report missing classes
or reporting the cases multiple times...
In the end, we should probably deduplicate and report each missing
class only once.

This would be part of #194

anywhere.

API is ugly and needs to be defined yet. The problem should be reported
as a configuration error rather than a processing error. But a
configuration error needs a rule and is unfortunately currently
ignored by the maven-pmd-plugin... (it doesn't end up in the report).

But in general, it works - the missing classes end up as processing
errors in the final report.

I probably missed some cases where we should report missing classes
or reporting the cases multiple times...
In the end, we should probably deduplicate and report each missing
class only once.
@adangel adangel added the a:RFC A drafted proposal on changes to PMD, up for feedback form the team and community label Oct 6, 2018

@jsotuyod jsotuyod left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

we do want to report on NoClassDefFoundError, but do we want to do so on other LinkageError such as ClassFormatError (#1330 / #1131)? I'm unsure an end user would be able to understand and fix those scenarios on it's own

Also, I'd consider reporting this separately and not just as a ProcessingError... I think reporting "The class foo.bar.Baz is missing from auxclasspath, this report could be incomplete" or something of the sort, instead of a stacktrace. It should be much friendlier to the user. Maybe a ConfigurationError error is easier on this as it takes a String and not an exception?

Also, we should filter out duplicates from this report...

@oowekyala

Copy link
Copy Markdown
Member

Maybe, instead of relying on static state (and the initialization/reset that requires) we could pass around a special error logger in the AstAnalysisConfiguration I introduce in #1426. This is what the object's made for, and it would be in scope at the current call sites of your ThreadContextHolder.

I agree with @jsotuyod that the error reporting should be user-friendly, though I guess that can be handled by the report renderers? Maybe using a subclass of ProcessingError would allow us to filter them out at that point? In the less verbose report formats, we could also only display the package names when there are very many missing classes.

@jsotuyod

jsotuyod commented Oct 5, 2019

Copy link
Copy Markdown
Member

I've come back to this after some time…

I don't think passing around AstAnalysisConfiguration will cut it here for a number of reasons:

  1. At some point we may want type res to be lazy, as it will get far more CPU-intensive as it progresses (ie: resolving return types of method calls in the presence of overloads / shadows / overrides). This is something we have already wrote about at some point.
  2. The AstAnalysisConfiguration refers to a single file, and not generally to the current analysis.
  3. We know from experience, some missing classes may not be found during preprocessing, but during rule analysis, hence we have code as this in rules such as MissingOverrideRule:

} catch (final LinkageError e) {
// we may have an incomplete auxclasspath
return null;
}

Moving the AstAnalysisConfiguration around through all analysis / having rules able to access it is going to bloat our interfaces. Moreover, if at some point we realize we need it somewhere else, it's going to force us into breaking changes to keep adding it as a parameter all along the call stack.

I think we should aim for the following:

Have a new AnalysisContext with info about a given PMD run. This should be easily globaly accessible from anywhere, but we probably can't just make it static as we need to be careful about multiple analysis under the same JVM, as Gradle can do. Maybe, the best approach would be:

  1. Have a new AnalysisContextHolder, which uses a ThreadLocal to retrieve it.
  2. Have PmdThreadFactory make sure the AnalysisContextHolder is populated with the one and only AnalysisContext for the current run.

It could provide a simple method such as noteIncompleteAuxclasspath(LinkageError e) and maybe other overloads; and have a single place to extract the missing class FQCN, and store it in a Set.

After analysis, we can dump these into the Report before rendering, thus saving us from sprinkling all the codebase with accesses to Report.

Notice, another benefit of this approach is that introduces no breaking API changes, so we can do it on master at any time.

@jsotuyod jsotuyod mentioned this pull request Oct 5, 2019
2 tasks
@oowekyala

Copy link
Copy Markdown
Member

@jsotuyod I don't really like that approach.

  1. The AstAnalysisConfiguration refers to a single file, and not generally to the current analysis.

TBH I think we should add a getLanguageVersion() to the Node interface and stop carrying around in ThreadLocals in RuleContext or so. A node isn't going to change its language, and if a node doesn't know its own language, then we can't support embedded languages. So we can remove that from the AstAnalysisContext anyway. (Same for the RuleContext#getCurrentFile. It should be accessible on the RootNode).

If we do that then the analysis context is not specific to a file anymore, and it's basically your AnalysisContext

  1. We know from experience, some missing classes may not be found during preprocessing, but during rule analysis, hence we have code as this in rules such as MissingOverrideRule

I don't think we should base any work on this hypothesis. If we have a richer data model for symbol/type resolution, that rule doesn't need to process Class objects. Same thing for eg UnnecessaryFullyQualifiedName and such. I'd rather shift the responsibility of processing Class objects away from rules, because that will simplify them, and allow sharing insight between all rules. I've already written about that extensively in #1566 and in our meeting briefs so won't go back into that.

  1. At some point we may want type res to be lazy,

This is irrelevant. Making it lazy doesn't mean we can't use a context object. We could have a lazy type resolver object per compilation unit, created with a context object.

noteIncompleteAuxclasspath(LinkageError e)

I think passing around a special logger object would be more general and scale better. Eg with methods like recoverableException(Throwable t); warn(String message);, etc, which would be handled in a generic way (maybe merging stack traces of the same exceptions, which btw would also be useful for exceptions occuring in rules). Using java.util.logging.Logger is easy but everything is static, so once again not analysis-scoped.

In general I think "more threadlocals" shouldn't ever be a long term design, precisely because we don't know exactly how PMD is executed outside of our codebase. It makes data ownership obscure, makes the app harder to understand. Reifying global things into context objects and passing them around is a much better place to start from I think. There are not many places where the parameter passing is needed, and nearly all of them are in the internals of PMD, which is internal API.

@adangel

adangel commented Jan 17, 2023

Copy link
Copy Markdown
Member Author

Closing this without merging it. It is irrelevant, will be replaced by a solution for #3914.

@adangel adangel closed this Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a:RFC A drafted proposal on changes to PMD, up for feedback form the team and community is:WIP For PRs that are not fully ready, or issues that are actively being tackled

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants