[Lldb-commits] [lldb] r342385 - Add descriptions to completed expressions

Raphael Isemann via lldb-commits lldb-commits at lists.llvm.org
Mon Sep 17 05:06:08 PDT 2018


Author: teemperor
Date: Mon Sep 17 05:06:07 2018
New Revision: 342385

URL: http://llvm.org/viewvc/llvm-project?rev=342385&view=rev
Log:
Add descriptions to completed expressions

Summary:
Completing inside the expression command now uses the new description API
to also provide additional information to the user. For now this information
are the types of variables/fields and the signatures of completed function calls.

Reviewers: #lldb, JDevlieghere

Reviewed By: JDevlieghere

Subscribers: JDevlieghere, lldb-commits

Differential Revision: https://reviews.llvm.org/D52103

Modified:
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py
    lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp

Modified: lldb/trunk/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py?rev=342385&r1=342384&r2=342385&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/completion/TestExprCompletion.py Mon Sep 17 05:06:07 2018
@@ -195,6 +195,39 @@ class CommandLineExprCompletionTestCase(
         self.complete_exactly('expr some_expr.Self(). FooNoArgs',
                               'expr some_expr.Self(). FooNoArgsBar()')
 
+    @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489")
+    def test_expr_completion_with_descriptions(self):
+        self.build()
+        self.main_source = "main.cpp"
+        self.main_source_spec = lldb.SBFileSpec(self.main_source)
+        self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
+
+        (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
+                                          '// Break here', self.main_source_spec)
+
+        self.check_completion_with_desc("expr ", [
+            # VarDecls have their type as description.
+            ["some_expr", "Expr &"],
+            # builtin types have no description.
+            ["int", ""],
+            ["float", ""]
+        ])
+        self.check_completion_with_desc("expr some_expr.", [
+            # Functions have their signature as description.
+            ["some_expr.Self()", "Expr &Self()"],
+            ["some_expr.operator=(", "inline Expr &operator=(const Expr &)"],
+            ["some_expr.FooNumbersBar1()", "int FooNumbersBar1()"],
+            ["some_expr.StaticMemberMethodBar()", "static int StaticMemberMethodBar()"],
+            ["some_expr.FooWithArgsBar(", "int FooWithArgsBar(int)"],
+            ["some_expr.FooNoArgsBar()", "int FooNoArgsBar()"],
+            ["some_expr.FooUnderscoreBar_()", "int FooUnderscoreBar_()"],
+            ["some_expr.FooWithMultipleArgsBar(", "int FooWithMultipleArgsBar(int, int)"],
+            ["some_expr.~Expr()", "inline ~Expr()"],
+            # FieldDecls have their type as description.
+            ["some_expr.MemberVariableBar", "int"],
+        ])
+
+
     def assume_no_completions(self, str_input, cursor_pos = None):
         interp = self.dbg.GetCommandInterpreter()
         match_strings = lldb.SBStringList()

Modified: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp?rev=342385&r1=342384&r2=342385&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp Mon Sep 17 05:06:07 2018
@@ -14,6 +14,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/ExternalASTSource.h"
+#include "clang/AST/PrettyPrinter.h"
 #include "clang/Basic/DiagnosticIDs.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/SourceLocation.h"
@@ -564,6 +565,9 @@ class CodeComplete : public CodeComplete
   std::string m_expr;
   unsigned m_position = 0;
   CompletionRequest &m_request;
+  /// The printing policy we use when printing declarations for our completion
+  /// descriptions.
+  clang::PrintingPolicy m_desc_policy;
 
   /// Returns true if the given character can be used in an identifier.
   /// This also returns true for numbers because for completion we usually
@@ -638,10 +642,22 @@ public:
   /// @param[out] position
   ///    The character position of the user cursor in the `expr` parameter.
   ///
-  CodeComplete(CompletionRequest &request, std::string expr, unsigned position)
+  CodeComplete(CompletionRequest &request, clang::LangOptions ops,
+               std::string expr, unsigned position)
       : CodeCompleteConsumer(CodeCompleteOptions(), false),
         m_info(std::make_shared<GlobalCodeCompletionAllocator>()), m_expr(expr),
-        m_position(position), m_request(request) {}
+        m_position(position), m_request(request), m_desc_policy(ops) {
+
+    // Ensure that the printing policy is producing a description that is as
+    // short as possible.
+    m_desc_policy.SuppressScope = true;
+    m_desc_policy.SuppressTagKeyword = true;
+    m_desc_policy.FullyQualifiedName = false;
+    m_desc_policy.TerseOutput = true;
+    m_desc_policy.IncludeNewlines = false;
+    m_desc_policy.UseVoidForZeroParams = false;
+    m_desc_policy.Bool = true;
+  }
 
   /// Deregisters and destroys this code-completion consumer.
   virtual ~CodeComplete() {}
@@ -692,6 +708,7 @@ public:
 
       CodeCompletionResult &R = Results[I];
       std::string ToInsert;
+      std::string Description;
       // Handle the different completion kinds that come from the Sema.
       switch (R.Kind) {
       case CodeCompletionResult::RK_Declaration: {
@@ -705,10 +722,16 @@ public:
             ToInsert += "()";
           else
             ToInsert += "(";
-        }
-        // If we try to complete a namespace, then we can directly append
-        // the '::'.
-        if (const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
+          raw_string_ostream OS(Description);
+          F->print(OS, m_desc_policy, false);
+          OS.flush();
+        } else if (const VarDecl *V = dyn_cast<VarDecl>(D)) {
+          Description = V->getType().getAsString(m_desc_policy);
+        } else if (const FieldDecl *F = dyn_cast<FieldDecl>(D)) {
+          Description = F->getType().getAsString(m_desc_policy);
+        } else if (const NamespaceDecl *N = dyn_cast<NamespaceDecl>(D)) {
+          // If we try to complete a namespace, then we can directly append
+          // the '::'.
           if (!N->isAnonymousNamespace())
             ToInsert += "::";
         }
@@ -735,7 +758,7 @@ public:
         // with the kind of result the lldb API expects.
         std::string CompletionSuggestion =
             mergeCompletion(m_expr, m_position, ToInsert);
-        m_request.AddCompletion(CompletionSuggestion);
+        m_request.AddCompletion(CompletionSuggestion, Description);
       }
     }
   }
@@ -773,7 +796,8 @@ bool ClangExpressionParser::Complete(Com
   // the LLVMUserExpression which exposes the right API. This should never fail
   // as we always have a ClangUserExpression whenever we call this.
   LLVMUserExpression &llvm_expr = *static_cast<LLVMUserExpression *>(&m_expr);
-  CodeComplete CC(request, llvm_expr.GetUserText(), typed_pos);
+  CodeComplete CC(request, m_compiler->getLangOpts(), llvm_expr.GetUserText(),
+                  typed_pos);
   // We don't need a code generator for parsing.
   m_code_generator.reset();
   // Start parsing the expression with our custom code completion consumer.




More information about the lldb-commits mailing list