2010-01-06 03:32:54 +08:00
|
|
|
//===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Clang-C Source Indexing library hooks for
|
|
|
|
// code completion.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "CIndexer.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "CIndexDiagnostic.h"
|
2013-01-19 16:09:44 +08:00
|
|
|
#include "CLog.h"
|
2011-07-21 09:05:26 +08:00
|
|
|
#include "CXCursor.h"
|
2011-08-18 06:19:53 +08:00
|
|
|
#include "CXString.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "CXTranslationUnit.h"
|
2011-07-21 09:05:26 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/AST/DeclObjC.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "clang/AST/Type.h"
|
2010-04-13 03:45:50 +08:00
|
|
|
#include "clang/Basic/FileManager.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2010-08-05 00:47:14 +08:00
|
|
|
#include "clang/Frontend/ASTUnit.h"
|
2010-04-13 03:45:50 +08:00
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
2010-01-28 08:56:43 +08:00
|
|
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
2010-01-06 03:32:54 +08:00
|
|
|
#include "clang/Sema/CodeCompleteConsumer.h"
|
Remove unnecessary inclusion of Sema.h
Let me tell you a tale...
Within some twisted maze of debug info I've ended up implementing an
insane man's Include What You Use device. When the debugger emits debug
info it really shouldn't, I find out why & then realize the code could
be improved too.
In this instance CIndexDiagnostics.cpp had a lot more debug info with
Clang than GCC. Upon inspection a major culprit was all the debug info
describing clang::Sema. This was emitted because clang::Sema is
befriended by DiagnosticEngine which was rightly required, but GCC
doesn't emit debug info for friends so it never emitted anything for
Clang. Clang does emit debug info for friends (will be fixed/changed to
reduce debug info size).
But why didn't Clang just emit a declaration of Sema if this entire TU
didn't require a definition?
1) Diagnostic.h did the right thing, only using a declaration of Sema
and not including Sema.h at all.
2) Some other dependency of CIndexDiagnostics.cpp didn't do the right
thing. ASTUnit.h, only needing a declaration, still included Sema.h
(hence this commit which removes that include and adds the necessary
includes to the cpp files that were relying on this)
3) -flimit-debug-info didn't save us because of
EnterExpressionEvaluationContext, defined inline in Sema.h which fires
the "requiresCompleteType" check/flag (since it uses nested types from
Sema and calls Sema member functions) and thus, if debug info is ever
emitted for the type, the whole type is emitted and not just a
declaration.
Improving -flimit-debug-info to account for this would be... hard.
Modifying the code so that's not 'required to be complete' might be
possible, but probably only by moving EnterExpressionEvaluationContext
either into Sema, or out of Sema.h. That might be a bit too much of a
contortion to be bothered with.
Also, this is only one of the cases where emitting debug info for
friends caused us to emit a lot more debug info (this change reduces
Clang's DWO size by 0.93%, dropping friends entirely reduces debug info
by 3.2%) - I haven't hunted down the other cases, but I assume they
might be similar (Sema or something like it). IWYU or a similar tool
might help us reduce build times a bit, but analyzing debug info to find
these differences isn't worthwhile. I'll take the 3.2% win, provide this
small improvement to the code itself, and move on.
llvm-svn: 190715
2013-09-14 02:32:52 +08:00
|
|
|
#include "clang/Sema/Sema.h"
|
2010-08-10 04:45:32 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2010-01-06 03:32:54 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2010-08-20 07:44:10 +08:00
|
|
|
#include "llvm/Support/CrashRecoveryContext.h"
|
2013-06-26 20:54:23 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2010-01-06 03:32:54 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2012-12-04 17:25:21 +08:00
|
|
|
#include "llvm/Support/Program.h"
|
2010-08-10 04:45:32 +08:00
|
|
|
#include "llvm/Support/Timer.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2014-03-03 01:08:31 +08:00
|
|
|
#include <atomic>
|
2010-07-27 00:29:14 +08:00
|
|
|
#include <cstdio>
|
2012-12-04 17:25:21 +08:00
|
|
|
#include <cstdlib>
|
2013-02-08 03:09:22 +08:00
|
|
|
#include <string>
|
2010-01-06 03:32:54 +08:00
|
|
|
|
2010-08-10 04:45:32 +08:00
|
|
|
|
2010-04-15 09:02:28 +08:00
|
|
|
#ifdef UDP_CODE_COMPLETION_LOGGER
|
|
|
|
#include "clang/Basic/Version.h"
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
2010-01-06 03:32:54 +08:00
|
|
|
using namespace clang;
|
2013-01-11 02:54:52 +08:00
|
|
|
using namespace clang::cxindex;
|
2010-01-06 03:32:54 +08:00
|
|
|
|
|
|
|
enum CXCompletionChunkKind
|
|
|
|
clang_getCompletionChunkKind(CXCompletionString completion_string,
|
|
|
|
unsigned chunk_number) {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
2010-01-06 03:32:54 +08:00
|
|
|
if (!CCStr || chunk_number >= CCStr->size())
|
|
|
|
return CXCompletionChunk_Text;
|
|
|
|
|
|
|
|
switch ((*CCStr)[chunk_number].Kind) {
|
|
|
|
case CodeCompletionString::CK_TypedText:
|
|
|
|
return CXCompletionChunk_TypedText;
|
|
|
|
case CodeCompletionString::CK_Text:
|
|
|
|
return CXCompletionChunk_Text;
|
|
|
|
case CodeCompletionString::CK_Optional:
|
|
|
|
return CXCompletionChunk_Optional;
|
|
|
|
case CodeCompletionString::CK_Placeholder:
|
|
|
|
return CXCompletionChunk_Placeholder;
|
|
|
|
case CodeCompletionString::CK_Informative:
|
|
|
|
return CXCompletionChunk_Informative;
|
|
|
|
case CodeCompletionString::CK_ResultType:
|
|
|
|
return CXCompletionChunk_ResultType;
|
|
|
|
case CodeCompletionString::CK_CurrentParameter:
|
|
|
|
return CXCompletionChunk_CurrentParameter;
|
|
|
|
case CodeCompletionString::CK_LeftParen:
|
|
|
|
return CXCompletionChunk_LeftParen;
|
|
|
|
case CodeCompletionString::CK_RightParen:
|
|
|
|
return CXCompletionChunk_RightParen;
|
|
|
|
case CodeCompletionString::CK_LeftBracket:
|
|
|
|
return CXCompletionChunk_LeftBracket;
|
|
|
|
case CodeCompletionString::CK_RightBracket:
|
|
|
|
return CXCompletionChunk_RightBracket;
|
|
|
|
case CodeCompletionString::CK_LeftBrace:
|
|
|
|
return CXCompletionChunk_LeftBrace;
|
|
|
|
case CodeCompletionString::CK_RightBrace:
|
|
|
|
return CXCompletionChunk_RightBrace;
|
|
|
|
case CodeCompletionString::CK_LeftAngle:
|
|
|
|
return CXCompletionChunk_LeftAngle;
|
|
|
|
case CodeCompletionString::CK_RightAngle:
|
|
|
|
return CXCompletionChunk_RightAngle;
|
|
|
|
case CodeCompletionString::CK_Comma:
|
|
|
|
return CXCompletionChunk_Comma;
|
Improve code completion by introducing patterns for the various C and
C++ grammatical constructs that show up in top-level (namespace-level)
declarations, member declarations, template declarations, statements,
expressions, conditions, etc. For example, we now provide a pattern
for
static_cast<type>(expr)
when we can have an expression, or
using namespace identifier;
when we can have a using directive.
Also, improves the results of code completion at the beginning of a
top-level declaration. Previously, we would see value names (function
names, global variables, etc.); now we see types, namespace names,
etc., but no values.
llvm-svn: 93134
2010-01-11 07:08:15 +08:00
|
|
|
case CodeCompletionString::CK_Colon:
|
|
|
|
return CXCompletionChunk_Colon;
|
|
|
|
case CodeCompletionString::CK_SemiColon:
|
|
|
|
return CXCompletionChunk_SemiColon;
|
|
|
|
case CodeCompletionString::CK_Equal:
|
|
|
|
return CXCompletionChunk_Equal;
|
|
|
|
case CodeCompletionString::CK_HorizontalSpace:
|
|
|
|
return CXCompletionChunk_HorizontalSpace;
|
|
|
|
case CodeCompletionString::CK_VerticalSpace:
|
|
|
|
return CXCompletionChunk_VerticalSpace;
|
2010-01-06 03:32:54 +08:00
|
|
|
}
|
|
|
|
|
2012-01-17 14:56:22 +08:00
|
|
|
llvm_unreachable("Invalid CompletionKind!");
|
2010-01-06 03:32:54 +08:00
|
|
|
}
|
|
|
|
|
2010-02-17 09:42:24 +08:00
|
|
|
CXString clang_getCompletionChunkText(CXCompletionString completion_string,
|
|
|
|
unsigned chunk_number) {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
2010-01-06 03:32:54 +08:00
|
|
|
if (!CCStr || chunk_number >= CCStr->size())
|
2013-02-01 22:13:32 +08:00
|
|
|
return cxstring::createNull();
|
2010-01-06 03:32:54 +08:00
|
|
|
|
|
|
|
switch ((*CCStr)[chunk_number].Kind) {
|
|
|
|
case CodeCompletionString::CK_TypedText:
|
|
|
|
case CodeCompletionString::CK_Text:
|
|
|
|
case CodeCompletionString::CK_Placeholder:
|
|
|
|
case CodeCompletionString::CK_CurrentParameter:
|
|
|
|
case CodeCompletionString::CK_Informative:
|
|
|
|
case CodeCompletionString::CK_LeftParen:
|
|
|
|
case CodeCompletionString::CK_RightParen:
|
|
|
|
case CodeCompletionString::CK_LeftBracket:
|
|
|
|
case CodeCompletionString::CK_RightBracket:
|
|
|
|
case CodeCompletionString::CK_LeftBrace:
|
|
|
|
case CodeCompletionString::CK_RightBrace:
|
|
|
|
case CodeCompletionString::CK_LeftAngle:
|
|
|
|
case CodeCompletionString::CK_RightAngle:
|
|
|
|
case CodeCompletionString::CK_Comma:
|
|
|
|
case CodeCompletionString::CK_ResultType:
|
Improve code completion by introducing patterns for the various C and
C++ grammatical constructs that show up in top-level (namespace-level)
declarations, member declarations, template declarations, statements,
expressions, conditions, etc. For example, we now provide a pattern
for
static_cast<type>(expr)
when we can have an expression, or
using namespace identifier;
when we can have a using directive.
Also, improves the results of code completion at the beginning of a
top-level declaration. Previously, we would see value names (function
names, global variables, etc.); now we see types, namespace names,
etc., but no values.
llvm-svn: 93134
2010-01-11 07:08:15 +08:00
|
|
|
case CodeCompletionString::CK_Colon:
|
|
|
|
case CodeCompletionString::CK_SemiColon:
|
|
|
|
case CodeCompletionString::CK_Equal:
|
|
|
|
case CodeCompletionString::CK_HorizontalSpace:
|
2010-05-25 14:14:46 +08:00
|
|
|
case CodeCompletionString::CK_VerticalSpace:
|
2013-02-02 08:02:12 +08:00
|
|
|
return cxstring::createRef((*CCStr)[chunk_number].Text);
|
2010-05-25 14:14:46 +08:00
|
|
|
|
2010-01-06 03:32:54 +08:00
|
|
|
case CodeCompletionString::CK_Optional:
|
|
|
|
// Note: treated as an empty text block.
|
2013-02-01 22:21:22 +08:00
|
|
|
return cxstring::createEmpty();
|
2010-01-06 03:32:54 +08:00
|
|
|
}
|
|
|
|
|
2012-01-21 05:50:17 +08:00
|
|
|
llvm_unreachable("Invalid CodeCompletionString Kind!");
|
2010-01-06 03:32:54 +08:00
|
|
|
}
|
|
|
|
|
2010-02-17 09:42:24 +08:00
|
|
|
|
2010-01-06 03:32:54 +08:00
|
|
|
CXCompletionString
|
|
|
|
clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
|
|
|
|
unsigned chunk_number) {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
2010-01-06 03:32:54 +08:00
|
|
|
if (!CCStr || chunk_number >= CCStr->size())
|
2014-06-08 16:38:04 +08:00
|
|
|
return nullptr;
|
2010-01-06 03:32:54 +08:00
|
|
|
|
|
|
|
switch ((*CCStr)[chunk_number].Kind) {
|
|
|
|
case CodeCompletionString::CK_TypedText:
|
|
|
|
case CodeCompletionString::CK_Text:
|
|
|
|
case CodeCompletionString::CK_Placeholder:
|
|
|
|
case CodeCompletionString::CK_CurrentParameter:
|
|
|
|
case CodeCompletionString::CK_Informative:
|
|
|
|
case CodeCompletionString::CK_LeftParen:
|
|
|
|
case CodeCompletionString::CK_RightParen:
|
|
|
|
case CodeCompletionString::CK_LeftBracket:
|
|
|
|
case CodeCompletionString::CK_RightBracket:
|
|
|
|
case CodeCompletionString::CK_LeftBrace:
|
|
|
|
case CodeCompletionString::CK_RightBrace:
|
|
|
|
case CodeCompletionString::CK_LeftAngle:
|
|
|
|
case CodeCompletionString::CK_RightAngle:
|
|
|
|
case CodeCompletionString::CK_Comma:
|
|
|
|
case CodeCompletionString::CK_ResultType:
|
Improve code completion by introducing patterns for the various C and
C++ grammatical constructs that show up in top-level (namespace-level)
declarations, member declarations, template declarations, statements,
expressions, conditions, etc. For example, we now provide a pattern
for
static_cast<type>(expr)
when we can have an expression, or
using namespace identifier;
when we can have a using directive.
Also, improves the results of code completion at the beginning of a
top-level declaration. Previously, we would see value names (function
names, global variables, etc.); now we see types, namespace names,
etc., but no values.
llvm-svn: 93134
2010-01-11 07:08:15 +08:00
|
|
|
case CodeCompletionString::CK_Colon:
|
|
|
|
case CodeCompletionString::CK_SemiColon:
|
|
|
|
case CodeCompletionString::CK_Equal:
|
|
|
|
case CodeCompletionString::CK_HorizontalSpace:
|
|
|
|
case CodeCompletionString::CK_VerticalSpace:
|
2014-06-08 16:38:04 +08:00
|
|
|
return nullptr;
|
2010-01-06 03:32:54 +08:00
|
|
|
|
|
|
|
case CodeCompletionString::CK_Optional:
|
|
|
|
// Note: treated as an empty text block.
|
|
|
|
return (*CCStr)[chunk_number].Optional;
|
|
|
|
}
|
|
|
|
|
2012-01-17 14:56:22 +08:00
|
|
|
llvm_unreachable("Invalid CompletionKind!");
|
2010-01-06 03:32:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
2010-01-06 03:32:54 +08:00
|
|
|
return CCStr? CCStr->size() : 0;
|
|
|
|
}
|
|
|
|
|
2010-05-27 06:00:08 +08:00
|
|
|
unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
2010-05-28 02:35:05 +08:00
|
|
|
return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
|
2010-05-27 06:00:08 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 07:00:57 +08:00
|
|
|
enum CXAvailabilityKind
|
|
|
|
clang_getCompletionAvailability(CXCompletionString completion_string) {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
|
|
|
return CCStr? static_cast<CXAvailabilityKind>(CCStr->getAvailability())
|
|
|
|
: CXAvailability_Available;
|
2010-08-24 07:00:57 +08:00
|
|
|
}
|
|
|
|
|
2011-10-14 23:31:08 +08:00
|
|
|
unsigned clang_getCompletionNumAnnotations(CXCompletionString completion_string)
|
|
|
|
{
|
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
|
|
|
return CCStr ? CCStr->getAnnotationCount() : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
CXString clang_getCompletionAnnotation(CXCompletionString completion_string,
|
|
|
|
unsigned annotation_number) {
|
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
2013-02-02 08:02:12 +08:00
|
|
|
return CCStr ? cxstring::createRef(CCStr->getAnnotation(annotation_number))
|
2013-02-01 22:13:32 +08:00
|
|
|
: cxstring::createNull();
|
2011-10-14 23:31:08 +08:00
|
|
|
}
|
|
|
|
|
2012-03-28 07:34:16 +08:00
|
|
|
CXString
|
|
|
|
clang_getCompletionParent(CXCompletionString completion_string,
|
|
|
|
CXCursorKind *kind) {
|
|
|
|
if (kind)
|
|
|
|
*kind = CXCursor_NotImplemented;
|
|
|
|
|
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
|
|
|
if (!CCStr)
|
2013-02-01 22:13:32 +08:00
|
|
|
return cxstring::createNull();
|
2012-03-28 07:34:16 +08:00
|
|
|
|
2013-02-02 10:19:29 +08:00
|
|
|
return cxstring::createRef(CCStr->getParentContextName());
|
2012-03-28 07:34:16 +08:00
|
|
|
}
|
2012-07-03 01:35:10 +08:00
|
|
|
|
|
|
|
CXString
|
|
|
|
clang_getCompletionBriefComment(CXCompletionString completion_string) {
|
|
|
|
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
|
|
|
|
|
|
|
if (!CCStr)
|
2013-02-01 22:13:32 +08:00
|
|
|
return cxstring::createNull();
|
2012-07-03 01:35:10 +08:00
|
|
|
|
2013-02-02 08:02:12 +08:00
|
|
|
return cxstring::createRef(CCStr->getBriefComment());
|
2012-07-03 01:35:10 +08:00
|
|
|
}
|
|
|
|
|
2012-11-22 23:02:44 +08:00
|
|
|
namespace {
|
|
|
|
|
2010-01-06 03:32:54 +08:00
|
|
|
/// \brief The CXCodeCompleteResults structure we allocate internally;
|
|
|
|
/// the client only sees the initial CXCodeCompleteResults structure.
|
2013-02-08 03:09:22 +08:00
|
|
|
///
|
|
|
|
/// Normally, clients of CXString shouldn't care whether or not a CXString is
|
|
|
|
/// managed by a pool or by explicitly malloc'ed memory. But
|
|
|
|
/// AllocatedCXCodeCompleteResults outlives the CXTranslationUnit, so we can
|
|
|
|
/// not rely on the StringPool in the TU.
|
2010-01-06 03:32:54 +08:00
|
|
|
struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
|
2014-04-16 02:16:25 +08:00
|
|
|
AllocatedCXCodeCompleteResults(IntrusiveRefCntPtr<FileManager> FileMgr);
|
2010-02-19 07:07:20 +08:00
|
|
|
~AllocatedCXCodeCompleteResults();
|
|
|
|
|
2010-02-19 02:08:43 +08:00
|
|
|
/// \brief Diagnostics produced while performing code completion.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<StoredDiagnostic, 8> Diagnostics;
|
2010-02-19 02:08:43 +08:00
|
|
|
|
2014-05-10 06:33:11 +08:00
|
|
|
/// \brief Allocated API-exposed wrappters for Diagnostics.
|
|
|
|
SmallVector<CXStoredDiagnostic *, 8> DiagnosticsWrappers;
|
|
|
|
|
2012-10-24 06:26:28 +08:00
|
|
|
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
|
|
|
|
|
2010-03-16 08:06:06 +08:00
|
|
|
/// \brief Diag object
|
2012-02-20 22:00:23 +08:00
|
|
|
IntrusiveRefCntPtr<DiagnosticsEngine> Diag;
|
2010-03-16 08:06:06 +08:00
|
|
|
|
2010-02-19 02:08:43 +08:00
|
|
|
/// \brief Language options used to adjust source locations.
|
2010-01-31 07:31:40 +08:00
|
|
|
LangOptions LangOpts;
|
2010-11-04 06:45:23 +08:00
|
|
|
|
2010-11-23 16:35:12 +08:00
|
|
|
/// \brief File manager, used for diagnostics.
|
2012-02-20 22:00:23 +08:00
|
|
|
IntrusiveRefCntPtr<FileManager> FileMgr;
|
2010-11-23 16:35:12 +08:00
|
|
|
|
2010-11-04 06:45:23 +08:00
|
|
|
/// \brief Source manager, used for diagnostics.
|
2012-02-20 22:00:23 +08:00
|
|
|
IntrusiveRefCntPtr<SourceManager> SourceMgr;
|
2010-02-19 07:35:40 +08:00
|
|
|
|
|
|
|
/// \brief Temporary files that should be removed once we have finished
|
|
|
|
/// with the code-completion results.
|
2013-06-26 20:54:23 +08:00
|
|
|
std::vector<std::string> TemporaryFiles;
|
2010-08-05 01:07:00 +08:00
|
|
|
|
2010-11-23 15:51:02 +08:00
|
|
|
/// \brief Temporary buffers that will be deleted once we have finished with
|
|
|
|
/// the code-completion results.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<const llvm::MemoryBuffer *, 1> TemporaryBuffers;
|
2011-02-02 03:23:04 +08:00
|
|
|
|
2011-02-17 03:08:06 +08:00
|
|
|
/// \brief Allocator used to store globally cached code-completion results.
|
2017-01-07 01:47:10 +08:00
|
|
|
IntrusiveRefCntPtr<clang::GlobalCodeCompletionAllocator>
|
|
|
|
CachedCompletionAllocator;
|
|
|
|
|
2011-02-02 03:23:04 +08:00
|
|
|
/// \brief Allocator used to store code completion results.
|
2017-01-07 01:47:10 +08:00
|
|
|
IntrusiveRefCntPtr<clang::GlobalCodeCompletionAllocator>
|
|
|
|
CodeCompletionAllocator;
|
|
|
|
|
2011-07-08 00:03:39 +08:00
|
|
|
/// \brief Context under which completion occurred.
|
|
|
|
enum clang::CodeCompletionContext::Kind ContextKind;
|
|
|
|
|
|
|
|
/// \brief A bitfield representing the acceptable completions for the
|
|
|
|
/// current context.
|
|
|
|
unsigned long long Contexts;
|
2011-07-21 09:05:26 +08:00
|
|
|
|
2011-07-26 23:24:30 +08:00
|
|
|
/// \brief The kind of the container for the current context for completions.
|
2011-07-21 09:05:26 +08:00
|
|
|
enum CXCursorKind ContainerKind;
|
2013-02-08 03:09:22 +08:00
|
|
|
|
2011-07-26 23:24:30 +08:00
|
|
|
/// \brief The USR of the container for the current context for completions.
|
2013-02-08 03:09:22 +08:00
|
|
|
std::string ContainerUSR;
|
|
|
|
|
2011-07-26 23:24:30 +08:00
|
|
|
/// \brief a boolean value indicating whether there is complete information
|
|
|
|
/// about the container
|
2011-07-21 09:05:26 +08:00
|
|
|
unsigned ContainerIsIncomplete;
|
2011-07-26 23:24:30 +08:00
|
|
|
|
|
|
|
/// \brief A string containing the Objective-C selector entered thus far for a
|
|
|
|
/// message send.
|
|
|
|
std::string Selector;
|
2010-01-06 03:32:54 +08:00
|
|
|
};
|
|
|
|
|
2012-11-22 23:02:44 +08:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
2010-11-17 08:13:31 +08:00
|
|
|
/// \brief Tracks the number of code-completion result objects that are
|
|
|
|
/// currently active.
|
|
|
|
///
|
|
|
|
/// Used for debugging purposes only.
|
2014-03-03 01:08:31 +08:00
|
|
|
static std::atomic<unsigned> CodeCompletionResultObjects;
|
2017-01-07 01:47:10 +08:00
|
|
|
|
2011-03-19 02:22:40 +08:00
|
|
|
AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(
|
2014-04-16 02:16:25 +08:00
|
|
|
IntrusiveRefCntPtr<FileManager> FileMgr)
|
2017-01-07 01:47:10 +08:00
|
|
|
: CXCodeCompleteResults(),
|
|
|
|
DiagOpts(new DiagnosticOptions),
|
2014-04-16 02:16:25 +08:00
|
|
|
Diag(new DiagnosticsEngine(
|
|
|
|
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs), &*DiagOpts)),
|
|
|
|
FileMgr(FileMgr), SourceMgr(new SourceManager(*Diag, *FileMgr)),
|
2017-01-07 01:47:10 +08:00
|
|
|
CodeCompletionAllocator(new clang::GlobalCodeCompletionAllocator),
|
2014-04-16 02:16:25 +08:00
|
|
|
Contexts(CXCompletionContext_Unknown),
|
|
|
|
ContainerKind(CXCursor_InvalidCode), ContainerIsIncomplete(1) {
|
2014-03-03 01:08:31 +08:00
|
|
|
if (getenv("LIBCLANG_OBJTRACKING"))
|
|
|
|
fprintf(stderr, "+++ %u completion results\n",
|
|
|
|
++CodeCompletionResultObjects);
|
2010-11-17 08:13:31 +08:00
|
|
|
}
|
2010-02-19 07:07:20 +08:00
|
|
|
|
|
|
|
AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
|
2014-05-10 06:33:11 +08:00
|
|
|
llvm::DeleteContainerPointers(DiagnosticsWrappers);
|
2010-02-19 07:07:20 +08:00
|
|
|
delete [] Results;
|
2013-02-08 03:09:22 +08:00
|
|
|
|
2010-02-19 07:35:40 +08:00
|
|
|
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
|
2013-06-26 20:54:23 +08:00
|
|
|
llvm::sys::fs::remove(TemporaryFiles[I]);
|
2010-08-05 01:07:00 +08:00
|
|
|
for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I)
|
|
|
|
delete TemporaryBuffers[I];
|
2010-11-17 08:13:31 +08:00
|
|
|
|
2014-03-03 01:08:31 +08:00
|
|
|
if (getenv("LIBCLANG_OBJTRACKING"))
|
|
|
|
fprintf(stderr, "--- %u completion results\n",
|
|
|
|
--CodeCompletionResultObjects);
|
2010-02-19 07:07:20 +08:00
|
|
|
}
|
2010-08-05 00:47:14 +08:00
|
|
|
|
2011-07-08 00:03:39 +08:00
|
|
|
static unsigned long long getContextsForContextKind(
|
|
|
|
enum CodeCompletionContext::Kind kind,
|
|
|
|
Sema &S) {
|
|
|
|
unsigned long long contexts = 0;
|
|
|
|
switch (kind) {
|
|
|
|
case CodeCompletionContext::CCC_OtherWithMacros: {
|
|
|
|
//We can allow macros here, but we don't know what else is permissible
|
|
|
|
//So we'll say the only thing permissible are macros
|
|
|
|
contexts = CXCompletionContext_MacroName;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_TopLevel:
|
|
|
|
case CodeCompletionContext::CCC_ObjCIvarList:
|
|
|
|
case CodeCompletionContext::CCC_ClassStructUnion:
|
|
|
|
case CodeCompletionContext::CCC_Type: {
|
|
|
|
contexts = CXCompletionContext_AnyType |
|
|
|
|
CXCompletionContext_ObjCInterface;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (S.getLangOpts().CPlusPlus) {
|
2011-07-08 00:03:39 +08:00
|
|
|
contexts |= CXCompletionContext_EnumTag |
|
|
|
|
CXCompletionContext_UnionTag |
|
|
|
|
CXCompletionContext_StructTag |
|
|
|
|
CXCompletionContext_ClassTag |
|
|
|
|
CXCompletionContext_NestedNameSpecifier;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_Statement: {
|
|
|
|
contexts = CXCompletionContext_AnyType |
|
|
|
|
CXCompletionContext_ObjCInterface |
|
|
|
|
CXCompletionContext_AnyValue;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (S.getLangOpts().CPlusPlus) {
|
2011-07-08 00:03:39 +08:00
|
|
|
contexts |= CXCompletionContext_EnumTag |
|
|
|
|
CXCompletionContext_UnionTag |
|
|
|
|
CXCompletionContext_StructTag |
|
|
|
|
CXCompletionContext_ClassTag |
|
|
|
|
CXCompletionContext_NestedNameSpecifier;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_Expression: {
|
|
|
|
contexts = CXCompletionContext_AnyValue;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (S.getLangOpts().CPlusPlus) {
|
2011-07-08 00:03:39 +08:00
|
|
|
contexts |= CXCompletionContext_AnyType |
|
|
|
|
CXCompletionContext_ObjCInterface |
|
|
|
|
CXCompletionContext_EnumTag |
|
|
|
|
CXCompletionContext_UnionTag |
|
|
|
|
CXCompletionContext_StructTag |
|
|
|
|
CXCompletionContext_ClassTag |
|
|
|
|
CXCompletionContext_NestedNameSpecifier;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ObjCMessageReceiver: {
|
|
|
|
contexts = CXCompletionContext_ObjCObjectValue |
|
|
|
|
CXCompletionContext_ObjCSelectorValue |
|
|
|
|
CXCompletionContext_ObjCInterface;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (S.getLangOpts().CPlusPlus) {
|
2011-07-08 00:03:39 +08:00
|
|
|
contexts |= CXCompletionContext_CXXClassTypeValue |
|
|
|
|
CXCompletionContext_AnyType |
|
|
|
|
CXCompletionContext_EnumTag |
|
|
|
|
CXCompletionContext_UnionTag |
|
|
|
|
CXCompletionContext_StructTag |
|
|
|
|
CXCompletionContext_ClassTag |
|
|
|
|
CXCompletionContext_NestedNameSpecifier;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_DotMemberAccess: {
|
|
|
|
contexts = CXCompletionContext_DotMemberAccess;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ArrowMemberAccess: {
|
|
|
|
contexts = CXCompletionContext_ArrowMemberAccess;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ObjCPropertyAccess: {
|
|
|
|
contexts = CXCompletionContext_ObjCPropertyAccess;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_EnumTag: {
|
|
|
|
contexts = CXCompletionContext_EnumTag |
|
|
|
|
CXCompletionContext_NestedNameSpecifier;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_UnionTag: {
|
|
|
|
contexts = CXCompletionContext_UnionTag |
|
|
|
|
CXCompletionContext_NestedNameSpecifier;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ClassOrStructTag: {
|
|
|
|
contexts = CXCompletionContext_StructTag |
|
|
|
|
CXCompletionContext_ClassTag |
|
|
|
|
CXCompletionContext_NestedNameSpecifier;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ObjCProtocolName: {
|
|
|
|
contexts = CXCompletionContext_ObjCProtocol;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_Namespace: {
|
|
|
|
contexts = CXCompletionContext_Namespace;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_PotentiallyQualifiedName: {
|
|
|
|
contexts = CXCompletionContext_NestedNameSpecifier;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_MacroNameUse: {
|
|
|
|
contexts = CXCompletionContext_MacroName;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_NaturalLanguage: {
|
|
|
|
contexts = CXCompletionContext_NaturalLanguage;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_SelectorName: {
|
|
|
|
contexts = CXCompletionContext_ObjCSelectorName;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ParenthesizedExpression: {
|
|
|
|
contexts = CXCompletionContext_AnyType |
|
|
|
|
CXCompletionContext_ObjCInterface |
|
|
|
|
CXCompletionContext_AnyValue;
|
2012-03-11 15:00:24 +08:00
|
|
|
if (S.getLangOpts().CPlusPlus) {
|
2011-07-08 00:03:39 +08:00
|
|
|
contexts |= CXCompletionContext_EnumTag |
|
|
|
|
CXCompletionContext_UnionTag |
|
|
|
|
CXCompletionContext_StructTag |
|
|
|
|
CXCompletionContext_ClassTag |
|
|
|
|
CXCompletionContext_NestedNameSpecifier;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ObjCInstanceMessage: {
|
|
|
|
contexts = CXCompletionContext_ObjCInstanceMessage;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ObjCClassMessage: {
|
|
|
|
contexts = CXCompletionContext_ObjCClassMessage;
|
|
|
|
break;
|
|
|
|
}
|
2011-07-30 14:55:39 +08:00
|
|
|
case CodeCompletionContext::CCC_ObjCInterfaceName: {
|
2011-07-08 00:03:39 +08:00
|
|
|
contexts = CXCompletionContext_ObjCInterface;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_ObjCCategoryName: {
|
|
|
|
contexts = CXCompletionContext_ObjCCategory;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_Other:
|
|
|
|
case CodeCompletionContext::CCC_ObjCInterface:
|
|
|
|
case CodeCompletionContext::CCC_ObjCImplementation:
|
|
|
|
case CodeCompletionContext::CCC_Name:
|
|
|
|
case CodeCompletionContext::CCC_MacroName:
|
|
|
|
case CodeCompletionContext::CCC_PreprocessorExpression:
|
|
|
|
case CodeCompletionContext::CCC_PreprocessorDirective:
|
|
|
|
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)
|
|
|
|
contexts = CXCompletionContext_Unexposed;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case CodeCompletionContext::CCC_Recovery: {
|
|
|
|
//We don't know what the current context is, so we'll return unknown
|
|
|
|
//This is the equivalent of setting all of the other context bits
|
|
|
|
contexts = CXCompletionContext_Unknown;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return contexts;
|
|
|
|
}
|
|
|
|
|
2010-08-05 00:47:14 +08:00
|
|
|
namespace {
|
|
|
|
class CaptureCompletionResults : public CodeCompleteConsumer {
|
|
|
|
AllocatedCXCodeCompleteResults &AllocatedResults;
|
2012-04-11 01:23:48 +08:00
|
|
|
CodeCompletionTUInfo CCTUInfo;
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<CXCompletionResult, 16> StoredResults;
|
2011-07-21 09:05:26 +08:00
|
|
|
CXTranslationUnit *TU;
|
2010-08-05 00:47:14 +08:00
|
|
|
public:
|
2012-07-03 01:35:10 +08:00
|
|
|
CaptureCompletionResults(const CodeCompleteOptions &Opts,
|
|
|
|
AllocatedCXCodeCompleteResults &Results,
|
2011-07-21 09:05:26 +08:00
|
|
|
CXTranslationUnit *TranslationUnit)
|
2012-07-03 01:35:10 +08:00
|
|
|
: CodeCompleteConsumer(Opts, false),
|
2012-04-11 01:23:48 +08:00
|
|
|
AllocatedResults(Results), CCTUInfo(Results.CodeCompletionAllocator),
|
|
|
|
TU(TranslationUnit) { }
|
2015-04-11 10:00:23 +08:00
|
|
|
~CaptureCompletionResults() override { Finish(); }
|
2014-03-15 15:47:46 +08:00
|
|
|
|
|
|
|
void ProcessCodeCompleteResults(Sema &S,
|
|
|
|
CodeCompletionContext Context,
|
|
|
|
CodeCompletionResult *Results,
|
|
|
|
unsigned NumResults) override {
|
2010-10-12 05:37:58 +08:00
|
|
|
StoredResults.reserve(StoredResults.size() + NumResults);
|
2010-08-05 00:47:14 +08:00
|
|
|
for (unsigned I = 0; I != NumResults; ++I) {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *StoredCompletion
|
2015-07-07 14:20:19 +08:00
|
|
|
= Results[I].CreateCodeCompletionString(S, Context, getAllocator(),
|
2012-07-03 01:35:10 +08:00
|
|
|
getCodeCompletionTUInfo(),
|
|
|
|
includeBriefComments());
|
2010-10-12 05:37:58 +08:00
|
|
|
|
|
|
|
CXCompletionResult R;
|
|
|
|
R.CursorKind = Results[I].CursorKind;
|
|
|
|
R.CompletionString = StoredCompletion;
|
|
|
|
StoredResults.push_back(R);
|
2010-08-05 00:47:14 +08:00
|
|
|
}
|
2011-07-08 00:03:39 +08:00
|
|
|
|
2011-07-21 09:05:26 +08:00
|
|
|
enum CodeCompletionContext::Kind contextKind = Context.getKind();
|
|
|
|
|
|
|
|
AllocatedResults.ContextKind = contextKind;
|
|
|
|
AllocatedResults.Contexts = getContextsForContextKind(contextKind, S);
|
|
|
|
|
2011-07-26 23:24:30 +08:00
|
|
|
AllocatedResults.Selector = "";
|
2013-06-18 12:41:50 +08:00
|
|
|
ArrayRef<IdentifierInfo *> SelIdents = Context.getSelIdents();
|
|
|
|
for (ArrayRef<IdentifierInfo *>::iterator I = SelIdents.begin(),
|
|
|
|
E = SelIdents.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (IdentifierInfo *selIdent = *I)
|
|
|
|
AllocatedResults.Selector += selIdent->getName();
|
2013-06-18 12:02:26 +08:00
|
|
|
AllocatedResults.Selector += ":";
|
2011-07-26 23:24:30 +08:00
|
|
|
}
|
|
|
|
|
2011-07-21 09:05:26 +08:00
|
|
|
QualType baseType = Context.getBaseType();
|
2014-06-08 16:38:04 +08:00
|
|
|
NamedDecl *D = nullptr;
|
|
|
|
|
2011-07-21 09:05:26 +08:00
|
|
|
if (!baseType.isNull()) {
|
|
|
|
// Get the declaration for a class/struct/union/enum type
|
|
|
|
if (const TagType *Tag = baseType->getAs<TagType>())
|
|
|
|
D = Tag->getDecl();
|
|
|
|
// Get the @interface declaration for a (possibly-qualified) Objective-C
|
|
|
|
// object pointer type, e.g., NSString*
|
|
|
|
else if (const ObjCObjectPointerType *ObjPtr =
|
|
|
|
baseType->getAs<ObjCObjectPointerType>())
|
|
|
|
D = ObjPtr->getInterfaceDecl();
|
|
|
|
// Get the @interface declaration for an Objective-C object type
|
|
|
|
else if (const ObjCObjectType *Obj = baseType->getAs<ObjCObjectType>())
|
|
|
|
D = Obj->getInterface();
|
|
|
|
// Get the class for a C++ injected-class-name
|
|
|
|
else if (const InjectedClassNameType *Injected =
|
|
|
|
baseType->getAs<InjectedClassNameType>())
|
|
|
|
D = Injected->getDecl();
|
|
|
|
}
|
2014-06-08 16:38:04 +08:00
|
|
|
|
|
|
|
if (D != nullptr) {
|
2011-07-21 09:05:26 +08:00
|
|
|
CXCursor cursor = cxcursor::MakeCXCursor(D, *TU);
|
2013-02-08 03:09:22 +08:00
|
|
|
|
|
|
|
AllocatedResults.ContainerKind = clang_getCursorKind(cursor);
|
|
|
|
|
|
|
|
CXString CursorUSR = clang_getCursorUSR(cursor);
|
|
|
|
AllocatedResults.ContainerUSR = clang_getCString(CursorUSR);
|
|
|
|
clang_disposeString(CursorUSR);
|
|
|
|
|
2011-07-21 09:05:26 +08:00
|
|
|
const Type *type = baseType.getTypePtrOrNull();
|
2014-06-08 16:38:04 +08:00
|
|
|
if (type) {
|
2011-07-21 09:05:26 +08:00
|
|
|
AllocatedResults.ContainerIsIncomplete = type->isIncompleteType();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
AllocatedResults.ContainerIsIncomplete = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
AllocatedResults.ContainerKind = CXCursor_InvalidCode;
|
2013-02-08 03:09:22 +08:00
|
|
|
AllocatedResults.ContainerUSR.clear();
|
2011-07-21 09:05:26 +08:00
|
|
|
AllocatedResults.ContainerIsIncomplete = 1;
|
|
|
|
}
|
2010-08-05 00:47:14 +08:00
|
|
|
}
|
2014-03-15 15:47:46 +08:00
|
|
|
|
|
|
|
void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
|
|
|
OverloadCandidate *Candidates,
|
|
|
|
unsigned NumCandidates) override {
|
2010-10-12 05:37:58 +08:00
|
|
|
StoredResults.reserve(StoredResults.size() + NumCandidates);
|
|
|
|
for (unsigned I = 0; I != NumCandidates; ++I) {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *StoredCompletion
|
2012-04-11 01:23:48 +08:00
|
|
|
= Candidates[I].CreateSignatureString(CurrentArg, S, getAllocator(),
|
2015-01-28 22:17:22 +08:00
|
|
|
getCodeCompletionTUInfo(),
|
|
|
|
includeBriefComments());
|
2010-10-12 05:37:58 +08:00
|
|
|
|
|
|
|
CXCompletionResult R;
|
2015-01-22 00:24:11 +08:00
|
|
|
R.CursorKind = CXCursor_OverloadCandidate;
|
2010-10-12 05:37:58 +08:00
|
|
|
R.CompletionString = StoredCompletion;
|
|
|
|
StoredResults.push_back(R);
|
|
|
|
}
|
|
|
|
}
|
2014-03-15 15:47:46 +08:00
|
|
|
|
|
|
|
CodeCompletionAllocator &getAllocator() override {
|
2012-04-11 01:23:48 +08:00
|
|
|
return *AllocatedResults.CodeCompletionAllocator;
|
2011-02-02 03:23:04 +08:00
|
|
|
}
|
2012-04-11 01:23:48 +08:00
|
|
|
|
2014-03-15 15:47:46 +08:00
|
|
|
CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo;}
|
|
|
|
|
2010-10-12 05:37:58 +08:00
|
|
|
private:
|
|
|
|
void Finish() {
|
|
|
|
AllocatedResults.Results = new CXCompletionResult [StoredResults.size()];
|
|
|
|
AllocatedResults.NumResults = StoredResults.size();
|
|
|
|
std::memcpy(AllocatedResults.Results, StoredResults.data(),
|
|
|
|
StoredResults.size() * sizeof(CXCompletionResult));
|
|
|
|
StoredResults.clear();
|
|
|
|
}
|
2010-08-05 00:47:14 +08:00
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2010-08-05 00:47:14 +08:00
|
|
|
|
2015-07-26 04:55:44 +08:00
|
|
|
static CXCodeCompleteResults *
|
|
|
|
clang_codeCompleteAt_Impl(CXTranslationUnit TU, const char *complete_filename,
|
|
|
|
unsigned complete_line, unsigned complete_column,
|
|
|
|
ArrayRef<CXUnsavedFile> unsaved_files,
|
|
|
|
unsigned options) {
|
2012-07-03 01:35:10 +08:00
|
|
|
bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
|
2010-08-20 07:44:10 +08:00
|
|
|
|
2010-08-05 00:47:14 +08:00
|
|
|
#ifdef UDP_CODE_COMPLETION_LOGGER
|
|
|
|
#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
|
|
|
|
const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2014-06-08 16:38:04 +08:00
|
|
|
bool EnableLogging = getenv("LIBCLANG_CODE_COMPLETION_LOGGING") != nullptr;
|
2014-02-11 22:34:14 +08:00
|
|
|
|
2014-02-11 23:02:48 +08:00
|
|
|
if (cxtu::isNotUsableTU(TU)) {
|
2014-02-11 22:34:14 +08:00
|
|
|
LOG_BAD_TU(TU);
|
2015-07-26 04:55:44 +08:00
|
|
|
return nullptr;
|
2014-02-11 22:34:14 +08:00
|
|
|
}
|
|
|
|
|
2013-01-27 02:53:38 +08:00
|
|
|
ASTUnit *AST = cxtu::getASTUnit(TU);
|
2010-08-05 00:47:14 +08:00
|
|
|
if (!AST)
|
2015-07-26 04:55:44 +08:00
|
|
|
return nullptr;
|
2010-08-05 00:47:14 +08:00
|
|
|
|
2013-01-27 05:49:50 +08:00
|
|
|
CIndexer *CXXIdx = TU->CIdx;
|
2012-03-28 10:18:05 +08:00
|
|
|
if (CXXIdx->isOptEnabled(CXGlobalOpt_ThreadBackgroundPriorityForEditing))
|
2012-03-28 10:49:54 +08:00
|
|
|
setThreadBackgroundPriority();
|
2012-03-28 10:18:05 +08:00
|
|
|
|
2010-09-24 02:47:53 +08:00
|
|
|
ASTUnit::ConcurrencyCheck Check(*AST);
|
|
|
|
|
2010-08-05 00:47:14 +08:00
|
|
|
// Perform the remapping of source files.
|
2011-07-23 18:55:15 +08:00
|
|
|
SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
|
2014-07-07 09:23:14 +08:00
|
|
|
|
2015-07-26 04:55:44 +08:00
|
|
|
for (auto &UF : unsaved_files) {
|
2014-08-28 04:03:29 +08:00
|
|
|
std::unique_ptr<llvm::MemoryBuffer> MB =
|
2014-07-07 09:23:14 +08:00
|
|
|
llvm::MemoryBuffer::getMemBufferCopy(getContents(UF), UF.Filename);
|
2014-08-28 04:03:29 +08:00
|
|
|
RemappedFiles.push_back(std::make_pair(UF.Filename, MB.release()));
|
2010-08-05 00:47:14 +08:00
|
|
|
}
|
2014-07-07 09:23:14 +08:00
|
|
|
|
2010-08-05 00:47:14 +08:00
|
|
|
if (EnableLogging) {
|
|
|
|
// FIXME: Add logging.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the resulting source file to find code-completion results.
|
2014-04-16 02:16:25 +08:00
|
|
|
AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults(
|
|
|
|
&AST->getFileManager());
|
2014-06-08 16:38:04 +08:00
|
|
|
Results->Results = nullptr;
|
2010-08-05 00:47:14 +08:00
|
|
|
Results->NumResults = 0;
|
2011-02-17 03:08:06 +08:00
|
|
|
|
2010-08-05 00:47:14 +08:00
|
|
|
// Create a code-completion consumer to capture the results.
|
2012-07-03 01:35:10 +08:00
|
|
|
CodeCompleteOptions Opts;
|
|
|
|
Opts.IncludeBriefComments = IncludeBriefComments;
|
|
|
|
CaptureCompletionResults Capture(Opts, *Results, &TU);
|
2010-08-05 00:47:14 +08:00
|
|
|
|
|
|
|
// Perform completion.
|
|
|
|
AST->CodeComplete(complete_filename, complete_line, complete_column,
|
2015-06-21 02:53:08 +08:00
|
|
|
RemappedFiles, (options & CXCodeComplete_IncludeMacros),
|
2010-08-05 17:09:23 +08:00
|
|
|
(options & CXCodeComplete_IncludeCodePatterns),
|
2015-06-21 02:53:08 +08:00
|
|
|
IncludeBriefComments, Capture,
|
|
|
|
CXXIdx->getPCHContainerOperations(), *Results->Diag,
|
|
|
|
Results->LangOpts, *Results->SourceMgr, *Results->FileMgr,
|
|
|
|
Results->Diagnostics, Results->TemporaryBuffers);
|
2014-05-10 06:33:11 +08:00
|
|
|
|
|
|
|
Results->DiagnosticsWrappers.resize(Results->Diagnostics.size());
|
|
|
|
|
2011-02-17 03:08:06 +08:00
|
|
|
// Keep a reference to the allocator used for cached global completions, so
|
|
|
|
// that we can be sure that the memory used by our code completion strings
|
|
|
|
// doesn't get freed due to subsequent reparses (while the code completion
|
|
|
|
// results are still active).
|
|
|
|
Results->CachedCompletionAllocator = AST->getCachedCompletionAllocator();
|
2010-08-05 00:47:14 +08:00
|
|
|
|
|
|
|
|
2010-01-06 03:32:54 +08:00
|
|
|
|
2010-04-15 09:02:28 +08:00
|
|
|
#ifdef UDP_CODE_COMPLETION_LOGGER
|
|
|
|
#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
|
|
|
|
const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
|
2012-02-13 20:32:26 +08:00
|
|
|
SmallString<256> LogResult;
|
2010-04-15 09:02:28 +08:00
|
|
|
llvm::raw_svector_ostream os(LogResult);
|
|
|
|
|
|
|
|
// Figure out the language and whether or not it uses PCH.
|
|
|
|
const char *lang = 0;
|
|
|
|
bool usesPCH = false;
|
|
|
|
|
|
|
|
for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
|
|
|
|
I != E; ++I) {
|
|
|
|
if (*I == 0)
|
|
|
|
continue;
|
|
|
|
if (strcmp(*I, "-x") == 0) {
|
|
|
|
if (I + 1 != E) {
|
|
|
|
lang = *(++I);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (strcmp(*I, "-include") == 0) {
|
|
|
|
if (I+1 != E) {
|
|
|
|
const char *arg = *(++I);
|
2012-02-13 20:32:26 +08:00
|
|
|
SmallString<512> pchName;
|
2010-04-15 09:02:28 +08:00
|
|
|
{
|
|
|
|
llvm::raw_svector_ostream os(pchName);
|
|
|
|
os << arg << ".pth";
|
|
|
|
}
|
|
|
|
pchName.push_back('\0');
|
|
|
|
struct stat stat_results;
|
2011-07-26 23:24:30 +08:00
|
|
|
if (stat(pchName.str().c_str(), &stat_results) == 0)
|
2010-04-15 09:02:28 +08:00
|
|
|
usesPCH = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-17 08:21:42 +08:00
|
|
|
os << "{ ";
|
|
|
|
os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
|
|
|
|
os << ", \"numRes\": " << Results->NumResults;
|
|
|
|
os << ", \"diags\": " << Results->Diagnostics.size();
|
|
|
|
os << ", \"pch\": " << (usesPCH ? "true" : "false");
|
|
|
|
os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
|
2010-04-15 09:02:28 +08:00
|
|
|
const char *name = getlogin();
|
2010-04-17 08:21:42 +08:00
|
|
|
os << ", \"user\": \"" << (name ? name : "unknown") << '"';
|
|
|
|
os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
|
|
|
|
os << " }";
|
2010-04-15 09:02:28 +08:00
|
|
|
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef res = os.str();
|
2010-04-15 09:02:28 +08:00
|
|
|
if (res.size() > 0) {
|
|
|
|
do {
|
|
|
|
// Setup the UDP socket.
|
|
|
|
struct sockaddr_in servaddr;
|
|
|
|
bzero(&servaddr, sizeof(servaddr));
|
|
|
|
servaddr.sin_family = AF_INET;
|
|
|
|
servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
|
|
|
|
if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
|
|
|
|
&servaddr.sin_addr) <= 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
|
|
if (sockfd < 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
sendto(sockfd, res.data(), res.size(), 0,
|
|
|
|
(struct sockaddr *)&servaddr, sizeof(servaddr));
|
|
|
|
close(sockfd);
|
|
|
|
}
|
|
|
|
while (false);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
2015-07-26 04:55:44 +08:00
|
|
|
return Results;
|
2010-08-20 07:44:10 +08:00
|
|
|
}
|
2015-07-26 04:55:44 +08:00
|
|
|
|
2010-08-20 07:44:10 +08:00
|
|
|
CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
|
|
|
|
const char *complete_filename,
|
|
|
|
unsigned complete_line,
|
|
|
|
unsigned complete_column,
|
|
|
|
struct CXUnsavedFile *unsaved_files,
|
|
|
|
unsigned num_unsaved_files,
|
|
|
|
unsigned options) {
|
2013-01-11 02:54:52 +08:00
|
|
|
LOG_FUNC_SECTION {
|
|
|
|
*Log << TU << ' '
|
|
|
|
<< complete_filename << ':' << complete_line << ':' << complete_column;
|
|
|
|
}
|
|
|
|
|
2014-07-07 09:23:14 +08:00
|
|
|
if (num_unsaved_files && !unsaved_files)
|
|
|
|
return nullptr;
|
|
|
|
|
2015-07-26 04:55:44 +08:00
|
|
|
CXCodeCompleteResults *result;
|
|
|
|
auto CodeCompleteAtImpl = [=, &result]() {
|
|
|
|
result = clang_codeCompleteAt_Impl(
|
|
|
|
TU, complete_filename, complete_line, complete_column,
|
|
|
|
llvm::makeArrayRef(unsaved_files, num_unsaved_files), options);
|
|
|
|
};
|
2012-12-22 12:48:07 +08:00
|
|
|
|
|
|
|
if (getenv("LIBCLANG_NOTHREADS")) {
|
2015-07-26 04:55:44 +08:00
|
|
|
CodeCompleteAtImpl();
|
|
|
|
return result;
|
2012-12-22 12:48:07 +08:00
|
|
|
}
|
|
|
|
|
2010-08-20 07:44:10 +08:00
|
|
|
llvm::CrashRecoveryContext CRC;
|
|
|
|
|
2015-07-26 04:55:44 +08:00
|
|
|
if (!RunSafely(CRC, CodeCompleteAtImpl)) {
|
2010-08-20 07:44:10 +08:00
|
|
|
fprintf(stderr, "libclang: crash detected in code completion\n");
|
2013-01-27 02:53:38 +08:00
|
|
|
cxtu::getASTUnit(TU)->setUnsafeToFree(true);
|
2014-06-08 16:38:04 +08:00
|
|
|
return nullptr;
|
2011-05-06 04:27:22 +08:00
|
|
|
} else if (getenv("LIBCLANG_RESOURCE_USAGE"))
|
|
|
|
PrintLibclangResourceUsage(TU);
|
2010-08-20 07:44:10 +08:00
|
|
|
|
2015-07-26 04:55:44 +08:00
|
|
|
return result;
|
2010-01-06 03:32:54 +08:00
|
|
|
}
|
|
|
|
|
2010-08-05 17:09:23 +08:00
|
|
|
unsigned clang_defaultCodeCompleteOptions(void) {
|
|
|
|
return CXCodeComplete_IncludeMacros;
|
|
|
|
}
|
|
|
|
|
2010-01-06 03:32:54 +08:00
|
|
|
void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
|
|
|
|
if (!ResultsIn)
|
|
|
|
return;
|
|
|
|
|
|
|
|
AllocatedCXCodeCompleteResults *Results
|
|
|
|
= static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
|
|
|
|
delete Results;
|
|
|
|
}
|
2010-08-24 07:00:57 +08:00
|
|
|
|
2010-02-19 02:08:43 +08:00
|
|
|
unsigned
|
|
|
|
clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
|
|
|
|
AllocatedCXCodeCompleteResults *Results
|
|
|
|
= static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
|
|
|
|
if (!Results)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Results->Diagnostics.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
CXDiagnostic
|
|
|
|
clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
|
|
|
|
unsigned Index) {
|
|
|
|
AllocatedCXCodeCompleteResults *Results
|
|
|
|
= static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
|
|
|
|
if (!Results || Index >= Results->Diagnostics.size())
|
2014-06-08 16:38:04 +08:00
|
|
|
return nullptr;
|
2010-02-19 02:08:43 +08:00
|
|
|
|
2014-05-10 06:33:11 +08:00
|
|
|
CXStoredDiagnostic *Diag = Results->DiagnosticsWrappers[Index];
|
|
|
|
if (!Diag)
|
|
|
|
Results->DiagnosticsWrappers[Index] = Diag =
|
|
|
|
new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
|
|
|
|
return Diag;
|
2010-02-19 02:08:43 +08:00
|
|
|
}
|
|
|
|
|
2011-07-08 00:03:39 +08:00
|
|
|
unsigned long long
|
|
|
|
clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) {
|
|
|
|
AllocatedCXCodeCompleteResults *Results
|
|
|
|
= static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
|
|
|
|
if (!Results)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return Results->Contexts;
|
|
|
|
}
|
2010-02-19 02:08:43 +08:00
|
|
|
|
2011-07-21 09:05:26 +08:00
|
|
|
enum CXCursorKind clang_codeCompleteGetContainerKind(
|
|
|
|
CXCodeCompleteResults *ResultsIn,
|
|
|
|
unsigned *IsIncomplete) {
|
|
|
|
AllocatedCXCodeCompleteResults *Results =
|
|
|
|
static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
|
|
|
|
if (!Results)
|
|
|
|
return CXCursor_InvalidCode;
|
2014-06-08 16:38:04 +08:00
|
|
|
|
|
|
|
if (IsIncomplete != nullptr) {
|
2011-07-21 09:05:26 +08:00
|
|
|
*IsIncomplete = Results->ContainerIsIncomplete;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Results->ContainerKind;
|
|
|
|
}
|
|
|
|
|
|
|
|
CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *ResultsIn) {
|
|
|
|
AllocatedCXCodeCompleteResults *Results =
|
|
|
|
static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
|
|
|
|
if (!Results)
|
2013-02-01 22:21:22 +08:00
|
|
|
return cxstring::createEmpty();
|
2013-02-08 03:09:22 +08:00
|
|
|
|
|
|
|
return cxstring::createRef(Results->ContainerUSR.c_str());
|
2011-07-21 09:05:26 +08:00
|
|
|
}
|
2011-07-26 23:24:30 +08:00
|
|
|
|
|
|
|
|
|
|
|
CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *ResultsIn) {
|
|
|
|
AllocatedCXCodeCompleteResults *Results =
|
|
|
|
static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
|
|
|
|
if (!Results)
|
2013-02-01 22:21:22 +08:00
|
|
|
return cxstring::createEmpty();
|
2011-07-26 23:24:30 +08:00
|
|
|
|
2013-02-02 10:19:29 +08:00
|
|
|
return cxstring::createDup(Results->Selector);
|
2011-07-26 23:24:30 +08:00
|
|
|
}
|
2011-07-21 09:05:26 +08:00
|
|
|
|
2010-10-19 05:05:04 +08:00
|
|
|
/// \brief Simple utility function that appends a \p New string to the given
|
|
|
|
/// \p Old string, using the \p Buffer for storage.
|
|
|
|
///
|
|
|
|
/// \param Old The string to which we are appending. This parameter will be
|
|
|
|
/// updated to reflect the complete string.
|
|
|
|
///
|
|
|
|
///
|
|
|
|
/// \param New The string to append to \p Old.
|
|
|
|
///
|
|
|
|
/// \param Buffer A buffer that stores the actual, concatenated string. It will
|
|
|
|
/// be used if the old string is already-non-empty.
|
2011-07-23 18:55:15 +08:00
|
|
|
static void AppendToString(StringRef &Old, StringRef New,
|
2012-02-13 20:32:26 +08:00
|
|
|
SmallString<256> &Buffer) {
|
2010-10-19 05:05:04 +08:00
|
|
|
if (Old.empty()) {
|
|
|
|
Old = New;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Buffer.empty())
|
|
|
|
Buffer.append(Old.begin(), Old.end());
|
|
|
|
Buffer.append(New.begin(), New.end());
|
|
|
|
Old = Buffer.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Get the typed-text blocks from the given code-completion string
|
|
|
|
/// and return them as a single string.
|
|
|
|
///
|
|
|
|
/// \param String The code-completion string whose typed-text blocks will be
|
|
|
|
/// concatenated.
|
|
|
|
///
|
|
|
|
/// \param Buffer A buffer used for storage of the completed name.
|
2011-07-23 18:55:15 +08:00
|
|
|
static StringRef GetTypedName(CodeCompletionString *String,
|
2012-02-13 20:32:26 +08:00
|
|
|
SmallString<256> &Buffer) {
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Result;
|
2010-10-19 05:05:04 +08:00
|
|
|
for (CodeCompletionString::iterator C = String->begin(), CEnd = String->end();
|
|
|
|
C != CEnd; ++C) {
|
|
|
|
if (C->Kind == CodeCompletionString::CK_TypedText)
|
|
|
|
AppendToString(Result, C->Text, Buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2010-08-26 21:48:20 +08:00
|
|
|
namespace {
|
|
|
|
struct OrderCompletionResults {
|
|
|
|
bool operator()(const CXCompletionResult &XR,
|
|
|
|
const CXCompletionResult &YR) const {
|
2011-02-02 03:23:04 +08:00
|
|
|
CodeCompletionString *X
|
|
|
|
= (CodeCompletionString *)XR.CompletionString;
|
|
|
|
CodeCompletionString *Y
|
|
|
|
= (CodeCompletionString *)YR.CompletionString;
|
2010-08-26 21:48:20 +08:00
|
|
|
|
2012-02-13 20:32:26 +08:00
|
|
|
SmallString<256> XBuffer;
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef XText = GetTypedName(X, XBuffer);
|
2012-02-13 20:32:26 +08:00
|
|
|
SmallString<256> YBuffer;
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef YText = GetTypedName(Y, YBuffer);
|
2010-08-26 21:48:20 +08:00
|
|
|
|
2010-10-19 05:05:04 +08:00
|
|
|
if (XText.empty() || YText.empty())
|
|
|
|
return !XText.empty();
|
|
|
|
|
|
|
|
int result = XText.compare_lower(YText);
|
2010-08-26 21:48:20 +08:00
|
|
|
if (result < 0)
|
|
|
|
return true;
|
|
|
|
if (result > 0)
|
|
|
|
return false;
|
|
|
|
|
2010-10-19 05:05:04 +08:00
|
|
|
result = XText.compare(YText);
|
2010-09-11 07:05:54 +08:00
|
|
|
return result < 0;
|
2010-08-26 21:48:20 +08:00
|
|
|
}
|
|
|
|
};
|
2015-06-23 07:07:51 +08:00
|
|
|
}
|
2010-08-26 21:48:20 +08:00
|
|
|
|
2016-12-17 09:09:40 +08:00
|
|
|
void clang_sortCodeCompletionResults(CXCompletionResult *Results,
|
|
|
|
unsigned NumResults) {
|
|
|
|
std::stable_sort(Results, Results + NumResults, OrderCompletionResults());
|
2010-08-26 23:07:07 +08:00
|
|
|
}
|