diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h --- a/clang-tools-extra/clangd/SourceCode.h +++ b/clang-tools-extra/clangd/SourceCode.h @@ -248,6 +248,10 @@ const LangOptions &LangOpts); }; +/// Return true if the \p TokenName is in the list of reversed keywords of the +/// language. +bool isKeyword(llvm::StringRef TokenName, const LangOptions &LangOpts); + /// Heuristically determine namespaces visible at a point, without parsing Code. /// This considers using-directives and enclosing namespace-declarations that /// are visible (and not obfuscated) in the file itself (not headers). diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -633,6 +633,12 @@ return Ranges; } +bool isKeyword(llvm::StringRef NewName, const LangOptions &LangOpts) { + // Keywords are initialized in constructor. + clang::IdentifierTable KeywordsTable(LangOpts); + return KeywordsTable.find(NewName) != KeywordsTable.end(); +} + namespace { struct NamespaceEvent { enum { diff --git a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp --- a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp +++ b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp @@ -789,6 +789,19 @@ EXPECT_TRUE(isHeaderFile("header.h", LangOpts)); } +TEST(SourceCodeTests, isKeywords) { + LangOptions LangOpts; + LangOpts.CPlusPlus20 = true; + EXPECT_TRUE(isKeyword("int", LangOpts)); + EXPECT_TRUE(isKeyword("return", LangOpts)); + EXPECT_TRUE(isKeyword("co_await", LangOpts)); + + // these are identifiers (not keywords!) with special meaning in some + // contexts. + EXPECT_FALSE(isKeyword("final", LangOpts)); + EXPECT_FALSE(isKeyword("override", LangOpts)); +} + } // namespace } // namespace clangd } // namespace clang