diff --git a/clang-tools-extra/clangd/FindSymbols.cpp b/clang-tools-extra/clangd/FindSymbols.cpp --- a/clang-tools-extra/clangd/FindSymbols.cpp +++ b/clang-tools-extra/clangd/FindSymbols.cpp @@ -136,17 +136,11 @@ auto &SM = Ctx.getSourceManager(); SourceLocation NameLoc = nameLocation(ND, SM); - // getFileLoc is a good choice for us, but we also need to make sure - // sourceLocToPosition won't switch files, so we call getSpellingLoc on top of - // that to make sure it does not switch files. - // FIXME: sourceLocToPosition should not switch files! SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc())); SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc())); - if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid()) - return llvm::None; - - if (!SM.isWrittenInMainFile(NameLoc) || !SM.isWrittenInMainFile(BeginLoc) || - !SM.isWrittenInMainFile(EndLoc)) + const auto SymbolRange = + toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc}); + if (!SymbolRange) return llvm::None; Position NameBegin = sourceLocToPosition(SM, NameLoc); @@ -162,8 +156,8 @@ SI.name = printName(Ctx, ND); SI.kind = SK; SI.deprecated = ND.isDeprecated(); - SI.range = - Range{sourceLocToPosition(SM, BeginLoc), sourceLocToPosition(SM, EndLoc)}; + SI.range = Range{sourceLocToPosition(SM, SymbolRange->getBegin()), + sourceLocToPosition(SM, SymbolRange->getEnd())}; SI.selectionRange = Range{NameBegin, NameEnd}; if (!SI.range.contains(SI.selectionRange)) { // 'selectionRange' must be contained in 'range', so in cases where clang diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp --- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp @@ -35,7 +35,7 @@ } MATCHER_P(WithName, N, "") { return arg.name == N; } MATCHER_P(WithKind, Kind, "") { return arg.kind == Kind; } -MATCHER_P(SymRange, Range, "") { return arg.location.range == Range; } +MATCHER_P(SymRange, Range, "") { return arg.range == Range; } // GMock helpers for matching DocumentSymbol. MATCHER_P(SymNameRange, Range, "") { return arg.selectionRange == Range; } @@ -712,6 +712,72 @@ WithName("Foo_type::method3"))); } +TEST(DocumentSymbolsTest, Ranges) { + TestTU TU; + Annotations Main(R"( + $foo[[int foo(bool Argument) { + return 42; + }]] + + $variable[[char GLOBAL_VARIABLE]]; + + $ns[[namespace ns { + $bar[[class Bar { + public: + $ctor[[Bar() {}]] + $dtor[[~Bar()]]; + + private: + $field[[unsigned Baz]]; + + $getbaz[[unsigned getBaz() { return Baz; }]] + }]]; + }]] // namespace ns + + $forwardclass[[class ForwardClassDecl]]; + + $struct[[struct StructDefinition { + $structfield[[int *Pointer = nullptr]]; + }]]; + $forwardstruct[[struct StructDeclaration]]; + + $forwardfunc[[void forwardFunctionDecl(int Something)]]; + )"); + TU.Code = Main.code().str(); + EXPECT_THAT( + getSymbols(TU.build()), + UnorderedElementsAre( + AllOf(WithName("foo"), WithKind(SymbolKind::Function), + SymRange(Main.range("foo"))), + AllOf(WithName("GLOBAL_VARIABLE"), WithKind(SymbolKind::Variable), + SymRange(Main.range("variable"))), + AllOf( + WithName("ns"), WithKind(SymbolKind::Namespace), + SymRange(Main.range("ns")), + Children(AllOf( + WithName("Bar"), WithKind(SymbolKind::Class), + SymRange(Main.range("bar")), + Children( + AllOf(WithName("Bar"), WithKind(SymbolKind::Constructor), + SymRange(Main.range("ctor"))), + AllOf(WithName("~Bar"), WithKind(SymbolKind::Constructor), + SymRange(Main.range("dtor"))), + AllOf(WithName("Baz"), WithKind(SymbolKind::Field), + SymRange(Main.range("field"))), + AllOf(WithName("getBaz"), WithKind(SymbolKind::Method), + SymRange(Main.range("getbaz"))))))), + AllOf(WithName("ForwardClassDecl"), WithKind(SymbolKind::Class), + SymRange(Main.range("forwardclass"))), + AllOf(WithName("StructDefinition"), WithKind(SymbolKind::Struct), + SymRange(Main.range("struct")), + Children(AllOf(WithName("Pointer"), WithKind(SymbolKind::Field), + SymRange(Main.range("structfield"))))), + AllOf(WithName("StructDeclaration"), WithKind(SymbolKind::Struct), + SymRange(Main.range("forwardstruct"))), + AllOf(WithName("forwardFunctionDecl"), WithKind(SymbolKind::Function), + SymRange(Main.range("forwardfunc"))))); +} + } // namespace } // namespace clangd } // namespace clang