llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangd Author: Berkay Sahin (berkaysahiin) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/219839.diff 2 Files Affected: - (modified) clang-tools-extra/clangd/XRefs.cpp (+54) - (modified) clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp (+56) ``````````diff diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 86528d806eab3..f51039f33992b 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -42,6 +42,7 @@ #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TokenKinds.h" @@ -235,6 +236,54 @@ std::optional<Location> makeLocation(const ASTContext &AST, SourceLocation Loc, return L; } +std::optional<LocatedSymbol> +locateModuleReferent(const syntax::Token &TouchedIdentifier, ParsedAST &AST, + llvm::StringRef MainFilePath) { + const SourceManager &SM = AST.getSourceManager(); + const ASTContext &Context = AST.getASTContext(); + + const Module *ResultModule = nullptr; + + for (const ImportDecl *Import : Context.local_imports()) { + const Module *Imported = Import->getImportedModule(); + ArrayRef<SourceLocation> IdentifierLocs = Import->getIdentifierLocs(); + if (!Imported || !Imported->isNamedModule() || IdentifierLocs.empty()) + continue; + + std::string Name = Imported->getFullModuleName(); + if (auto Colon = Name.find(':'); Colon != std::string::npos) + Name.erase(0, Colon + 1); + if (Name.empty()) + continue; + + const size_t NameSize = static_cast<int>(Name.size() - 1); + + const SourceLocation NameBegin = SM.getSpellingLoc(IdentifierLocs.front()); + const SourceLocation NameEnd = NameBegin.getLocWithOffset(NameSize); + + if (SM.isPointWithin(TouchedIdentifier.location(), NameBegin, NameEnd)) { + ResultModule = Imported; + break; + } + } + + if (!ResultModule) + return std::nullopt; + + const SourceLocation DefinitionLoc = + SM.getSpellingLoc(ResultModule->DefinitionLoc); + auto Definition = makeLocation(Context, DefinitionLoc, MainFilePath); + + if (!Definition) + return std::nullopt; + + LocatedSymbol Result; + Result.Name = ResultModule->getFullModuleName(); + Result.PreferredDeclaration = *Definition; + Result.Definition = *Definition; + return Result; +} + // Treat #included files as symbols, to enable go-to-definition on them. std::optional<LocatedSymbol> locateFileReferent(const Position &Pos, ParsedAST &AST, @@ -865,6 +914,11 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos, } } + if (TouchedIdentifier) + if (auto Module = + locateModuleReferent(*TouchedIdentifier, AST, MainFilePath)) + return {*std::move(Module)}; + ASTNodeKind NodeKind; auto ASTResults = locateASTReferent(*CurLoc, TouchedIdentifier, AST, MainFilePath, Index, NodeKind); diff --git a/clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp b/clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp index f10f3e4976cf9..8933a21108e0e 100644 --- a/clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp +++ b/clang-tools-extra/clangd/unittests/PrerequisiteModulesTest.cpp @@ -19,6 +19,7 @@ #include "ProjectModules.h" #include "SemanticHighlighting.h" #include "TestTU.h" +#include "XRefs.h" #include "support/Path.h" #include "support/ThreadsafeFS.h" #include "clang/Tooling/Tooling.h" @@ -629,6 +630,61 @@ import A; EXPECT_TRUE(D.isFromASTFile()); } +TEST_F(PrerequisiteModulesTests, LocateImportedModule) { + MockDirectoryCompilationDatabase CDB(TestDir, FS); + + Annotations Dep(R"cpp( +export $decl[[module]] dep.one.two; +)cpp"); + CDB.addFile("Dep.cppm", Dep.code()); + + Annotations Part(R"cpp( +export $decl[[module]] M:part.one; +)cpp"); + CDB.addFile("M-part.cppm", Part.code()); + + Annotations Use(R"cpp( +export module M; +import $dep0^dep.$dep1^one.$dep2^two; +import :$part0^part.$part1^one; +)cpp"); + CDB.addFile("M.cppm", Use.code()); + + ModulesBuilder Builder(CDB); + auto Inputs = getInputs("M.cppm", CDB); + Inputs.ModulesManager = &Builder; + Inputs.Opts.SkipPreambleBuild = true; + + auto CI = buildCompilerInvocation(Inputs, DiagConsumer); + ASSERT_TRUE(CI); + auto Preamble = + buildPreamble(getFullPath("M.cppm"), *CI, Inputs, /*InMemory=*/true, + /*Callback=*/nullptr); + ASSERT_TRUE(Preamble); + + auto AST = ParsedAST::build(getFullPath("M.cppm"), Inputs, std::move(CI), {}, + Preamble); + ASSERT_TRUE(AST); + ASSERT_TRUE(AST->getDiagnostics().empty()); + + auto Check = [&](llvm::StringRef Point, llvm::StringRef Name, + llvm::StringRef File, Range TargetRange) { + auto Results = locateSymbolAt(*AST, Use.point(Point)); + ASSERT_THAT(Results, testing::SizeIs(1)); + EXPECT_EQ(Results.front().Name, Name); + Location Target{ + URIForFile::canonicalize(getFullPath(File), getFullPath("M.cppm")), + TargetRange}; + EXPECT_EQ(Results.front().PreferredDeclaration, Target); + EXPECT_EQ(Results.front().Definition, Target); + }; + + for (llvm::StringRef Point : {"dep0", "dep1", "dep2"}) + Check(Point, "dep.one.two", "Dep.cppm", Dep.range("decl")); + for (llvm::StringRef Point : {"part0", "part1"}) + Check(Point, "M:part.one", "M-part.cppm", Part.range("decl")); +} + // An end to end test for code complete in modules TEST_F(PrerequisiteModulesTests, CodeCompleteTest) { MockDirectoryCompilationDatabase CDB(TestDir, FS); `````````` </details> https://github.com/llvm/llvm-project/pull/219839 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
