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

2023-08-28 Thread Vassil Vassilev via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5ab25a42ba70: Reland "[clang-repl] support code 
completion at a REPL." (authored by capfredf, committed by v.g.vassilev).

Changed prior to commit:
  https://reviews.llvm.org/D154382?vs=554002&id=554027#toc

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/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/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

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 "CIndexer.h"
 #include "CIndexDiagnostic.h"
+#include "CIndexer.h"
 #include "CLog.h"
 #include "CXCursor.h"
 #include "CXSourceLocation.h"
@@ -25,6 +25,7 @@
 #include "clang/Basic/SourceManager.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
 #include "clang/Sema/CodeCompleteConsumer.h"
 #include "clang/Sema/Sema.h"
 #include "llvm/ADT/SmallString.h"
@@ -41,7 +42,6 @@
 #include 
 #include 
 
-
 #ifdef UDP_CODE_COMPLETION_LOGGER
 #include "clang/Basic/Version.h"
 #include 
@@ -543,6 +543,7 @@
 case CodeCompletionContext::CCC_PreprocessorExpression:
 case CodeCompletionContext::CCC_PreprocessorDirective:
 case CodeCompletionContext::CCC_Attribute:
+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
@@ -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"
@@ -70,6 +71,70 @@
   return (Errs || HasError) ? EXIT_FAILURE : EXIT_SUCCESS;
 }
 
+struct ReplListCompleter {
+  clang::IncrementalCompilerBuilder &CB;
+  clang::Interpreter &MainInterp;
+  ReplListCompleter(clang::IncrementalCompilerBuilder &CB,
+clang::Interpreter &Interp)
+  : CB(CB), MainInterp(Interp){};
+
+  std::vector operator()(llvm::StringRef Buffer,
+   size_t Pos) const;
+  std::vector
+  operator()(llvm::StringRef Buffer, size_t Pos, llvm::Error &ErrRes) const;
+};
+
+std::vector
+ReplListCompleter::operator()(llvm::StringRef Buffer, size_t Pos) const {
+  auto Err = llvm::Error::success();
+  auto res = (*this)(Buffer, Pos, Err);
+  if (Err)
+llvm::logAllUnhandledErrors(std::move(Err), llvm::errs(), "error: ");
+  return res;
+}
+
+std::vector
+ReplListCompleter::operator()(llvm::StringRef Buffer, size_t Pos,
+  llvm::Error &ErrRes) const {
+  std::vector Comps;
+  std::vector Results;
+
+  auto CI = CB.CreateCpp();
+  if (auto Err = CI.takeError()) {
+ErrRes = std::move(Err);
+return {};
+  }
+
+  size_t Lines =
+  std::count(Buffer.begin(), std::next(Buffer.begin(), Pos), '\n') + 1;
+  auto Interp = clang::Interpreter::create(std::move(*CI));
+
+  if (auto Err = Interp.takeError()) {
+// log the error and returns an empty vector;
+ErrRes = std::move(Err);
+
+return {};
+  }
+
+  codeComplete(
+  const_cast((*Interp)->getCompilerInstance()),
+  Buffer, Lines, Pos + 1, MainInterp.getCompilerInstance(), Results);
+
+  size_t space_po

[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] 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-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-25 Thread Sam McCall via Phabricator via cfe-commits
sammccall added inline comments.



Comment at: clang-tools-extra/clangd/CodeComplete.cpp:845
   case CodeCompletionContext::CCC_NewName:
+  case CodeCompletionContext::CCC_TopLevelOrExpression:
 return false;

This should be `true` rather than `false`, since both TopLevel and Expression 
are completed using the index.

(Though I realize that for now we'll never hit this context)


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-24 Thread Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added inline comments.



Comment at: clang/unittests/Interpreter/CodeCompletionTest.cpp:38
+
+  std::vector Results;
+

We should make this an out parameter instead of returning it by copy.



Comment at: clang/unittests/Interpreter/CodeCompletionTest.cpp:42
+  const_cast((*Interp)->getCompilerInstance()),
+  Prefix, 1, Prefix.size(), MainInterp.getCompilerInstance(), Results);
+




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-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-23 Thread Vassil Vassilev via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGeb0e6c3134ef: [clang-repl] support code completion at a 
REPL. (authored by capfredf, committed by v.g.vassilev).

Changed prior to commit:
  https://reviews.llvm.org/D154382?vs=552418&id=552696#toc

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

[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] D154382: [ClangRepl] support code completion at a REPL

2023-08-19 Thread Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev accepted this revision.
v.g.vassilev added a comment.

Thanks for working on this @capfredf. Let me know if I should land that for you.


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-18 Thread Sam McCall via Phabricator via cfe-commits
sammccall accepted this revision.
sammccall added a comment.
This revision is now accepted and ready to land.

LGTM, thanks!




Comment at: clang/include/clang/Sema/CodeCompleteConsumer.h:341
+
+/// Code completion at a top level in a REPL session.
+CCC_TopLevelOrExpression,

I think this is non-obvious & worthy of more explanation

```
/// Completion in a namespace or global scope, but also accept expressions.
/// This occurs in REPL inputs, which may declare things  or print expression
/// values.
```


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-17 Thread Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added a comment.

@sammccall could you take another look? It seems quite ready to me to land.


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-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-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-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-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 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-14 Thread Sam McCall via Phabricator via cfe-commits
sammccall added a comment.

This mostly looks good.

My main concern is adding code to the parser to suppress errors when code 
completing: this is unlikely to be the only such place. Existing consumers seem 
happy to ignore errors, if this doesn't work for clang-repl it'd be good to 
understand why.




Comment at: clang/include/clang/Frontend/ASTUnit.h:891
   ///
+  /// \param Act A SyntaxOnlyAction performs actions on the syntax.
+  ///

This comment doesn't really say anything beyond echoing the name/type, either 
remove it or add some separate explanation?

e.g. "If Act is specified, it will be used to parse the file. This allows 
customizing the parse by overriding FrontendAction's lifecycle methods."



Comment at: clang/include/clang/Frontend/ASTUnit.h:901
+SmallVectorImpl &OwnedBuffers,
+std::function 
AfterBeginSourceFile = [](CompilerInstance& CI) -> void {});
 

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.)



