This is an archive of the discontinued LLVM Phabricator instance.

[clangd] #include statements support for Open definition
ClosedPublic

Authored by Nebiroth on Oct 6 2017, 11:11 AM.

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
ilya-biryukov added inline comments.Oct 9 2017, 5:25 AM
clangd/ClangdUnit.cpp
162

Please use our descriptive Path typedef.

unittests/clangd/ClangdTests.cpp
991 ↗(On Diff #118046)

Some includes may come outside of preamble, I would expect current implementation to fail for this case:

#include <vector> // <-- works here 
// preamble ends here
int main() {

  #include "my_include.h" // <-- does not work here
}
Nebiroth marked 21 inline comments as done.Oct 16 2017, 1:51 PM
Nebiroth added inline comments.
clangd/ClangdUnit.cpp
149

If I were to use InclusionDirective , how would that callback be called automatically? As far as I know, it wouldn't be called automatically for every file that gets indexed the same way AfterExecute would be.

Nebiroth marked an inline comment as done.Oct 16 2017, 1:56 PM
ilya-biryukov added inline comments.Oct 23 2017, 5:22 AM
clangd/ClangdUnit.cpp
149

It will be called for each #include directive that Preprocessor encountered while building the preamble.
A separate instance of CppFilePreambleCallbacks is created every time we build a preamble for file.

Does that answer your question?

Nebiroth updated this revision to Diff 120482.Oct 26 2017, 1:58 PM
Nebiroth edited edge metadata.
  • Now overriding InclusionDirective as a callback to get proper includes information.
  • Fixed tests.
Nebiroth updated this revision to Diff 120485.EditedOct 26 2017, 2:00 PM
  • Fixed adding incorrect test file.

This revision requires modifications to clang which can be reviewed on revision D39375.

I'm not sure it's better to use the InclusionDirective callback for this. We need to get the includes in two places: in the preamble and non-preamble. In the preamble we use the callback, have to store some temporary stuff because we don't have a SourceManager in InclusionDirective, then in finish we use the SourceManager to convert everything. In the non-preamble, we cannot use the callback so we use the SourceManager to go through the includes. Therefore, we have to maintain two different ways of getting the inclusion map. Without using the InclusionDirective callback, we use the SourceManager in both cases and can use the same code to iterate through inclusions, just on two different SourceManagers at different moments. We also don't need to make another patch to modify the PreambleCallbacks. I also double this is much slower but I think this simplifies the code nicely.
What do you think?

I'm not sure it's better to use the InclusionDirective callback for this. We need to get the includes in two places: in the preamble and non-preamble. In the preamble we use the callback, have to store some temporary stuff because we don't have a SourceManager in InclusionDirective, then in finish we use the SourceManager to convert everything. In the non-preamble, we cannot use the callback so we use the SourceManager to go through the includes. Therefore, we have to maintain two different ways of getting the inclusion map. Without using the InclusionDirective callback, we use the SourceManager in both cases and can use the same code to iterate through inclusions, just on two different SourceManagers at different moments. We also don't need to make another patch to modify the PreambleCallbacks. I also double this is much slower but I think this simplifies the code nicely.
What do you think?

I think we should never iterate through SourceManager, as it's much easier to get wrong than using the callbacks. I agree that all that fiddling with callbacks is unfortunate, but it's well worth the fact that it'd be much easier to tell that the implementation is correct by simply looking at the implementation and not knowing how SourceManager works. PPCallbacks is a much more direct API that was designed to handle our purposes.

Note that we don't need to use SourceManager to find non-preamble includes, we should implement proper PPCallbacks and use them when building the AST.

ilya-biryukov added inline comments.Nov 9 2017, 7:16 AM
clangd/ClangdServer.cpp
368 ↗(On Diff #120485)

This map and two vectors come up quite often in your commit.
Is this a storage for saved includes? Could we define a class that stores this data?

Something like

class IncludeReferenceMap {
  llvm::Optional<PathRef> findIncludeTargetAtLoc(Location Loc);

private:
// maps, vectors, whatever we need go here ....
};

We'd build it using the callbacks, then store it in PreambleData (for PCH include) and ParsedAST (for non-PCH includes). And later query both maps to get the result.

clangd/ClangdUnit.cpp
31

We probably don't need it this include

35

What's the purpose of this class?

157

Please also use PPCallbacks interface instead of the SourceManager (should be possible to hook it up somewhere in ParsedAST::Build).

ilya-biryukov requested changes to this revision.Nov 9 2017, 7:16 AM
This revision now requires changes to proceed.Nov 9 2017, 7:16 AM

I think we should never iterate through SourceManager, as it's much easier to get wrong than using the callbacks. I agree that all that fiddling with callbacks is unfortunate, but it's well worth the fact that it'd be much easier to tell that the implementation is correct by simply looking at the implementation and not knowing how SourceManager works. PPCallbacks is a much more direct API that was designed to handle our purposes.

Note that we don't need to use SourceManager to find non-preamble includes, we should implement proper PPCallbacks and use them when building the AST.

Sounds good!

Nebiroth marked an inline comment as done.Dec 5 2017, 2:16 PM
Nebiroth added inline comments.
clangd/ClangdUnit.cpp
35

We need to be able to use a wrapper class to be able to make a unique_ptr to be sent to PrecompiledPreamble::Build in order to add the list of preprocessor Callbacks.

Nebiroth updated this revision to Diff 125813.Dec 6 2017, 2:15 PM
Nebiroth edited edge metadata.

Using PPCallbacks interface to find non-preamble includes
Created inner class to store vectors in to find locations
Refactored methods to remove some unnecessary parameters
Refactored Unit tests
Merge with most recent master branch + clang

Nebiroth updated this revision to Diff 125814.Dec 6 2017, 2:17 PM

Fixed re-added include

ilya-biryukov added inline comments.Dec 8 2017, 3:30 AM
clangd/ClangdUnit.cpp
35

Could we implement an instance of PPCallbacks that contains CppFilePreambleCallbacks and forwards to that specific method instead?

The reason is that we're not really delegating other methods in this calls(nor should we, the implementation would be too compilcated).
Having a class that contains CppFilePreambleCallbacks &Collector and calling Collector.InclusionDirective seems perfectly fine, though: its purpose is clear and the implementation is easy.

Nebiroth updated this revision to Diff 126429.Dec 11 2017, 12:55 PM
Creating unique_ptr for wrapper class now uses overriden method createPPCallbacks() from PrecompiledPreamble class
Moved wrapper class to inline inside createPPCallbacks()
Wrapper class now uses CppFilePreambleCallbacks as field
malaperle requested changes to this revision.Dec 14 2017, 9:03 PM
malaperle added inline comments.
clangd/ClangdServer.cpp
454 ↗(On Diff #126429)

IncludeReferenceMap & here? See other comment in takeIRM

clangd/ClangdUnit.cpp
31

remove

121

remove

128

These need to be swapped to be in the same order that they are declared below.

130

I don't think we need this if we pass the map by reference (and store it as a reference, see other comment)

137

Remove (see previous comment)

140

remove

157

I tried to simply the methods introduced here:

void AfterExecute(CompilerInstance &CI) override {
  SourceMgr = &CI.getSourceManager();
  for (auto InclusionLoc : TempPreambleIncludeLocations)
    addIncludeLocation(InclusionLoc);
}

void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,
                        StringRef FileName, bool IsAngled,
                        CharSourceRange FilenameRange, const FileEntry *File,
                        StringRef SearchPath, StringRef RelativePath,
                        const Module *Imported) override {
  auto SR = FilenameRange.getAsRange();
  if (SR.isInvalid() || !File || File->tryGetRealPathName().empty())
    return;

  if (SourceMgr) {
    addIncludeLocation({SR, File->tryGetRealPathName()});
  } else {
    // When we are processing the inclusion directives inside the preamble,
    // we don't have access to a SourceManager, so we cannot convert
    // SourceRange to Range. This is done instead in AfterExecute when a
    // SourceManager becomes available.
    TempPreambleIncludeLocations.push_back({SR, File->tryGetRealPathName()});
  }
}

void addIncludeLocation(std::pair<SourceRange, std::string> InclusionLoc) {
  // Only inclusion directives in the main file make sense. The user cannot
  // select directives not in the main file.
  if (SourceMgr->getMainFileID() == SourceMgr->getFileID(InclusionLoc.first.getBegin()))
    IRM.insert({getRange(InclusionLoc.first), InclusionLoc.second});
}

Range getRange(SourceRange SR) {
  Position Begin;
  Begin.line = SourceMgr->getSpellingLineNumber(SR.getBegin());
  Begin.character = SourceMgr->getSpellingColumnNumber(SR.getBegin());
  Position End;
  End.line = SourceMgr->getSpellingLineNumber(SR.getEnd());
  End.character = SourceMgr->getSpellingColumnNumber(SR.getEnd());
  return {Begin, End};
}
162

IncludeReferenceMap &IRM;

That way, we can use the same map and pass it multiple times to different "collectors".

179

I think we need a "is main file" check here. In case this is used on a AST with no preamble.

273

I don't think this change was brought back intentionally?

283–284

IncludeReferenceMap &IRM

311

unnecessary std::move

328

std::move(IRM)

339–340

I think after rebase, all this code in DeclarationLocationsFinder will need to be moved around, probably inside clangd::findDefinitions?

341
for (auto &IncludeLoc : IncludeLocationMap) {
  Range R = IncludeLoc.first;
  if (isSameLine(R.start.line))
    addLocation(URI::fromFile(IncludeLoc.second), R);
}
348

Probably if an include location was found, we don't want to continue and it should early return.

474

I think you can put the construction of SerializedDeclsCollector back to where it was.

479

You can pass just IRM, so there is no need for the getIRM. We'll have eventually to transfer ownership to ParsedAST so maybe std::move(IRM) here?

clangd/ClangdUnit.h
63

With the map being the only field left (see other comments), there is no need for a class I think. Maybe make a handy type alias for this?

using IncludeReferenceMap = std::unordered_map<Range, Path, RangeHash>;
64

findIncludeTargetAtLoc is never used, remove

68

No need to keep this.

69

No need to keep this.

101

We need to keep this copy of IRM alive for subsequent calls to "open definition" for the same ParsedAST. So it is correct to not do a std::move here. However, I think it should be changed to:

IncludeReferenceMap &getIRM()

and also the caller should assign to a reference.

131

this wrongly came back?

unittests/clangd/ClangdTests.cpp
622 ↗(On Diff #126429)

why is this check removed?

751 ↗(On Diff #126429)

Need to test includes outside preamble.

778 ↗(On Diff #126429)

I get an "unchecked assertion" here before the Expected is not checked. I was able to replace it with:

auto ExpectedLocations = Server.findDefinitions(FooCpp, P);
ASSERT_TRUE(!!ExpectedLocations);
std::vector<Location> Locations = ExpectedLocations->Value;
784 ↗(On Diff #126429)

I get a test failure here.

../tools/clang/tools/extra/unittests/clangd/ClangdTests.cpp(785): Error:       Expected: check
      Which is: "clangd-test/foo."
To be equal to: FooH
      Which is: { '/' (47, 0x2F), 'c' (99, 0x63), 'l' (108, 0x6C), 'a' (97, 0x61), 'n' (110, 0x6E), 'g' (103, 0x67), 'd' (100, 0x64), '-' (45, 0x2D), 't' (116, 0x74), 'e' (101, 0x65), 's' (115, 0x73), 't' (116, 0x74), '/' (47, 0x2F), 'f' (102, 0x66), 'o' (111, 0x6F), 'o' (111, 0x6F), '.' (46, 0x2E), 'h' (104, 0x68) }

Not sure what's wrong. There is an additional front slash and missing ".h" at the end?

793 ↗(On Diff #126429)

Similar unchecked problem here, this works (although a bit yucky):

ExpectedLocations = Server.findDefinitions(FooCpp, P3);
ASSERT_TRUE(!!ExpectedLocations);
Locations = ExpectedLocations->Value;
EXPECT_TRUE(!Locations.empty());

// Test invalid include
Position P2 = Position{2, 11};

ExpectedLocations = Server.findDefinitions(FooCpp, P2);
ASSERT_TRUE(!!ExpectedLocations);
Locations = ExpectedLocations->Value;
EXPECT_TRUE(Locations.empty());
This revision now requires changes to proceed.Dec 14 2017, 9:03 PM
Nebiroth updated this revision to Diff 127161.Dec 15 2017, 10:58 AM
Nebiroth marked 27 inline comments as done.

inner class IncludeReferenceMap replaced by one map
fillRangeVector() and findPreambleIncludes() code moved into wrapper class
Open definition now returns an empty Range struct (line, character = 0)
Fixed unit tests
Minor code improvements

ilya-biryukov requested changes to this revision.Dec 18 2017, 2:22 AM
ilya-biryukov added inline comments.
clangd/ClangdServer.cpp
446 ↗(On Diff #127161)

We don't need this Preamble variable, right?

clangd/ClangdUnit.cpp
121

We don't need to derive this class from PPCallbacks, DelegatingPPCallbacks can call any method on it anyway as it knows the exact type. Please remove this inheritance.

127

Instead of passing SourceManager in constructor, maybe add a BeforeExecute(CompilerInstance &CI) method to PreambleCallbacks and set SourceManager when its called.

164

Adding BeforeExecute would allow to get rid of this vector.

214

NIT: replace with return llvm::make_unique<DelegatingPPCallbacks>(*this); and remove the local variable.

283–284

Let's store IncludeReferenceMap in ParsedAST instead of having it as out parameter.
It allows to properly manage the lifetime of IncludeReferenceMap (logically, it is exactly tied to the AST).

308

Why do we use CppFilePreambleCallbacks here? Factor the code that handles the references into a separate class and use it here:

class IncludeRefsCollector : public PPCallbacks {
public:
  IncludeRefsCollector(IncludeReferenceMap &Refs) : Refs(Refs) {}

   // implementation of PPCallbacks ...

private;
  IncludeReferenceMap &Refs;
};

/// .....
class CppFilePreambleCaallbacks {
public:
// ....

  std::unique_ptr<PPCallbacks> createPPCallbacks() { return llvm::make_unique<IncludeRefsCollector>(this->IRM); }
};

// ....
void ParsedAST::Build() {
  // ....
  // No need to create CppFilePreambleCallbacks here.
  Clang->getPreprocessor().addPPCallbacks(llvm::make_unique<IncludeRefsCollector>(IRM));
  //....
}
340

Use IncludeReferenceMap typedef here.

340

Do we change semantics of getting the file paths here? Maybe leave the code as is?

340

NIT: empty linke at the start of the function

342
  • use a typedef for the map here
  • accept the map by const reference to avoid copies
343

Let's check the the point is in range, not that it's not the same line. So that we don't trigger goto in strange places, like comments:

#include <vector> // this include is very important.  <--- we should not skip to include when editor caret is over a comment
343

If we store IncludeLocationMap in ParsedAST we don't need to change interface of this function.

345

This method does not seem particularly useful. One can construct location like this: Location{Uri, R}, the whole method can be written as DeclarationLocations.push_back(Location{Uri, R}).

clangd/ClangdUnit.h
63

We store a map, but only iterate through it in order. Let's use vector<pair<Range, Path>> instead.

This revision now requires changes to proceed.Dec 18 2017, 2:22 AM
Nebiroth updated this revision to Diff 127386.Dec 18 2017, 10:31 AM
Nebiroth marked 14 inline comments as done.
CppFilePreambleCallbacks no longer extends PPCallbacks
CppFilePreambleCallbacks no longer needs SourceManager parameter
Removed temporary vector TempPreambleIncludeLocations
IncludeReferenceMap in ParsedAST no longer passed by reference
Code handling includes outside of preambles is now separated in IncludeRefsCollector class
Removed addLocation
Changed isSameLine function name and now checks if searched location is in range instead of verifying the line
Removed changes to findDefinitions interface
ilya-biryukov requested changes to this revision.Dec 19 2017, 1:39 AM

Thanks for addressing the comments quickly.
I took another look and added a few more comments.
This moves in the right direction, though, this is really close to landing.

clangd/ClangdServer.cpp
25 ↗(On Diff #127386)

Is this include redundant now? Can we remove it?

430 ↗(On Diff #127386)

Capturing this seems redundant. Remove it?

clangd/ClangdUnit.cpp
90

clang-format please

90

Do we need both checks? Doesn't SourceMgr.isInMainFile handles all the cases?

127

Let's create a new empty map inside this class and have a takeIncludeReferences method (similar to TopLevelDeclIDs and takeTopLevelDeclIDs)

164

We should have SourceMgr at all the proper places now, let's store IncludeReferenceMap directly

285

What reference does this IncludeReferenceMap contain? Includes from the preamble?

339–340

This class handles processing AST and preprocessor, it does not need to get IncludeLocationMap in constructor or store it at all.
Remove IncludeLocationMap from this class and handle getting references from IncludeLocationMap outside this class instead.

clangd/ClangdUnit.h
101

Make it all const?

const IncludeReferenceMap &getIRM() const { return IRM; }

185

This function moved without need and lost a comment.

This revision now requires changes to proceed.Dec 19 2017, 1:39 AM
Nebiroth marked 8 inline comments as done.Dec 19 2017, 2:15 PM
Nebiroth added inline comments.
clangd/ClangdUnit.cpp
90

This check was here to prevent an issue that appeared previously. I don't think this check is needed anymore.

164

The idea was to pass a single map around to fill with every reference instead of having separate maps being merged together.

285

This should contain every reference available for one file.

Nebiroth marked 2 inline comments as done.Dec 19 2017, 3:38 PM
Nebiroth updated this revision to Diff 127617.Dec 19 2017, 3:55 PM
Removed some useless inclusions
Removed superfluous check when inserting data in map
Moved addition to DeclarationLocations in finish() outside of DeclMacrosFinder
Merged with revision 321087 (moved findDefinitions and findDocumentHighlights
ilya-biryukov requested changes to this revision.Dec 20 2017, 10:17 AM

Another round of review

clangd/ClangdUnit.cpp
127

This comment is not addressed yet, but marked as done.

154

Maybe add assert(SourceMgr && "SourceMgr must be set at this point") here?

164

You copy the map for preamble and then append to it in CppFilePreambleCallbacks? That also LG, we should not have many references there anyway.

285

Thanks for clarifying, LG.

289

Don't we already store the map we need in PreambleData? Why do we need an extra IRM parameter?

clangd/ClangdUnit.h
185

Now we have duplicated definitions here. Bad merge?

clangd/CodeComplete.cpp
328 ↗(On Diff #127617)

Accidental change?

807 ↗(On Diff #127617)

Accidental change?

clangd/XRefs.cpp
58

We don't need locations anymore. Remove them.

175

Probably a good place for a comment. Also, maybe rename local var to something easier to understand like IncludeDefinitions

/// Process targets for paths inside #include directive.
std::vector<Location> IncludeTargets;
176

No need to special case empty maps, remove the if altogether.

181

Replace with DeclMacrosFinder->getSearchedLocation() SourceLocationBeg, it makes the code easier to read.

183

why do we need to convert to unsigned? To slience compiler warnings?

186

this should be R.start.charater <= CharNumber && CharNumber <= R.end.character

This revision now requires changes to proceed.Dec 20 2017, 10:17 AM
ilya-biryukov added inline comments.Dec 21 2017, 7:39 AM
clangd/XRefs.cpp
181

Sorry, the comment got messed up. Here's the correct version:

Replace DeclMacrosFinder->getSearchedLocation() with SourceLocationBeg, it makes the code easier to read.

Nebiroth updated this revision to Diff 127900.Dec 21 2017, 9:11 AM
Nebiroth marked 11 inline comments as done.
Minor code cleanup

@ilya-biryukov Hi! I'll be updating William's patches that were in progress. I just have a few comments/question before I send a new update. (I also don't know if I can update this diff or I have to create a new diff on Phabricator... I guess we'll see!!).

clangd/ClangdUnit.cpp
127

As mentioned below, the idea was to have a single map being appended to, without having to merge two separate maps. However, I can change the code so that two separate maps are built and merged if you prefer.

But I'm not so clear if that's what you'd prefer:

You copy the map for preamble and then append to it in CppFilePreambleCallbacks? That also LG, we should not have many references there anyway.

It's not meant to have any copy. The idea was to create a single IncludeReferenceMap in CppFile::deferRebuild, populate it with both preamble and non-preamble include references and std::move it around for later use (stored in ParsedAST).

289

Since the map will be now stored in ParsedAST and the instance doesn't exist yet, we need to keep the IRM parameter. I noticed that it wasn't being std::move'd though.

clangd/XRefs.cpp
183

Yes, "line" from the protocol is signed, whereas getSpellingColumn/lineNumber returns unsigned. I'll extract another var for the line number and cast both to int instead to have less casts and make the condition smaller.

@malaperle, hi! Both new diff and updating this works, so feel free the one that suits you best. I tend to look over the whole change on each new round of reviews anyway.

clangd/ClangdUnit.cpp
127

We can't have a single map because AST is rebuilt more often than the Preamble, so we have two options:

  • Store a map for the preamble separately, copy it when we need to rebuild the AST and append references from the AST to the new instance of the map.
  • Store two maps: one contains references only from the Preamble, the other one from the AST.

I think both are fine, since the copy of the map will be cheap anyway, as we only store a list of includes inside the main file.

289

That looks fine. Also see the other comment on why we need to copy the map from the Preamble, and not std::move it.

clangd/XRefs.cpp
183

Can we maybe convert to clangd::Position using the helper methods first and do the comparison of two clangd::Positions?
Comparing between clangd::Position and clang's line/column numbers is a common source of off-by-one errors in clangd.

malaperle added inline comments.Jan 10 2018, 9:36 AM
clangd/ClangdUnit.cpp
127

We can't have a single map because AST is rebuilt more often than the Preamble, so we have two options:

Doh! Indeed.

OK so I added the map in PreambleData, this one will say every reparse unless the preamble changes. When the AST is built/rebuilt, the map is copied (or empty) and includes from the AST are appended to it then stored in ParsedAST (option #1?).

clangd/XRefs.cpp
183

offsetToPosition (if that's what you mean) uses a StringRef of the code, which is not handy in this case. I'll add another one "sourceLocToPosition" to convert a SourceLocation to a Position. WDYT? It can be used in a few other places too.

malaperle updated this revision to Diff 129292.Jan 10 2018, 9:38 AM

Store map in PremableData and copy it on reparse.
Convert SourceLoc to Position when comparing with include Positions.

malaperle resigned from this revision.Jan 10 2018, 9:39 AM
malaperle updated this revision to Diff 129293.Jan 10 2018, 9:43 AM

Revert an unintentional white space change.

ilya-biryukov added inline comments.Jan 11 2018, 2:22 AM
clangd/ClangdUnit.h
48

We use unordered_map as a vector<pair<>> here. (i.e. we never look up values by key, because we don't only the range, merely a point in the range)
Replace map with vector<pair<>> and remove RangeHash that we don't need anymore.

clangd/XRefs.cpp
183

Looks good, thanks!

unittests/clangd/ClangdTests.cpp
781 ↗(On Diff #129293)

We moved findDefinition tests to XRefsTests.cpp and added a useful Annotation helper to make writing these tests simpler.
Maybe we could use it for this test as well?

malaperle updated this revision to Diff 133978.Feb 12 2018, 7:09 PM

Move tests to XRefsTests, change IncludeReferenceMap to a vector and rename it.

malaperle added inline comments.Feb 12 2018, 7:10 PM
clangd/ClangdUnit.h
48

Done. I also renamed, IncludeReferenceMap to InclusionLocations. I thought I was more suitable.

unittests/clangd/ClangdTests.cpp
781 ↗(On Diff #129293)

Done. (I don't know why I can't use the "done" checkbox, maybe because I wasn't the original author?)

ilya-biryukov added inline comments.Feb 13 2018, 6:07 AM
clangd/ClangdUnit.cpp
102

NIT: replace FilenameRange.getAsRange() with SR

131

NIT: remove ctor, use initializer on the member instead:

private:
  SourceManager *SourceMgr = nullptr;
163

Maybe swap IncLocations and SourceMgr? Grouping TopLevelDecls, TopLevelDeclIDs and IncLocations together seems reasonable, as all of them are essentially output parameters.

287

NIT: move IncLocations closer to their first use, i.e. create the variable right before addPPCallbacks()

clangd/ClangdUnit.h
48

LG

105

NIT: move to .cpp file to be consisten with other decls in this file.

clangd/XRefs.cpp
179

NIT: SourceMgr does not depend on the loop variable, declare it out of the loop.

182

NIT: define operator <= for Position and do this instead: R.start <= Pos && Pos < R.end (note that LSP ranges are half-open, i.e. the end is excluded).
Even better: define a bool contains(Position Pos) const helper in the Range class and use it here (will abstract away to half-open nature of the range)

186

Let's follow the pattern of decls and macros here. I.e. not return from the function, merely collect all the results.

unittests/clangd/XRefsTests.cpp
59

NIT: remove this class, use IgnoreDiagnostics from Compiler.h instead.

246

Could we also add tests for corner cases: cursor before opening quote, cursor after the closing quote, cursor in the middle of #include token? (we shouldn't navigate anywhere in the middle of the #include token)

malaperle added inline comments.Feb 13 2018, 10:05 AM
unittests/clangd/XRefsTests.cpp
59

It looks like IgnoreDiagnostics from Compiler.h implements DiagnosticConsumer from Compiler.h, and not DiagnosticsConsumer from ClangdServer.h so that wouldn't work.

malaperle added inline comments.Feb 13 2018, 9:42 PM
unittests/clangd/XRefsTests.cpp
246

cursor before opening quote, cursor after the closing quote

I assume we don't want to navigate anywhere for these positions? I don't have an opinion.

(we shouldn't navigate anywhere in the middle of the #include token)

It did in CDT and I thought it worked nicely as it made it easier to click on it. You can hold ctrl on the whole line and it underlined it (well except trailing comments). But clients don't handle the spaces nicely (underline between #include and file name) so I thought I'd work on the client first before making the server do it. Anyhow, for now it shouldn't navigate indeed.

ilya-biryukov added inline comments.Feb 14 2018, 5:36 AM
unittests/clangd/XRefsTests.cpp
59

You're right, I got confused, sorry. Disregard my comment.

246

> cursor before opening quote, cursor after the closing quote
I assume we don't want to navigate anywhere for these positions? I don't have an opinion.

I'd say we should navigate when the cursor is right before the opening quote. For the closing quote I don't have any opinions either :-)

Fix some NITs, add more tests.

Last drop of NITs. After they're fixed, this change is ready to land!

unittests/clangd/XRefsTests.cpp
282

There's a typo, should be HeaderAnnotations

302

NIT: one assertion using EXPECT_THAT will read better and produce more helpful messages in case of failures:

// Create FooHUri to avoid typing URIForFile everywhere.
auto FooHUri = URIForFile{FooH.str()};

EXPECT_THAT(Locations, ElementsAre(Location{FooHUri, HeaderAnnoations.range()}));
328

NIT: Use EXPECT_THAT here too:
EXPECT_THAT(Locations, IsEmpty());

malaperle updated this revision to Diff 134432.Feb 15 2018, 7:51 AM

Use EXPECT_THAT in a few places and clean-ups in tests.

ilya-biryukov accepted this revision.Feb 15 2018, 8:50 AM

LGTM modulo the ASSERT_TRUE nit.

unittests/clangd/XRefsTests.cpp
292

Maybe replace with ASSERT_TRUE?
If Locations has an error, an assertion will fire in debug mode inside Expected that the error was not handled.

This revision is now accepted and ready to land.Feb 15 2018, 8:50 AM
malaperle updated this revision to Diff 134549.Feb 15 2018, 7:27 PM

Change some EXPECT_TRUE to ASSERT_TRUE

ilya-biryukov accepted this revision.Feb 16 2018, 2:02 AM
This revision was automatically updated to reflect the committed changes.