This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Handle unresolved scope specifier when fixing includes.
ClosedPublic

Authored by ioeric on Feb 13 2019, 8:00 AM.

Details

Summary

In the following examples, "clangd" is unresolved, and the fixer will try to fix
include for clang::clangd; however, clang::clangd::X is usually intended. So
when handling a qualifier that is unresolved, we change the unresolved name and
scopes so that the fixer will fix "clang::clangd::X" in the following example.

  namespace clang {
  	clangd::X
	~~~~~~
  }
  // or
  clang::clangd::X
         ~~~~~~

Diff Detail

Repository
rL LLVM

Event Timeline

ioeric created this revision.Feb 13 2019, 8:00 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 13 2019, 8:00 AM
ioeric updated this revision to Diff 186674.Feb 13 2019, 8:02 AM
  • Remove unintended change.
ioeric edited the summary of this revision. (Show Details)Feb 13 2019, 8:02 AM
Harbormaster completed remote builds in B28103: Diff 186674.
sammccall added inline comments.Feb 18 2019, 2:30 AM
clangd/IncludeFixer.cpp
208 ↗(On Diff #186674)

No idea when this can be invalid, but we could just return here?

211 ↗(On Diff #186674)

We can be more precise about this now I think: IIUC this is the resolved specified scope.
in two senses: it's the part of what was typed that was resolved, and it's in its resolved form not its typed form (think namespace clang { clangd::x } --> clang::clangd::)

212 ↗(On Diff #186674)

nit: I don't think this is an example, it's the only case right?

Consider calling this UnresolvedSpecifiedScope

213 ↗(On Diff #186674)

nit: qualier -> qualifier
accissible -> accessible

216 ↗(On Diff #186674)

I'm a bit concerned about how this mixes extraction of scopes from the source code/AST (which is now *really* complicated) with building the query and assembling the correction.

Can we reasonably extract the former to a helper function? Not sure exactly what the signature would be, but it would be helpful to find out.

The other thing is I think this has a lot in common with the scope-wrangling code in CodeComplete, and could *maybe* be unified a bit once isolated.

235 ↗(On Diff #186674)

hmm, won't this heuristic have false positives?

// indexed-header.h
namespace a { int X; }

// main-file.cc
namespace b = a;
namespace c { int Y = b::x; }

I worry spelling is going to be "b::" here, while SpecifiedNS is going to be "a::".

315 ↗(On Diff #186674)

identifiers

320 ↗(On Diff #186674)

this only depends on the params right?
This could be static or even moved out of the class.

ioeric updated this revision to Diff 187222.Feb 18 2019, 4:39 AM
ioeric marked 9 inline comments as done.
  • address review comments
ioeric added inline comments.Feb 18 2019, 4:39 AM
clangd/IncludeFixer.cpp
235 ↗(On Diff #186674)

Thanks for pointing this out! I completely missed the namespace alias case. Fixed and added a test.

sammccall accepted this revision.Feb 18 2019, 10:29 AM

Thanks! The layering is *much* clearer now.
I can still suggest a couple of tweaks, but they're pretty much cosmetic.

clangd/IncludeFixer.cpp
190 ↗(On Diff #187222)

you're showing a range here, it should be a point though?

191 ↗(On Diff #187222)

this isn't wrong per se (conservative, bails out e.g. on unicode)
But is it much harder to call Lexer::findNextToken twice and expect a raw identifier and ::?

231 ↗(On Diff #187222)

Unrsolved -> Unresolved

emphasis might be clearer as UnresolvedIsSpecifier - there's always an unresolved entity, the boolean is indicating that it's a specifier

256 ↗(On Diff #187222)

I don't think this vlog is useful as-is (quite far down the stack with no context)
Did you intend to remove it?

322 ↗(On Diff #187222)

Following up on our offline discussion :-)
I think that since extractSpecifiedScopes can want to modify the name, we should just expand that function's signature/responsibility to always determine the name.

So we'd pass the const DeclarationNameInfo& to extractSpecifiedScopes, and it would return a struct {optional<string> ResolvedScope; optional<string> UnresolvedScope; string Name}.
Maybe need to call them CheapUnresolvedName/extractUnresolvedNameCheaply or similar.
But I think the code change is small.

This revision is now accepted and ready to land.Feb 18 2019, 10:29 AM

Hi Eric, I have just couple details.

clangd/IncludeFixer.cpp
188 ↗(On Diff #187222)

qualfied -> qualified

193 ↗(On Diff #187222)

It seems to me that calling Lexer would be better indeed.

216 ↗(On Diff #187222)

Maybe move the comment about work done eagerly to the function?

251 ↗(On Diff #187222)

Does this work with anonymous namespaces?

263 ↗(On Diff #187222)

I'd personally prefer to add parentheses here to have the if/else if/else consistent. Up to you though.

271 ↗(On Diff #187222)

Is the term qualifier applicable here? (Honest question.)

It seems like C++ grammar uses specifier (same as you in IsUnrsolvedSpecifier )
http://www.nongnu.org/hcb/#nested-name-specifier

unittests/clangd/DiagnosticsTests.cpp
452 ↗(On Diff #187222)

If (see above) we decide qualifier should be replaced by specifier or smth else please replace here as well, otherwise ignore this.

ioeric updated this revision to Diff 187343.Feb 19 2019, 3:57 AM
ioeric marked 16 inline comments as done.
  • address review comment
clangd/IncludeFixer.cpp
191 ↗(On Diff #187222)

Good idea. Lexer is a better option.

251 ↗(On Diff #187222)

I'm not sure... how do you use an anonymous namespace as a scope specifier?

256 ↗(On Diff #187222)

Indeed. Thanks for the catch!

271 ↗(On Diff #187222)

You've raised a good point. We've been using specifier and qualifier interchangeably in the project. But specifier does seem to be a more appropriate name to use. I've fixed uses in this file. Uses in other files probably need a separate cleanup.

322 ↗(On Diff #187222)

Sounds good. Thanks!

ioeric updated this revision to Diff 187359.Feb 19 2019, 6:30 AM
  • minor cleanup
This revision was automatically updated to reflect the committed changes.
Herald added a project: Restricted Project. · View Herald TranscriptFeb 19 2019, 6:31 AM