This is an archive of the discontinued LLVM Phabricator instance.

[clangd] DefineInline action availability checks
ClosedPublic

Authored by kadircet on Jul 30 2019, 1:44 AM.

Event Timeline

kadircet created this revision.Jul 30 2019, 1:44 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 30 2019, 1:44 AM
sammccall added inline comments.Aug 28 2019, 8:20 AM
clang-tools-extra/clangd/unittests/TweakTests.cpp
53

This function, and all the other helpers in this file, are actually imminently going away in favor of TweakTesting.h.
Sorry it's been stuck in my backlog for a couple of weeks...

We should work out how to do that stuff there.
One approach is to give TweakTest a StringMap<string> ExtraFiles and StringMap<string> EditedFiles that excludes main, so you'd write

ExtraFiles["foo.h"] = "...";
EXPECT_EQ(apply("..."), "...");
EXPECT_THAT(EditedFiles, ElementsAre(Pair(testPath("foo.h"), "...");

or something like this.

(Whatever we do, we should bear in mind the fact that out-line will mean we need to supply an index too)

545

I don't think so

567

nit: NoForwardDecl

597

FWIW, I find these params rather cryptic - it'd be nice to have an API for the helpers that is explicit about this being files/filenames

kadircet updated this revision to Diff 218936.Sep 5 2019, 9:14 AM
kadircet marked 4 inline comments as done.
  • Rebase and address comments

When fully implemented, will define inline tweak work with C++ methods in classes as well?
E.g.

HEADER:
class Foo { void foo(); }
CPP:
#include "Header.h"
void Foo::foo() {}

becomes:

HEADER:
class Foo { void foo() { } }
CPP:
#include "Header.h"
clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
192

Sorry, I'm not really familiar with design of tweaks, so this might be a bad question: Is it possible to change the title of the tweak on a per-TU basis. More specifically, some tweaks might want to have different titles for Objective-C actions compared to their C++ siblings.

kadircet marked an inline comment as done.Sep 9 2019, 12:34 AM

When fully implemented, will define inline tweak work with C++ methods in classes as well?

Yes you can see an example of it in the tests provided in TweakTests.cpp

clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
192

Current design returns a constant string per tweak, but we can change that behaviour easily by making this a function of language options. You can take a look at ClangdServer::enumerateTweaks for details.

sammccall added inline comments.Sep 9 2019, 12:57 AM
clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
192

This isn't quite true: id() must be constant but title() need not be. See ExpandMacro for an example.

The only constraint is it shouldn't be terribly expensive (this is why ExpandAuto doesn't include the type in the title, due to an AST bug it requires a new traversal).

More specifically, some tweaks might want to have different titles for Objective-C actions compared to their C++ siblings.

I think this is possible and the right idea. But for completeness I should mention: having multiple Tweak subclasses that share implementation is also possible. In particular in cases where you have two related actions and may want to provide *both* as options (maybe extract function vs method?), they'd need to be separate subclasses. (Or we'd need to change the design a bit)

arphaman added inline comments.Sep 9 2019, 1:11 PM
clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
192

Oh yes, I think it's probably better to use the Tweak subclasses like you said. This will be better for ObjC++, which could have either a C++ or an ObjC tweak available depending on the current AST selection.

hokein added inline comments.Sep 18 2019, 3:27 AM
clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
65

nit: maybe use auto?

78

thinking this a bit more, the function is non-trivial, we probably want unit test for it.

105

IIUC, I believe this function relies on the flag "Opts.IndexFunctionLocals"? could we spell it explicitly in the code even its default value false fits our use case.

113

hmm, looks like we don't use TargetContext in the implemenation at all. Is the comment out-of-date now?

141

we are distinguishing two cases here: normal functions and the class methods. Could we make the code handle these two cases separately? e.g.

if (Class) {
   // check whether they are in the same class;
} else { // handle normal function
  // call isBeforeInTranslation
}
160

function template is tricky, I may be not aware of the context, what's our plan for supporting it? could you give an concrete example? it seems that the current unit test doesn't cover it.

172

I believe it also works for class methods?

183

