[PATCH] D154382: [ClangRepl] support code completion at a REPL

2023-07-18 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-20 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-20 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-21 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-12 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-12 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-13 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-13 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-13 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-13 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-13 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-13 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-15 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-15 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-15 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-16 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-17 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-22 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-23 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-23 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-01 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-04 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-03 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-06 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-12 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-12 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-12 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-13 Thread Fred Fu via Phabricator via cfe-commits
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

2023-07-13 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-26 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-26 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-28 Thread Fred Fu via Phabricator via cfe-commits
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

2023-08-30 Thread Fred Fu via Phabricator via cfe-commits
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