Comment at: clang/include/clang/Interpreter/InterpreterCodeCompletion.h:30
+std::vector
+ConvertToCodeCompleteStrings(const std::vector &Results);
+} // namespace clang

nit: lowercase initial letter for functions



Comment at: clang/include/clang/Interpreter/InterpreterCodeCompletion.h:30
+std::vector
+ConvertToCodeCompleteStrings(const std::vector &Results);
+} // namespace clang

sammccall wrote:
> nit: lowercase initial letter for functions
you might consider `vector` instead.

this signature doesn't provide any way to return owned names, and so requires 
that the results are already allocated somewhere as contiguous strings.

This will prevents completing names like `operator int`, as well as some 
non-names that might prove useful.

This is an interactive operation, copying the strings is unlikely to add 
significant latency on human scale.



Comment at: clang/include/clang/Sema/CodeCompleteConsumer.h:342
+/// Code completion at a top level in a REPL session.
+CCC_ReplTopLevel,
   };

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`?



Comment at: clang/lib/Interpreter/InterpreterCodeCompletion.cpp:72
+  break;
+default:
+  break;

(up to you, but default between cases seems surprising)



Comment at: clang/lib/Parse/ParseDecl.cpp:6648
 if (Tok.is(tok::l_paren)) {
+  if (PP.isIncrementalProcessingEnabled() &&
+  NextToken().is(tok::code_completion)) {

AIUI, all code completion actions should be ignoring errors, and we should 
always be happy to cut off parsing and give up as soon as the completion token 
is reached.

So why do we need special handling for incremental processing here?

(i.e. what behavior do non-repl users see here - if it's correct can clang-repl 
do the same, if it's wrong why don't we fix both?)


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 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-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 Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added inline comments.



Comment at: clang/lib/Interpreter/CodeCompletion.cpp:1
+//===-- CodeCompletion.cpp - Code Completion for ClangRepl ---===//
+//

I would propose to rename this file to `InterpreterCodeCompletion.cpp` and 
implement the `Interpreter::codeComplete` interface. Then we can move all of 
the content of `ExternalSource.{h,cpp}`, `CodeCompletion.h` and 
`ExternalSource.h` in it. That will increase the encapsulation of the 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-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 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 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 Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added a reviewer: sammccall.
v.g.vassilev added a subscriber: sammccall.
v.g.vassilev added a comment.

This looks mostly good to me. I noticed that @sammccall has done some work in 
that area in clangd and I was wondering if he has some thoughts about this 
patch.


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 Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added inline comments.



Comment at: clang/lib/Interpreter/IncrementalParser.h:91
+
+class IncrementalSyntaxOnlyAction : public SyntaxOnlyAction {
+  const CompilerInstance *ParentCI;

Can we not move this class definition locally to the CodeComplete interface?


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-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-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-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-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-07-31 Thread Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added a comment.

I think we are getting there. I added a few suggestions how to improve the 
current design.




Comment at: clang/include/clang/Interpreter/CodeCompletion.h:15
+#define LLVM_CLANG_INTERPRETER_CODE_COMPLETION_H
+#include "llvm/LineEditor/LineEditor.h"
+

I still am a bit uncomfortable with relying on a line editor api to address a 
generic question one could as the interpreter such as "What's visible at that 
code position"?

Can we not make the overloaded operators outside of the `ReplListCompleter` 
class. That means moving them in ClangRepl.cpp?



Comment at: clang/include/clang/Interpreter/Interpreter.h:42
 class IncrementalParser;
+class CodeCompleteConsumer;
 

We should put that in its alphabetical order.



Comment at: clang/lib/Interpreter/CodeCompletion.cpp:111
+  auto *CConsumer = new ReplCompletionConsumer(Results);
+  auto Interp = Interpreter::createForCodeCompletion(
+  CB, MainInterp.getCompilerInstance(), CConsumer);

I do not believe we need a spe



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) {

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?



Comment at: clang/lib/Interpreter/Interpreter.cpp:304
+llvm::Expected>
+Interpreter::createForCodeCompletion(
+IncrementalCompilerBuilder &CB, const CompilerInstance *ParentCI,

capfredf wrote:
> 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?
I do not believe we need a special case for creating a CodeCompletionConsumer. 
I think we could rely on the logic in 
`CompilerInstance::createCodeCompletionConsumer` which can be triggered in 
`IncrementalAction::ExecuteAction` just like in 
`ASTFrontendAction::ExecuteAction`. We will need to copy some of the code over 
but then you could start the same interpreter infrastructure with slightly 
different flags.



Comment at: clang/lib/Parse/ParseDecl.cpp:6652
+break;
+  }
+

Can we test this change separately outside of clang-repl? That would mean 
creating a tests and run it with `clang -Xclang -fincremental-extensions`



Comment at: clang/lib/Parse/Parser.cpp:934
+  PCC = Sema::PCC_Namespace;
+};
 Actions.CodeCompleteOrdinaryName(

Likewise, it would be great if we have a test in clang-only mode.


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-07-20 Thread Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added inline comments.



Comment at: clang/unittests/Interpreter/CodeCompletionTest.cpp:71
+Completer(std::string("void app("), 9);
+  EXPECT_EQ((size_t)0, out.length());
+}

capfredf wrote:
> @v.g.vassilev The way I fixed this is a bit hacky. Do you have a better idea?
Now I think I understand what you were after. Instead of handling the error in 
the constructor we should handle it in the caller. Here is some information how 
we could do that: 
https://llvm.org/docs/ProgrammersManual.html#fallible-constructors


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-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-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-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-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-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-12 Thread Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added inline comments.



Comment at: clang/include/clang/Sema/CodeCompleteConsumer.h:342
+/// Code completion at a top level in a REPL session.
+CCC_ReplTopLevel,
   };





Comment at: clang/lib/Interpreter/CodeCompletion.cpp:102
+  std::vector Results;
+  auto *CConsumer = new ReplCompletionConsumer(Results);
+  auto Interp = Interpreter::createForCodeCompletion(

Let's move this in `Interpreter::createForCodeCompletion`.



Comment at: clang/lib/Interpreter/CodeCompletion.cpp:118
+  llvm::StringRef s;
+  if (space_pos == llvm::StringRef::npos) {
+s = Buffer;

Please remove the braces around single statement blocks.



Comment at: clang/lib/Interpreter/Interpreter.cpp:304
+llvm::Expected>
+Interpreter::createForCodeCompletion(
+IncrementalCompilerBuilder &CB, const CompilerInstance *ParentCI,

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..


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 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-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 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 Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added a reviewer: aaron.ballman.
v.g.vassilev added a subscriber: aaron.ballman.
v.g.vassilev added a comment.

@capfredf this seems to be heading in a good direction. Please find another 
round of comments.

@aaron.ballman, I could not find a person that's active in that area. Could you 
help with finding reviewers for this type of patch?




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;

I could not find where this interface was used. If it is unused, let'd drop it.



Comment at: clang/include/clang/Sema/Sema.h:13324
+/// Code completion occurs at top-level in a REPL session
+PCC_ReplTopLevel,
   };





Comment at: clang/lib/Interpreter/IncrementalParser.cpp:338
+  //   return;
+  // }
+  if (FE) {

Seems that we have stray debug fragments? Can you remove them?



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);

Why we had to comment out this line?



Comment at: clang/lib/Interpreter/Interpreter.cpp:248
+  auto *CConsumer = new ReplCompletionConsumer(CompResults);
+  CI->setCodeCompletionConsumer(CConsumer);
+  IncrParser = std::make_unique(

IIUC, `setCodeCompletionConsumer` takes the ownership of `CConsumer`. I'd 
suggest to drop `CConsumer` member.


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-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 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 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 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 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 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 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] D154382: [ClangRepl] support code completion at a REPL

2023-07-05 Thread Vassil Vassilev via Phabricator via cfe-commits
v.g.vassilev added a comment.

Can you extend the commit log to include a description of how things are 
currently done? For example, it would be good to read about design and 
technical decisions, etc.




Comment at: clang/lib/Interpreter/CodeCompletion.cpp:79
+  if (auto Err = Interp.takeError()) {
+llvm::consumeError(std::move(Err));
+return Comps;

Why we drop the error on the floor?



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;

I am not sure why we need to wrap this code. Can we teach the 
`TopLevelStmtDecl` to work with the code completion logic?


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-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