now we get a potential ODR violation in this example, maybe choose a different example?

224

The tweak is under development, do we need to hide it until it is completed?

clang-tools-extra/clangd/unittests/TweakTests.cpp
25

the header seems irrelevant to me.

709

The a.h seems to be non-existed unless you explicitly set it via ExtraFiles["a.h"]?

kadircet updated this revision to Diff 220821.Sep 19 2019, 12:19 AM
kadircet marked 17 inline comments as done.
  • Address comments
clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
78

agreed, sent out D67748

113

we are still checking its visibility in target context, but without making use of declcontext. Updating the comment.

160

Yes we plan to support them, added a test case thanks for pointing it out.

This basically ensures that we select the correct decl in the case of template spec decls, because canonical decl is function template itself, instead of the specialization decl.

183

You are right, but we cannot get away from it by changing the example. Adding an "inline " instead, and I believe that's what we should do if we are moving a function definition to a header.

224

I wasn't planning to land it before all of its dependencies are LGTM'd, but marking it as hidden just in case.

mostly good to me, a few more comments.

clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
156

maybe name it findTarget? I think the function is used to find a potential target decl which the definition will be moved to, Canonical doesn't provide much information here.

160

We may get a nullptr if FD is the first declaration, I think we need to handle the nullptr case, otherwise the check will crash.

183

I think not all cases will need inline, e.g. class method, or function template(?). Fix these problems is out-scope of the tweak (there is a clang-tidy check handling this case), and probably add complexity to the implementation. I'm leaning on not fixing it.

Maybe a better example is class method?

185

I'm not sure Inline function definition is a widely-known refactoring term, I think "Move function definition to declaration" is probably easier for normal C++ developers to understand?

clang-tools-extra/clangd/unittests/TweakTests.cpp
713

I think we missing a basic test where a declaration is in the header and it can be moved?

Header = "void foo();"
Main = "void f^oo() { // no dependency code }"

kadircet updated this revision to Diff 221270.Sep 23 2019, 2:20 AM
kadircet marked 5 inline comments as done.
  • Address comments
clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
160

theoretically, a template specialization cannot be the first decl, as one needs to declare function template first.
making this more clear by changing this into a loop that finds the first forward declaration for the specialization.

183

yes clang-tidy can generate those fixes but I believe a code-action should not generate code that relies on a clang-tidy check to fix it.

clang-tools-extra/clangd/unittests/TweakTests.cpp
713

isn't it covered by the next testcase ?

hokein accepted this revision.Sep 23 2019, 4:56 AM

looks good with a few nits.

clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
154

nit: the comment is out of date with the new change?

183

I'm still not convinced that we should fix it in the check. but we don't have to solve it out in this patch, could we remove the inline from the sample? (adding it now seems to confuse users, we don't support it yet).

clang-tools-extra/clangd/unittests/TweakTesting.h
52

nit: add a comment // file name => file content.

clang-tools-extra/clangd/unittests/TweakTests.cpp
713

ah, sorry, I missed that.

This revision is now accepted and ready to land.Sep 23 2019, 4:56 AM
kadircet updated this revision to Diff 221314.Sep 23 2019, 6:03 AM
kadircet marked 7 inline comments as done.
clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
183

we basically support nothing in that sample in this patch, it is just to reflect the end-state of the code-action.
but as you wish; deleting it now, and instead adding with the next patch(that implements apply).

kadircet updated this revision to Diff 221910.Sep 26 2019, 4:15 AM
  • Rebase and update testhelpers
kadircet updated this revision to Diff 221911.Sep 26 2019, 4:17 AM
  • Revert miscommit
kadircet updated this revision to Diff 221947.Sep 26 2019, 7:36 AM
  • Use canonical decl when checking visibility
kadircet updated this revision to Diff 222158.Sep 27 2019, 6:11 AM
  • Rebase and bail out on methods inside templated classes
This revision was automatically updated to reflect the committed changes.
thakis added a subscriber: thakis.Oct 25 2019, 9:00 AM

The test fails in Windows: http://45.33.8.238/win/1112/step_7.txt

Ptal, and if it takes a while to investigate please revert while you look.