This is an archive of the discontinued LLVM Phabricator instance.

[clang-tidy] Extract Class IncluderClangTidyCheck
AbandonedPublic

Authored by LegalizeAdulthood on Jan 12 2022, 10:18 AM.

Details

Summary

IncluderClangTidyCheck is a base class for checks that
want to insert include files as part of their fixits.

IncluderClangTidyCheck::storeOptions should be called
first by any derived classes that override storeOptions.

IncluderClangTidyCheck::registerPPCallbacks should be
called first by any derived classes that override
registerPPCallbacks and perform additional preprocessor
logic.

Switch the following classes to use IncluderClangTidyCheck:

  • abseil::StringFindStartswithCheck
  • bugprone::ImplicitWideningOfMultiplicationResultCheck
  • cppcoreguidelines::InitVariablesCheck
  • cppcoreguidelines::ProBoundsCOnstantArrayIndexCheck
  • misc::UniqueptrResetReleaseCheck
  • modernize::LoopConvertCheck
  • modernize::MakeSmartPtrCheck
  • modernize::PassByValueCheck
  • modernize::ReplaceAutoPtrCheck
  • modernize::ReplaceRandomShuffleCheck
  • performance::TypePromotionInMathFnCheck
  • performance::UnnecessaryValueParamCheck
  • utils::TransformerClangTidyCheck

Diff Detail

Event Timeline

LegalizeAdulthood requested review of this revision.Jan 12 2022, 10:18 AM

Overall, this change looks good and makes sense. But, it doesn't scale past 1 feature, which makes me a bit hesitant. I don't have another example offhand, but include-inserter is an arbitrary feature and I don't love conflating feature addition with the class hierarchy. Might there be some other way to get the benefits of saving implementers the cut and paste (and bug-prone code that comes with it) without changing the class hierarchy?

clang-tools-extra/clang-tidy/utils/TransformerClangTidyCheck.h
13

can you delete this?

Overall, this change looks good and makes sense. But, it doesn't scale past 1 feature
[...] Might there be some other way to get the benefits of saving implementers the
cut and paste (and bug-prone code that comes with it) without changing the class
hierarchy?

Maybe some sort of mix-in approach or "implementation inheritance" as they say?

Another option would be to migrate this to ClangTidyCheck itself
and add a flag/option passed to the ClangTidyCheck c'tor to opt-in
to the feature?

Another option would be to migrate this to ClangTidyCheck itself
and add a flag/option passed to the ClangTidyCheck c'tor to opt-in
to the feature?

Right, I was wondering about this. The feature is pretty core to handling C++ files and widely used, so it may warrant that. But, I don't know who the right reviewers are to ask about making changes to the ClangTidyCheck class.

Another option would be to migrate this to ClangTidyCheck itself
and add a flag/option passed to the ClangTidyCheck c'tor to opt-in
to the feature?

I feel that this direction is much better, Its something I wanted to introduce a while back, but my work was getting in the way.
My proposed idea was putting the IncludeInserter instance inside the ClangTidyContext, but then only registering it if any checks actually want to use it.

My proposed idea was putting the IncludeInserter instance
inside the ClangTidyContext, but then only registering it if
any checks actually want to use it.

Use of the IncludeInserter would be signaled by an argument
to the ctor fo r`ClangTidyCheck` in the c'tor for the derived
class?

My proposed idea was putting the IncludeInserter instance
inside the ClangTidyContext, but then only registering it if
any checks actually want to use it.

Use of the IncludeInserter would be signaled by an argument
to the ctor fo r`ClangTidyCheck` in the c'tor for the derived
class?

There is a hurdle to overcome with this, Currently each check can have its own include style - which doesn't really make sense. Hopefully people actually just use the global version of the option instead.
However if we were to coalesce all checks to use the same IncludeInserter, we would have to force clang-tidy to just read the global version.
Going this route it'd be best if we warned on configs that specify their own IncludeStyle. I've created a draft implementation above, definitely needs work though.

Eliminate an intermediate class and move the IncludeInserter
functionality into ClangTidyCheck with an enum to indicate
opt-in to use of the IncludeInserter.

There is a hurdle to overcome with this, Currently each check can have its own include style - which doesn't really make sense. Hopefully people actually just use the global version of the option instead.
However if we were to coalesce all checks to use the same IncludeInserter, we would have to force clang-tidy to just read the global version.
Going this route it'd be best if we warned on configs that specify their own IncludeStyle. I've created a draft implementation above, definitely needs work though.

I pushed the functionality down into ClangTidyCheck
instead of introducing an intermediate class. Does this
address your concern?

I pushed the functionality down into ClangTidyCheck
instead of introducing an intermediate class. Does this
address your concern?

This is a step backwards. Now every check is paying for an IncludeInserter that most never use. I've put D117409 up that, despite being a little rough round the edges, solves the problem in a way where there is only 1 shared Inserter.

I added some comments on the other review.

Is constructing an IncludeInserter particularly expensive?
I'm just curious.

My proposed idea was putting the IncludeInserter instance
inside the ClangTidyContext, but then only registering it if
any checks actually want to use it.

Use of the IncludeInserter would be signaled by an argument
to the ctor fo r`ClangTidyCheck` in the c'tor for the derived
class?

There is a hurdle to overcome with this, Currently each check can have its own include style - which doesn't really make sense.

Hmm, I think it could make sense for sizeable projects that have components written by separate teams. Granted, I think it's a bit of a strange situation, but I wouldn't go so far as to say it doesn't make sense.

There is a hurdle to overcome with this, Currently each check can have its own include style - which doesn't really make sense.

Hmm, I think it could make sense for sizeable projects that have components written by separate teams. Granted, I think it's a bit of a strange situation, but I wouldn't go so far as to say it doesn't make sense.

I'm not saying that different teams having different include styles doesn't make sense. I'm saying one translation unit that runs multiple checks with IncludeInserters where they have different styles doesn't make sense.
That could result in each check trying to create includes in the same file, but assuming a different include style.

There is a hurdle to overcome with this, Currently each check can have its own include style - which doesn't really make sense.

Hmm, I think it could make sense for sizeable projects that have components written by separate teams. Granted, I think it's a bit of a strange situation, but I wouldn't go so far as to say it doesn't make sense.

I'm not saying that different teams having different include styles doesn't make sense. I'm saying one translation unit that runs multiple checks with IncludeInserters where they have different styles doesn't make sense.
That could result in each check trying to create includes in the same file, but assuming a different include style.

Oh, I see what you mean now: include sort orders that battle one another. Yeah, that is a situation that seems worth warning the user about. Thanks for clarifying!