[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 541753. capfredf added a comment. Remove unnecessary braces Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -543,6 +543,7 @@ case CodeCompletionContext::CCC_PreprocessorExpression: case CodeCompletionContext::CCC_PreprocessorDirective: case CodeCompletionContext::CCC_Attribute: +case CodeCompletionContext::CCC_ReplTopLevel: case CodeCompletionContext::CCC_TypeQualifiers: { //Only Clang results should be accepted, so we'll set all of the other //context bits to 0 (i.e. the empty set) Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line = LE.readLine()) { llvm::StringRef L = *Line; L = L.trim(); @@ -168,10 +169,10 @@ } Input += L; - if
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 542622. capfredf added a comment. handle cases where code completion in a function declaration Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,74 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} + + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + std::string out; + auto rs = llvm::raw_string_ostream(out); + auto Completer = ReplListCompleter(CB, *Interp, rs); + std::vector comps = +Completer(std::string("void app("), 9); + EXPECT_EQ((size_t)0, out.length()); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -543,6 +543,7 @@ case CodeCompletionContext::CCC_PreprocessorExpression: case CodeCompletionContext::CCC_PreprocessorDirective: case CodeCompletionContext::CCC_Attribute: +case CodeCompletionContext::CCC_ReplTopLevel: case CodeCompletionContext::CCC_TypeQualifiers: { //Only Clang results should be accepted, so we'll set all of the other //context bits to 0 (i.e. the empty set) Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #i
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf added inline comments. Comment at: clang/unittests/Interpreter/CodeCompletionTest.cpp:71 +Completer(std::string("void app("), 9); + EXPECT_EQ((size_t)0, out.length()); +} @v.g.vassilev The way I fixed this is a bit hacky. Do you have a better idea? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 543000. capfredf added a comment. changes per @v.g.vassilev's comments Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,71 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Completer = ReplListCompleter(CB, *Interp); + auto Err = llvm::Error::success(); + std::vector comps = + Completer(std::string("void app("), 9, Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -543,6 +543,7 @@ case CodeCompletionContext::CCC_PreprocessorExpression: case CodeCompletionContext::CCC_PreprocessorDirective: case CodeCompletionContext::CCC_Attribute: +case CodeCompletionContext::CCC_ReplTopLevel: case CodeCompletionContext::CCC_TypeQualifiers: { //Only Clang results should be accepted, so we'll set all of the other //context bits to 0 (i.e. the empty set) Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 549658. capfredf added a comment. use ASTUnit::codeComplete Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/ExternalSource.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/DeviceOffload.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,100 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + (*Interp)->codeComplete(Prefix, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : ConvertToCodeCompleteStrings(Results)) { +if (c.startswith(Prefix)) + Comps.push_back(c.substr(Prefix.size()).str()); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CInde
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf added inline comments. Comment at: clang/include/clang/Frontend/ASTUnit.h:901 +SmallVectorImpl &OwnedBuffers, +std::function AfterBeginSourceFile = [](CompilerInstance& CI) -> void {}); @v.g.vassilev Not sure if this is the right solution or idiom to extend this method. we can make this high order function more general, like `std::unique_ptr<()>` Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 549739. capfredf added a comment. Herald added a subscriber: ChuanqiXu. changes per discussions Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/ExternalSource.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/DeviceOffload.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,100 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + (*Interp)->codeComplete(Prefix, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : ConvertToCodeCompleteStrings(Results)) { +if (c.startswith(Prefix)) + Comps.push_back(c.substr(Prefix.size()).str()); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp ==
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 549749. capfredf added a comment. up Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/ExternalSource.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/DeviceOffload.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,100 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + (*Interp)->codeComplete(Prefix, 1, Prefix.size(), + MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : ConvertToCodeCompleteStrings(Results)) { +if (c.startswith(Prefix)) + Comps.push_back(c.substr(Prefix.size()).str()); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 549750. capfredf added a comment. up Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/ExternalSource.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/DeviceOffload.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,100 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + (*Interp)->codeComplete(Prefix, 1, Prefix.size(), + MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : ConvertToCodeCompleteStrings(Results)) { +if (c.startswith(Prefix)) + Comps.push_back(c.substr(Prefix.size()).str()); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 549751. capfredf added a comment. use auto Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/ExternalSource.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/DeviceOffload.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,100 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + (*Interp)->codeComplete(Prefix, 1, Prefix.size(), + MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : ConvertToCodeCompleteStrings(Results)) { +if (c.startswith(Prefix)) + Comps.push_back(c.substr(Prefix.size()).str()); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/lib
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 549759. capfredf added a comment. move everything into InterpreterCodeCompletion. the entry point for code completion is now a function, codeCompletion Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/InterpreterCodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/InterpreterCodeCompletion.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Interpreter/InterpreterCodeCompletion.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : ConvertToCodeCompleteStrings(Results)) { +if (c.startswith(Prefix)) + Comps.push_back(c.substr(Prefix.size()).str()); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCod
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 549760. capfredf added a comment. format Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/InterpreterCodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/InterpreterCodeCompletion.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Interpreter/InterpreterCodeCompletion.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : ConvertToCodeCompleteStrings(Results)) { +if (c.startswith(Prefix)) + Comps.push_back(c.substr(Prefix.size()).str()); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -11,8 +11,8 @@ // //===--
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 550489. capfredf marked 7 inline comments as done. capfredf added a comment. address @sammccall 's comments Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/InterpreterCodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/InterpreterCodeCompletion.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- clang/unittests/Interpreter/CodeCompletionTest.cpp +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -42,9 +42,9 @@ Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); std::vector Comps; - for (auto c : ConvertToCodeCompleteStrings(Results)) { -if (c.startswith(Prefix)) - Comps.push_back(c.substr(Prefix.size()).str()); + for (auto c : convertToCodeCompleteStrings(Results)) { +if (c.find(Prefix) == 0) + Comps.push_back(c.substr(Prefix.size())); } return Comps; Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -543,7 +543,7 @@ case CodeCompletionContext::CCC_PreprocessorExpression: case CodeCompletionContext::CCC_PreprocessorDirective: case CodeCompletionContext::CCC_Attribute: -case CodeCompletionContext::CCC_ReplTopLevel: +case CodeCompletionContext::CCC_TopLevelOrExpression: case CodeCompletionContext::CCC_TypeQualifiers: { //Only Clang results should be accepted, so we'll set all of the other //context bits to 0 (i.e. the empty set) Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -129,13 +129,14 @@ s = Buffer.substr(space_pos + 1); } - for (auto c : ConvertToCodeCompleteStrings(Results)) { -if (c.startswith(s)) + for (auto c : convertToCodeCompleteStrings(Results)) { +if (c.find(s) == 0) Comps.push_back( - llvm::LineEditor::Completion(c.substr(s.size()).str(), c.str())); + llvm::LineEditor::Completion(c.substr(s.size()), c)); } return Comps; } + llvm::ExitOnError ExitOnErr; int main(int argc, const char **argv) { ExitOnErr.setBanner("clang-repl: "); Index: clang/lib/Sema/SemaCodeComplete.cpp === --- clang/lib/Sema/SemaCodeComplete.cpp +++ clang/lib/Sema/SemaCodeComplete.cpp @@ -225,7 +225,7 @@ case CodeCompletionContext::CCC_ObjCMessageReceiver: case CodeCompletionContext::CCC_ParenthesizedExpression: case CodeCompletionContext::CCC_Statement: -case CodeCompletionContext::CCC_ReplTopLevel: +case CodeCompletionContext::CCC_TopLevelOrExpression: case CodeCompletionContext::CCC_Recovery: if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) if (Method->isInstanceMethod()) @@ -1851,7 +1851,7 @@ case Sema::PCC_ObjCInstanceVariableList: case Sema::PCC_Expression: case Sema::PCC_Statement: - case Sema::PCC_TopLevelStmtDecl: + case Sema::PCC_TopLevelOrExpression: case Sema::PCC_ForInit: case Sema::PCC_Condition: case Sema::PCC_RecoveryInFunction: @@ -1909,7 +1909,7 @@ case Sema::PCC_Type: case Sema::PCC_ParenthesizedExpression: case Sema::PCC_LocalDeclarationSpecifiers: - case Sema::PCC_TopLevelStmtDecl: + case Sema::PCC_TopLevelOrExpression: return true; case Sema::PCC_Expression: @@ -,7 +,7 @@ break; case Sema::PCC_RecoveryInFunction: - case Sema::PCC_TopLevelStmtDecl: + case Sema::PCC_TopLevelOrExpression: case Sema::PCC_Statement: { if (SemaRef.getLangOpts().CPlusPlus11) AddUsingAliasResult(Builder, Results); @@ -4212,8 +4212,8 @@ case Sema::PCC_LocalDeclarationSpecifiers: return CodeCompletionContext::CCC_Type; - case Sema::PCC_TopLevelStmtDecl: -return CodeCompletionContext::CCC_ReplTopLevel; + case Sema::PCC_TopLevelOrExpression: +return CodeCompletionContext::CCC_TopLevelOrExpression; } llvm_unreachable("Invalid ParserCompletionContext!"); @@ -4354,7 +4354,7 @@ break; case PCC_Statement: - case PCC_TopLevelStmtDecl: + case PCC_TopLevelOrExpression: case PCC_ParenthesizedExpression: case PCC_Expression: case PCC_ForInit: @@ -4392,7
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf added inline comments. Comment at: clang/include/clang/Frontend/ASTUnit.h:901 +SmallVectorImpl &OwnedBuffers, +std::function AfterBeginSourceFile = [](CompilerInstance& CI) -> void {}); sammccall wrote: > capfredf wrote: > > @v.g.vassilev Not sure if this is the right solution or idiom to extend > > this method. > > > > we can make this high order function more general, like > > `std::unique_ptr<()>` > There's no need for this to be a SyntaxOnlyAction, you can take > FrontendAction here. > > I don't think there's any need to provide a factory, it's safe to assume it > will always create one action. (We have FrontendActionFactory in tooling, and > it's a pain.) Ideally, this method requires a FrontendAction with `hasCodeCompletionSupport` returning `true`. The reason I chose `SyntaxOnlyAction` are 1. the old code used it 2. `SyntaxOnlyAction::hasCodeCompletionSupport` returns `true`. Certainly, right now `SyntaxOnlyAction` does not prevent its subclasses from overriding this method. Comment at: clang/include/clang/Sema/CodeCompleteConsumer.h:342 +/// Code completion at a top level in a REPL session. +CCC_ReplTopLevel, }; sammccall wrote: > v.g.vassilev wrote: > > > I don't think this name fits with the others, it describes the client rather > than the grammatical/semantic context. > > I would suggest maybe `CCC_TopLevelOrExpression`? Nice. This one sounds better indeed. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf added a comment. @sammccall Thank you very much for your valuable input. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 550940. capfredf added a comment. up Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/InterpreterCodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Interpreter/InterpreterCodeCompletion.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Interpreter/InterpreterCodeCompletion.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : convertToCodeCompleteStrings(Results)) { +if (c.find(Prefix) == 0) + Comps.push_back(c.substr(Prefix.size())); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -11,8 +11,8 @@ // //===-
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 551218. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : convertToCodeCompleteStrings(Results)) { +if (c.find(Prefix) == 0) + Comps.push_back(c.substr(Prefix.size())); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -11,8 +11,8 @@ // //===--===// -#include "CInd
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 552418. capfredf edited the summary of this revision. capfredf added a comment. update the commit message Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : convertToCodeCompleteStrings(Results)) { +if (c.find(Prefix) == 0) + Comps.push_back(c.substr(Prefix.size())); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -11,8 +11,8 @@ //
[PATCH] D158629: [ClangRepl] support code completion at the repl
capfredf created this revision. Herald added subscribers: ChuanqiXu, kadircet, arphaman. Herald added a project: All. capfredf requested review of this revision. Herald added projects: clang, clang-tools-extra. Herald added a subscriber: cfe-commits. This patch enabled code completion for ClangREPL. The feature was built upon three existing Clang components: a list completer for `LineEditor`, a CompletionConsumer from `SemaCodeCompletion`, and the ASTUnit::codeComplete method. with the first component serving as the main entry point of handling interactive inputs. Because a completion point for a compiler instance has to be unchanged once it is set, an incremental compiler instance is created for each code completion. Such a compiler instance carries over AST context source from the main interpreter compiler in order to obtain declarations or bindings from previous input in the same REPL session. The most important API `codeComplete` in `Interpreter/CodeCompletion` is a thin wrapper that calls with ASTUnit::codeComplete with necessary arguments, such as a code completion point and a `ReplCompletionConsumer`, which communicates completion results from `SemaCodeCompletion` back to the list completer for the REPL. In addition, `PCC_TopLevelOrExpression and `CCC_TopLevelOrExpression` top levels were added so that `SemaCodeCompletion` can treat top level statements like expression statements at the REPL. For example, clang-repl> int foo = 42; clang-repl> f >From a parser's persective, the cursor is at a top level. If we used code completion without any changes, `PCC_Namespace` would be supplied to `Sema::CodeCompleteOrdinaryName`, and thus the completion results would not include `foo`. Currently, the way we use `PCC_TopLevelOrExpression` and `CCC_TopLevelOrExpression` is no different from the way we use `PCC_Statement` and `CCC_Statement` respectively. Previous Differential Revision: https://reviews.llvm.org/D154382 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D158629 Files: clang-tools-extra/clangd/CodeComplete.cpp clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : convertToCodeCompleteStrings(Results)) { +if (c.find(Prefix) == 0) + Comps.push_back(c.substr(Prefix.size())); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo"));
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 552736. capfredf added a comment. Herald added a subscriber: kadircet. Herald added a project: clang-tools-extra. fix code in Clangd Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang-tools-extra/clangd/CodeComplete.cpp clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + std::vector Comps; + for (auto c : convertToCodeCompleteStrings(Results)) { +if (c.find(Prefix) == 0) + Comps.push_back(c.substr(Prefix.size())); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf marked 5 inline comments as done. capfredf added inline comments. Comment at: clang/lib/Interpreter/CodeCompletion.cpp:111 + auto *CConsumer = new ReplCompletionConsumer(Results); + auto Interp = Interpreter::createForCodeCompletion( + CB, MainInterp.getCompilerInstance(), CConsumer); v.g.vassilev wrote: > I do not believe we need a spe I am not sure I am following. For a regular interpreter, create Interpreter -> create Incremental Parser -> IncrmentalASTAction triggered -> set a default code completion consumer(PrintCodeCompletionConsumer) to CI if no code consumer has been set -> Sema initialized. Based on this logic, we need to provide our CodeConsumer so that IncrementalASTAction does not create the default, plus we need to a parent CI to a new code completion interpreter. I don't see how we can avoid a special code path for creation Comment at: clang/lib/Interpreter/IncrementalParser.cpp:324 -llvm::Expected -IncrementalParser::Parse(llvm::StringRef input) { +llvm::Error IncrementalParser::ParseForCodeCompletion(llvm::StringRef input, + size_t Col, size_t Line) { v.g.vassilev wrote: > Is there any other particular reason for this routine to be different rather > than `PP.SetCodeCompletionPoint(*FE, Line, Col)`? That is, can we merge back > the old code and only set the point of completion externally? The regular `Parse` does some lexing after parsing, which I don't think is necessary for code completion. Also, this is more or less because, as a functional programmer, I prefer building things using small functions with explicit arguments. I'll try if I can use the old parse with the completion point set and tested. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 547241. capfredf marked 2 inline comments as done. capfredf added a comment. changes per discussions Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/DeviceOffload.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp clang/unittests/Interpreter/IncrementalProcessingTest.cpp clang/unittests/Interpreter/InterpreterTest.cpp Index: clang/unittests/Interpreter/InterpreterTest.cpp === --- clang/unittests/Interpreter/InterpreterTest.cpp +++ clang/unittests/Interpreter/InterpreterTest.cpp @@ -41,6 +41,7 @@ namespace { using Args = std::vector; + static std::unique_ptr createInterpreter(const Args &ExtraArgs = {}, DiagnosticConsumer *Client = nullptr) { Index: clang/unittests/Interpreter/IncrementalProcessingTest.cpp === --- clang/unittests/Interpreter/IncrementalProcessingTest.cpp +++ clang/unittests/Interpreter/IncrementalProcessingTest.cpp @@ -55,6 +55,7 @@ auto CB = clang::IncrementalCompilerBuilder(); CB.SetCompilerArgs(ClangArgv); auto CI = cantFail(CB.CreateCpp()); + auto Interp = llvm::cantFail(Interpreter::create(std::move(CI))); std::array PTUs; Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,107 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + std::vector Results; + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + size_t Lines = std::count(Prefix.begin(), Prefix.end(), '\n') + 1; + auto CFG = clang::CodeCompletionCfg{ + Prefix.size(), Lines, + const_cast(MainInterp.getCompilerInstance()), + Results}; + + auto Interp = clang::Interpreter::create(std::move(*CI), CFG); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + if (auto PTU = (*Interp)->Parse(Prefix); !PTU) { +ErrR = std::move(PTU.takeError()); +return {}; + } + + std::vector Comps; + for (auto c : ConvertToCodeCompleteStrings(Results)) { +if (c.startswith(Prefix)) + Comps.push_back(c.substr(Prefix.size()).str()); + } + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("oo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf created this revision. capfredf added a reviewer: v.g.vassilev. Herald added a project: All. capfredf requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits. This patch enabled users to use code completion in a REPL session. The solution is based on LineEditor and Sema/CodeCompletion. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line = LE.readLine()) { llvm::StringRef L = *Line; L = L.trim(); @@ -168,10 +169,10 @@ } Input += L; - if (Input == R"(%quit)") { break; - } else if (Input == R"(%undo)") { + } + if (Input == R"(%undo)") { if (auto Err = Interp->Undo()) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); HasError = true; Index: clang/lib/Interpreter/Interpreter.cpp === --- clang/lib/Interpreter/Interpreter.cpp +++ clang/lib/Interpreter/Interpreter.cpp @@ -14,6 +14,7 @@ #include "clang/Interpreter/Interpreter.h" #include "DeviceOffload.h" +#include "ExternalSource.h" #include "IncrementalExecutor.h" #include "IncrementalParser.h" @@ -33,6 +34,7 @@ #include "clang/Driver/Tool.h" #include "clang/Frontend
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf added inline comments. Comment at: clang/lib/Interpreter/CodeCompletion.cpp:84 + std::string AllCodeText = + MainInterp.getAllInput() + "\nvoid dummy(){\n" + Buffer.str() + "}"; + auto Lines = std::count(AllCodeText.begin(), AllCodeText.end(), '\n') + 1; v.g.vassilev wrote: > I am not sure why we need to wrap this code. Can we teach the > `TopLevelStmtDecl` to work with the code completion logic? I think the problem has less to do with the TopLevelStmtDecl. Usually, a `TopLevelStmtDecl` instance is a successful result from `ParseX`, but when `CodeCompletion` is triggered during parsing, nothing meaning comes out from `Parse`. We need to wrap our input because we need `Sema::CodeCompleteOrdinaryName` to work on code from the REPL in a different completion context than the same code from a regular source file. In a regular C++ file, ``` int foo = 42; f_ ``` Since top-level expressions are not supported, `foo` should not be an option. But in a REPL session, ``` clang-repl> int foo = 42; clang-repl> f_ ``` we are allowed to use `foo` to make a statement like `foo + 84;`. Since the argument for `CompletionContext` to `CodeCompleteOrdinaryName` is controlled by the parsing process, ie. there is no way to configure it from outside, I think faking context is a straightforward solution. Alternatively, we can check if the compiler is in incremental mode and call `CodeCompleteOrdinaryName` with the context we want in parsing. Something like: ``` if (PP.isIncrementalProcessingEnabled() { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement); } else { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace); } ``` I personally think both solutions are extensionally equivalent, but the alternative is a bit intrusive. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154621: [ClangRepl] support code completion at the repl
capfredf created this revision. Herald added a project: All. capfredf requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits. This patch enabled code completion for ClangREPL. The feature was built upon two existing Clang components: a list completer for `LineEditor` and `SemaCodeCompletion`. The former serves the main entry point to trigger the latter. Because a completion point for a compiler instance needs to be unchanged once it is set, an incremental compiler instance for code completion is created. In addition to completion points, it differs from a regular incremental compiler in the following ways: 1. It does not execute input. 2. To obtain declarations or bindings from previous input in the same REPL session, it carries over AST context source from the main compiler, i.e. the one used for the interpreter. 3. It contains a `ReplCompletionConsumer`, a subclass of `CodeCompletionConsumer`. The consumer communicates completion results from `SemaCodeCompletion` back to the list completer for the REPL. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D154621 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line = LE.readLine()) { llvm::StringRef L = *Line; L = L.trim(); @@ -168,10 +169,10 @@ } Input += L; - if (In
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 537766. capfredf edited the summary of this revision. capfredf added a comment. changes per discussions Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line = LE.readLine()) { llvm::StringRef L = *Line; L = L.trim(); @@ -168,10 +169,10 @@ } Input += L; - if (Input == R"(%quit)") { break; - } else if (Input == R"(%undo)") { + } + if (Input == R"(%undo)") { if (auto Err = Interp->Undo()) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); HasError = true; Index: clang/lib/Interpreter/Interpreter.cpp === --- clang/lib/Interpreter/Interpreter.cpp +++ clang/lib/Interpreter/Interpreter.cpp @@ -14,6 +14,7 @@ #include "clang/Interpreter/Interpreter.h" #include "DeviceOffload.h" +#include "ExternalSource.h" #include "IncrementalExecutor.h" #include "IncrementalParser.h" @@ -33,6 +34,7 @@ #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/I
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 537883. capfredf edited the summary of this revision. capfredf added a comment. update Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line = LE.readLine()) { llvm::StringRef L = *Line; L = L.trim(); @@ -168,10 +169,10 @@ } Input += L; - if (Input == R"(%quit)") { break; - } else if (Input == R"(%undo)") { + } + if (Input == R"(%undo)") { if (auto Err = Interp->Undo()) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); HasError = true; Index: clang/lib/Interpreter/Interpreter.cpp === --- clang/lib/Interpreter/Interpreter.cpp +++ clang/lib/Interpreter/Interpreter.cpp @@ -14,6 +14,7 @@ #include "clang/Interpreter/Interpreter.h" #include "DeviceOffload.h" +#include "ExternalSource.h" #include "IncrementalExecutor.h" #include "IncrementalParser.h" @@ -33,6 +34,7 @@ #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Value.
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 537910. capfredf added a comment. move the comment up Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/lib/Interpreter/CodeCompletion.cpp Index: clang/lib/Interpreter/CodeCompletion.cpp === --- clang/lib/Interpreter/CodeCompletion.cpp +++ clang/lib/Interpreter/CodeCompletion.cpp @@ -81,8 +81,6 @@ return Comps; } - std::string AllCodeText = "void __dummy(){\n" + Buffer.str(); - // We need to wrap our input because we need `Sema::CodeCompleteOrdinaryName` // to work on code from the REPL in a statement completion context. By // default, `Sema::CodeCompleteOrdinaryName` thinks the input is a regular c++ @@ -102,6 +100,7 @@ // Since top-level expressions are not supported, `foo` should not be an // option. But in a REPL session, we should be allowed to use `foo` to make a // statement like `foo + 84;`. + std::string AllCodeText = "void __dummy(){\n" + Buffer.str(); auto Lines = std::count(AllCodeText.begin(), AllCodeText.end(), '\n') + 1; Index: clang/lib/Interpreter/CodeCompletion.cpp === --- clang/lib/Interpreter/CodeCompletion.cpp +++ clang/lib/Interpreter/CodeCompletion.cpp @@ -81,8 +81,6 @@ return Comps; } - std::string AllCodeText = "void __dummy(){\n" + Buffer.str(); - // We need to wrap our input because we need `Sema::CodeCompleteOrdinaryName` // to work on code from the REPL in a statement completion context. By // default, `Sema::CodeCompleteOrdinaryName` thinks the input is a regular c++ @@ -102,6 +100,7 @@ // Since top-level expressions are not supported, `foo` should not be an // option. But in a REPL session, we should be allowed to use `foo` to make a // statement like `foo + 84;`. + std::string AllCodeText = "void __dummy(){\n" + Buffer.str(); auto Lines = std::count(AllCodeText.begin(), AllCodeText.end(), '\n') + 1; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 537912. capfredf added a comment. move the comment up Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line = LE.readLine()) { llvm::StringRef L = *Line; L = L.trim(); @@ -168,10 +169,10 @@ } Input += L; - if (Input == R"(%quit)") { break; - } else if (Input == R"(%undo)") { + } + if (Input == R"(%undo)") { if (auto Err = Interp->Undo()) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); HasError = true; Index: clang/lib/Interpreter/Interpreter.cpp === --- clang/lib/Interpreter/Interpreter.cpp +++ clang/lib/Interpreter/Interpreter.cpp @@ -14,6 +14,7 @@ #include "clang/Interpreter/Interpreter.h" #include "DeviceOffload.h" +#include "ExternalSource.h" #include "IncrementalExecutor.h" #include "IncrementalParser.h" @@ -33,6 +34,7 @@ #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Value.h" #include "clang/Lex/Preproces
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 537915. capfredf added a comment. remove an unused decl Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line = LE.readLine()) { llvm::StringRef L = *Line; L = L.trim(); @@ -168,10 +169,10 @@ } Input += L; - if (Input == R"(%quit)") { break; - } else if (Input == R"(%undo)") { + } + if (Input == R"(%undo)") { if (auto Err = Interp->Undo()) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); HasError = true; Index: clang/lib/Interpreter/Interpreter.cpp === --- clang/lib/Interpreter/Interpreter.cpp +++ clang/lib/Interpreter/Interpreter.cpp @@ -14,6 +14,7 @@ #include "clang/Interpreter/Interpreter.h" #include "DeviceOffload.h" +#include "ExternalSource.h" #include "IncrementalExecutor.h" #include "IncrementalParser.h" @@ -33,6 +34,7 @@ #include "clang/Driver/Tool.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Value.h" #include "clang/Lex/Preproc
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf marked an inline comment as not done. capfredf added inline comments. Comment at: clang/lib/Interpreter/CodeCompletion.cpp:84 + std::string AllCodeText = + MainInterp.getAllInput() + "\nvoid dummy(){\n" + Buffer.str() + "}"; + auto Lines = std::count(AllCodeText.begin(), AllCodeText.end(), '\n') + 1; capfredf wrote: > v.g.vassilev wrote: > > I am not sure why we need to wrap this code. Can we teach the > > `TopLevelStmtDecl` to work with the code completion logic? > I think the problem has less to do with the TopLevelStmtDecl. Usually, a > `TopLevelStmtDecl` instance is a successful result from `ParseX`, but > when `CodeCompletion` is triggered during parsing, nothing meaning comes out > from `Parse`. > > We need to wrap our input because we need `Sema::CodeCompleteOrdinaryName` to > work on code from the REPL in a different completion context than the same > code from a regular source file. > > In a regular C++ file, > > ``` > int foo = 42; > f_ > ``` > > Since top-level expressions are not supported, `foo` should not be an option. > > But in a REPL session, > > ``` > clang-repl> int foo = 42; > clang-repl> f_ > ``` > > we are allowed to use `foo` to make a statement like `foo + 84;`. > > Since the argument for `CompletionContext` to `CodeCompleteOrdinaryName` is > controlled by the parsing process, ie. there is no way to configure it from > outside, I think faking context is a straightforward solution. > > Alternatively, we can check if the compiler is in incremental mode and call > `CodeCompleteOrdinaryName` with the context we want in parsing. Something > like: > > ``` > if (PP.isIncrementalProcessingEnabled() { > Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement); > } else { > Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace); > } > ``` > > I personally think both solutions are extensionally equivalent, but the > alternative is a bit intrusive. I think the combination of checking `isIncrementalProcessingEnabled` and adding a new PCC might be better since it is really a different context at the REPL Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 537933. capfredf marked an inline comment as not done. capfredf added a comment. get rid of the wrapping Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/tools/clang-repl/ClangRepl.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line = LE.readLine()) { llvm::StringRef L = *Line; L = L.trim(); @@ -168,10 +169,10 @@ } Input += L; - if (Input == R"(%quit)") { break; - } else if (Input == R"(%undo)") { + } + if (Input == R"(%undo)") { if (auto Err = Interp->Undo()) { llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: "); HasError = true; Index: clang/lib/Sema/SemaCodeComplete.cpp === --- clang/lib/Sema/SemaCodeComplete.cpp +++ clang/lib/Sema/SemaCodeComplete.cpp @@ -225,6 +225,7 @@ case CodeCompletionContext::CCC_ObjCMessageReceiver: case CodeCompletionContext::CCC_ParenthesizedExpression: case CodeCompletionContext::CCC_St
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf marked 5 inline comments as done. capfredf added inline comments. Comment at: clang/include/clang/Interpreter/Interpreter.h:117 ASTContext &getASTContext(); + void CodeComplete(llvm::StringRef Input, size_t Col, size_t Line = 1); const CompilerInstance *getCompilerInstance() const; v.g.vassilev wrote: > I could not find where this interface was used. If it is unused, let'd drop > it. it is used at L86 of CodeCompletion.cpp Comment at: clang/lib/Interpreter/IncrementalParser.cpp:376 // Create FileID for the current buffer. - FileID FID = SM.createFileID(std::move(MB), SrcMgr::C_User, /*LoadedID=*/0, - /*LoadedOffset=*/0, NewLoc); + // FileID FID = SM.createFileID(std::move(MB), SrcMgr::C_User, /*LoadedID=*/0, + // /*LoadedOffset=*/0, NewLoc); v.g.vassilev wrote: > Why we had to comment out this line? This is old code. `FID` is created in a different way. See below. I will remove the commented code Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 539572. capfredf marked 2 inline comments as done. capfredf edited the summary of this revision. capfredf added a comment. Herald added a subscriber: arphaman. - rename - Do not export ReplCompletionConsumer - remove commented code Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/Sema.h clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/tools/libclang/CIndexCodeCompletion.cpp Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -543,6 +543,7 @@ case CodeCompletionContext::CCC_PreprocessorExpression: case CodeCompletionContext::CCC_PreprocessorDirective: case CodeCompletionContext::CCC_Attribute: +case CodeCompletionContext::CCC_ReplTopLevel: case CodeCompletionContext::CCC_TypeQualifiers: { //Only Clang results should be accepted, so we'll set all of the other //context bits to 0 (i.e. the empty set) Index: clang/lib/Sema/SemaCodeComplete.cpp === --- clang/lib/Sema/SemaCodeComplete.cpp +++ clang/lib/Sema/SemaCodeComplete.cpp @@ -1851,7 +1851,7 @@ case Sema::PCC_ObjCInstanceVariableList: case Sema::PCC_Expression: case Sema::PCC_Statement: - case Sema::PCC_ReplTopLevel: + case Sema::PCC_TopLevelStmtDecl: case Sema::PCC_ForInit: case Sema::PCC_Condition: case Sema::PCC_RecoveryInFunction: @@ -1909,7 +1909,7 @@ case Sema::PCC_Type: case Sema::PCC_ParenthesizedExpression: case Sema::PCC_LocalDeclarationSpecifiers: - case Sema::PCC_ReplTopLevel: + case Sema::PCC_TopLevelStmtDecl: return true; case Sema::PCC_Expression: @@ -,7 +,7 @@ break; case Sema::PCC_RecoveryInFunction: - case Sema::PCC_ReplTopLevel: + case Sema::PCC_TopLevelStmtDecl: case Sema::PCC_Statement: { if (SemaRef.getLangOpts().CPlusPlus11) AddUsingAliasResult(Builder, Results); @@ -4212,7 +4212,7 @@ case Sema::PCC_LocalDeclarationSpecifiers: return CodeCompletionContext::CCC_Type; - case Sema::PCC_ReplTopLevel: + case Sema::PCC_TopLevelStmtDecl: return CodeCompletionContext::CCC_ReplTopLevel; } @@ -4354,7 +4354,7 @@ break; case PCC_Statement: - case PCC_ReplTopLevel: + case PCC_TopLevelStmtDecl: case PCC_ParenthesizedExpression: case PCC_Expression: case PCC_ForInit: @@ -4392,7 +4392,7 @@ case PCC_ParenthesizedExpression: case PCC_Expression: case PCC_Statement: - case PCC_ReplTopLevel: + case PCC_TopLevelStmtDecl: case PCC_RecoveryInFunction: if (S->getFnParent()) AddPrettyFunctionResults(getLangOpts(), Results); Index: clang/lib/Parse/Parser.cpp === --- clang/lib/Parse/Parser.cpp +++ clang/lib/Parse/Parser.cpp @@ -928,7 +928,7 @@ if (CurParsedObjCImpl) { PCC = Sema::PCC_ObjCImplementation; } else if (PP.isIncrementalProcessingEnabled()) { - PCC = Sema::PCC_ReplTopLevel; + PCC = Sema::PCC_TopLevelStmtDecl; } else { PCC = Sema::PCC_Namespace; }; Index: clang/lib/Interpreter/Interpreter.cpp === --- clang/lib/Interpreter/Interpreter.cpp +++ clang/lib/Interpreter/Interpreter.cpp @@ -239,12 +239,11 @@ } Interpreter::Interpreter(std::unique_ptr CI, llvm::Error &Err, - std::vector &CompResults, + CodeCompleteConsumer* CConsumer, const CompilerInstance *ParentCI) { llvm::ErrorAsOutParameter EAO(&Err); auto LLVMCtx = std::make_unique(); TSCtx = std::make_unique(std::move(LLVMCtx)); - auto *CConsumer = new ReplCompletionConsumer(CompResults); CI->setCodeCompletionConsumer(CConsumer); IncrParser = std::make_unique( *this, std::move(CI), *TSCtx->getContext(), Err, ParentCI); @@ -304,7 +303,7 @@ llvm::Expected> Interpreter::createForCodeCompletion( IncrementalCompilerBuilder &CB, const CompilerInstance *ParentCI, -std::vector &CompResults) { +CodeCompleteConsumer* CConsumer) { auto CI = CB.CreateCpp(); if (auto Err = CI.takeError()) { return std::move(Err); @@ -315,12 +314,9 @@ (*CI)->getLangOpts().SpellChecking = false; (*CI)->getLangOpts().DelayedTemplateParsing = false; - auto &FrontendOpts = (*CI)->getFrontendOpts(); - FrontendOpts.CodeCompleteOpts = getClangCompleteOpts(); - llvm::Error Err = llvm::Error::success(); auto I
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 539578. capfredf edited the summary of this revision. capfredf added a comment. @v.g.vassilev I moved the ReplCodeCompletionConsumer class out of the header file, since it is not needed elsewhere. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Interpreter/Interpreter.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/ExternalSource.cpp clang/lib/Interpreter/ExternalSource.h clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,61 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Interpreter/Interpreter.h" + +#include "llvm/LineEditor/LineEditor.h" + +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("f"), 1); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0].TypedText, std::string("oo")); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("babanana"), 8); + EXPECT_EQ((size_t)0, comps.size()); // foo and float +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Completer = ReplListCompleter(CB, *Interp); + std::vector comps = + Completer(std::string("app"), 3); + EXPECT_EQ((size_t)2, comps.size()); +} +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -543,6 +543,7 @@ case CodeCompletionContext::CCC_PreprocessorExpression: case CodeCompletionContext::CCC_PreprocessorDirective: case CodeCompletionContext::CCC_Attribute: +case CodeCompletionContext::CCC_ReplTopLevel: case CodeCompletionContext::CCC_TypeQualifiers: { //Only Clang results should be accepted, so we'll set all of the other //context bits to 0 (i.e. the empty set) Index: clang/tools/clang-repl/ClangRepl.cpp === --- clang/tools/clang-repl/ClangRepl.cpp +++ clang/tools/clang-repl/ClangRepl.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Interpreter/CodeCompletion.h" #include "clang/Interpreter/Interpreter.h" #include "llvm/ExecutionEngine/Orc/LLJIT.h" @@ -155,8 +156,8 @@ if (OptInputs.empty()) { llvm::LineEditor LE("clang-repl"); -// FIXME: Add LE.setListCompleter std::string Input; +LE.setListCompleter(clang::ReplListCompleter(CB, *Interp)); while (std::optional Line
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf added inline comments. Comment at: clang/lib/Interpreter/Interpreter.cpp:304 +llvm::Expected> +Interpreter::createForCodeCompletion( +IncrementalCompilerBuilder &CB, const CompilerInstance *ParentCI, v.g.vassilev wrote: > I still do not entirely understand why we can "just" ask the codecompletion > infrastructure for the possible options at the current position. I know > that's probably easier set than done but I'd like to entertain that idea for > a while.. I'm a bit confused. Can you expand on the suggestion? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf added inline comments. Comment at: clang/lib/Interpreter/CodeCompletion.cpp:102 + std::vector Results; + auto *CConsumer = new ReplCompletionConsumer(Results); + auto Interp = Interpreter::createForCodeCompletion( v.g.vassilev wrote: > Let's move this in `Interpreter::createForCodeCompletion`. The reasons I moved this out of `Interpreter::createForCodeCompletion` are 1. Design-wise, we don't need to expose `ReplCompletionConsumer` to `Interpreter.cpp`. All `createForCodeCompletion` needs is a subclass instance of `CodeCompletionConsumer`. 2. ReplCompletionConsumer has more data members on the type-directed branch than the one on this branch. I'd rather create an instance here than pass all the necessary arguments to one layer down and do that there. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 553759. capfredf added a comment. fix potential memory issues Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang-tools-extra/clangd/CodeComplete.cpp clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,100 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + std::vector Comps; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results); + + for (auto Res : Results) +if (Res.find(Prefix) == 0) + Comps.push_back(Res); + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("foo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -11,8 +11,8 @@ // //===-
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 553762. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang-tools-extra/clangd/CodeComplete.cpp clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + std::vector Comps; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, /* Lines */ 1, Prefix.size(), MainInterp.getCompilerInstance(), + Results); + + for (auto Res : Results) +if (Res.find(Prefix) == 0) + Comps.push_back(Res); + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("foo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -11,8 +11,8 @@ // //===--===// -#in
[PATCH] D154382: [ClangRepl] support code completion at a REPL
capfredf updated this revision to Diff 554002. capfredf added a comment. fix memory issues Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D154382/new/ https://reviews.llvm.org/D154382 Files: clang-tools-extra/clangd/CodeComplete.cpp clang/include/clang/Frontend/ASTUnit.h clang/include/clang/Interpreter/CodeCompletion.h clang/include/clang/Sema/CodeCompleteConsumer.h clang/include/clang/Sema/Sema.h clang/lib/Frontend/ASTUnit.cpp clang/lib/Interpreter/CMakeLists.txt clang/lib/Interpreter/CodeCompletion.cpp clang/lib/Interpreter/IncrementalParser.cpp clang/lib/Interpreter/IncrementalParser.h clang/lib/Interpreter/Interpreter.cpp clang/lib/Parse/ParseDecl.cpp clang/lib/Parse/Parser.cpp clang/lib/Sema/CodeCompleteConsumer.cpp clang/lib/Sema/SemaCodeComplete.cpp clang/test/CodeCompletion/incrememal-mode-completion-no-error.cpp clang/test/CodeCompletion/incremental-top-level.cpp clang/tools/clang-repl/ClangRepl.cpp clang/tools/libclang/CIndexCodeCompletion.cpp clang/unittests/Interpreter/CMakeLists.txt clang/unittests/Interpreter/CodeCompletionTest.cpp Index: clang/unittests/Interpreter/CodeCompletionTest.cpp === --- /dev/null +++ clang/unittests/Interpreter/CodeCompletionTest.cpp @@ -0,0 +1,101 @@ +#include "clang/Interpreter/CodeCompletion.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Interpreter/Interpreter.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +using namespace clang; +namespace { +auto CB = clang::IncrementalCompilerBuilder(); + +static std::unique_ptr createInterpreter() { + auto CI = cantFail(CB.CreateCpp()); + return cantFail(clang::Interpreter::create(std::move(CI))); +} + +static std::vector runComp(clang::Interpreter &MainInterp, +llvm::StringRef Prefix, +llvm::Error &ErrR) { + auto CI = CB.CreateCpp(); + if (auto Err = CI.takeError()) { +ErrR = std::move(Err); +return {}; + } + + auto Interp = clang::Interpreter::create(std::move(*CI)); + if (auto Err = Interp.takeError()) { +// log the error and returns an empty vector; +ErrR = std::move(Err); + +return {}; + } + + std::vector Results; + std::vector Comps; + + codeComplete( + const_cast((*Interp)->getCompilerInstance()), + Prefix, /* Lines */ 1, Prefix.size(), MainInterp.getCompilerInstance(), + Results); + + for (auto Res : Results) +if (Res.find(Prefix) == 0) + Comps.push_back(Res); + + return Comps; +} + +TEST(CodeCompletionTest, Sanity) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "f", Err); + EXPECT_EQ((size_t)2, comps.size()); // foo and float + EXPECT_EQ(comps[0], std::string("foo")); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, SanityNoneValid) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int foo = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "babanana", Err); + EXPECT_EQ((size_t)0, comps.size()); // foo and float + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, TwoDecls) { + auto Interp = createInterpreter(); + if (auto R = Interp->ParseAndExecute("int application = 12;")) { +consumeError(std::move(R)); +return; + } + if (auto R = Interp->ParseAndExecute("int apple = 12;")) { +consumeError(std::move(R)); +return; + } + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "app", Err); + EXPECT_EQ((size_t)2, comps.size()); + EXPECT_EQ((bool)Err, false); +} + +TEST(CodeCompletionTest, CompFunDeclsNoError) { + auto Interp = createInterpreter(); + auto Err = llvm::Error::success(); + auto comps = runComp(*Interp, "void app(", Err); + EXPECT_EQ((bool)Err, false); +} + +} // anonymous namespace Index: clang/unittests/Interpreter/CMakeLists.txt === --- clang/unittests/Interpreter/CMakeLists.txt +++ clang/unittests/Interpreter/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_unittest(ClangReplInterpreterTests IncrementalProcessingTest.cpp InterpreterTest.cpp + CodeCompletionTest.cpp ) target_link_libraries(ClangReplInterpreterTests PUBLIC clangAST Index: clang/tools/libclang/CIndexCodeCompletion.cpp === --- clang/tools/libclang/CIndexCodeCompletion.cpp +++ clang/tools/libclang/CIndexCodeCompletion.cpp @@ -11,8 +11,8 @@ // //===
[PATCH] D159213: [AIX][ClangRepl] Disable new tests on AIX
capfredf added a comment. Thanks! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D159213/new/ https://reviews.llvm.org/D159213 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits