This is an archive of the discontinued LLVM Phabricator instance.

[Clangd] Make the type hint length limit configurable
ClosedPublic

Authored by zhangyi1357 on Apr 1 2023, 8:06 PM.

Details

Summary

[Clangd] Make the type hint length limit configurable

This commit is about clangd's type name hint length limit. The past behavior was 32 characters fixed limit. It is now configurable.

Projects can now add the following config fragment to their .clangd:

InlayHints:
  TypeNameLimit: 34

Ref: Make the type hint length limit configurable

Diff Detail

Event Timeline

zhangyi1357 created this revision.Apr 1 2023, 8:06 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 1 2023, 8:06 PM
zhangyi1357 requested review of this revision.Apr 1 2023, 8:06 PM
zhangyi1357 edited the summary of this revision. (Show Details)Apr 1 2023, 8:23 PM
zhangyi1357 added a reviewer: sammccall.
zhangyi1357 edited the summary of this revision. (Show Details)Apr 1 2023, 8:32 PM

Format code modified using clang format.

hokein added a comment.Apr 3 2023, 4:01 AM

Thanks for the contribution!

clang-tools-extra/clangd/Config.h
151

I would extend it a bit more -- 0 means no limit.

Can you also add a unittest in TEST(TypeHints, LongTypeName) in InlayHintTests.cpp?

clang-tools-extra/clangd/ConfigFragment.h
326

if we add uint32Value method (see my other comment), then the type is std::optional<Located<uint32_t>>.

clang-tools-extra/clangd/ConfigYAML.cpp
258

Similar to the boolValue, I think it would be better to have a uint32Value method (this is the first time that we have an integer in the config), something like below

 std::optional<Located<uint32_t>> uint32Value(Node &N, llvm::StringRef Desc) {
   if (auto Scalar = scalarValue(N, Desc)) {
        unsigned long long n;
        if (getAsUnsignedInteger(Scalar, 0, n)) {
           warning(Desc + "invalid number", N);
           return;
        }
        return Located<uint32_t>(n, Scalar->Range);
    }
    return std::nullopt;
}

Add uint32Value() for uint32_t type parsing in config file.
For TypeNameLimit config, support no limit with value 0.

zhangyi1357 marked 2 inline comments as done.Apr 3 2023, 8:38 AM
This comment was removed by zhangyi1357.
clang-tools-extra/clangd/Config.h
151

0 means no limit.

This is quite a good idea. I've done it.

For unittest, there is already TEST(TypeHints, LongTypeName) in InlayHintTests.cpp. Do you mean add more tests in the same TEST or another TEST with TypeNameLimit configured?

zhangyi1357 marked an inline comment as not done.

Try to fix the build problem.

Thanks for the contribution!

It's quite interesting for me. Thanks for your time reviewing and your great advice!

hokein added inline comments.Apr 4 2023, 1:04 AM
clang-tools-extra/clangd/Config.h
151

I mean adding one more test in the same TEST(TypeHints, LongTypeName).

This test verifies the the long type name is shown when the limit is set to 0, something like

TEST(TypeHints, LongTypeName) {
  assertTypeHints(R"cpp(
    template <typename, typename, typename>
    struct A {};
    struct MultipleWords {};
    A<MultipleWords, MultipleWords, MultipleWords> foo();
    // Omit type hint past a certain length (currently 32)
    auto var = foo();
  )cpp");

    Config cfg; 
     ... // set the limit to 0

   assertTypeHints(R"cpp(
    template <typename, typename, typename>
    struct A {};
    struct MultipleWords {};
    A<MultipleWords, MultipleWords, MultipleWords> foo();
    // Omit type hint past a certain length (currently 32)
    auto var = foo();
  )cpp", ExpectedHint...);
}
  • [Clangd] Add unittest for TypeNameLimit config
hokein accepted this revision.Apr 5 2023, 12:28 AM

Thanks, looks good with a nit.

clang-tools-extra/clangd/unittests/InlayHintTests.cpp
80

why do we need this change? I think it should be fine without it.

This revision is now accepted and ready to land.Apr 5 2023, 12:28 AM
zhangyi1357 marked 2 inline comments as done.
  • [Clangd] Remove unneccessary modification
zhangyi1357 marked an inline comment as done.

Combine mutiple commits into single one

I dont have commit access. Could you help committing the change for me? @hokein

clang-tools-extra/clangd/Config.h
151

Thanks for your example! I've added that.

clang-tools-extra/clangd/unittests/InlayHintTests.cpp
80

Yes, without this line the tests will not fail. But I am a little confused about the code below without 'C.InlayHints.TypeNameLimit = 1;'.

Config noHintsConfig() {
  Config C;
  C.InlayHints.Parameters = false;
  C.InlayHints.DeducedTypes = false;
  C.InlayHints.Designators = false;
  // C.InlayHints.TypeNameLimit = 1;
  return C;
}

template <typename... ExpectedHints>
void assertHints(InlayHintKind Kind, llvm::StringRef AnnotatedSource,
                 ExpectedHints... Expected) {
  Annotations Source(AnnotatedSource);
  TestTU TU = TestTU::withCode(Source.code());
  TU.ExtraArgs.push_back("-std=c++20");
  auto AST = TU.build();

  EXPECT_THAT(hintsOfKind(AST, Kind),
              ElementsAre(HintMatcher(Expected, Source)...));
  // Sneak in a cross-cutting check that hints are disabled by config.
  // We'll hit an assertion failure if addInlayHint still gets called.
  WithContextValue WithCfg(Config::Key, noHintsConfig());
  EXPECT_THAT(inlayHints(AST, std::nullopt), IsEmpty());  // Why does this succeed with TypeNameLimit = 32 ?
}

TEST(TypeHints, Smoke) {
  assertTypeHints(R"cpp(
    auto $waldo[[waldo]] = 42;
  )cpp",
                  ExpectedHint{": int", "waldo"});
}

The dault TypeNameLimit is 32, why does the second EXPECT_THAT succeed with TypeNameLimit = 32.

I dont have commit access. Could you help committing the change for me? @hokein

sure, I will land it for you (sorry for the late response).

clang-tools-extra/clangd/unittests/InlayHintTests.cpp
80

The second EXPECT_THAT(inlayHints(AST, std::nullopt), IsEmpty()); is expected, because we have disabled the inlay-hint by the previous statement WithContextValue WithCfg(Config::Key, noHintsConfig());, so the expected result is empty.

This revision was automatically updated to reflect the committed changes.