forked from OSchip/llvm-project
New libclang API to expose container type for code completion, from
Connor Wakamo! llvm-svn: 135651
This commit is contained in:
parent
858e9f083d
commit
63745d5935
|
@ -3144,6 +3144,39 @@ CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
|
|||
CINDEX_LINKAGE
|
||||
unsigned long long clang_codeCompleteGetContexts(
|
||||
CXCodeCompleteResults *Results);
|
||||
|
||||
/**
|
||||
* \brief Returns the cursor kind for the container for the current code
|
||||
* completion context. The container is only guaranteed to be set for
|
||||
* contexts where a container exists (i.e. member accesses or Objective-C
|
||||
* message sends); if there is not a container, this function will return
|
||||
* CXCursor_InvalidCode.
|
||||
*
|
||||
* \param Results the code completion results to query
|
||||
*
|
||||
* \param IsIncomplete on return, this value will be false if Clang has complete
|
||||
* information about the container. If Clang does not have complete
|
||||
* information, this value will be true.
|
||||
*
|
||||
* \returns the container kind, or CXCursor_InvalidCode if there is not a
|
||||
* container
|
||||
*/
|
||||
CINDEX_LINKAGE
|
||||
enum CXCursorKind clang_codeCompleteGetContainerKind(
|
||||
CXCodeCompleteResults *Results,
|
||||
unsigned *IsIncomplete);
|
||||
|
||||
/**
|
||||
* \brief Returns the USR for the container for the current code completion
|
||||
* context. If there is not a container for the current context, this
|
||||
* function will return the empty string.
|
||||
*
|
||||
* \param Results the code completion results to query
|
||||
*
|
||||
* \returns the USR for the container
|
||||
*/
|
||||
CINDEX_LINKAGE
|
||||
CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
|
|
@ -275,7 +275,8 @@ public:
|
|||
/// \brief Construct a new code-completion context of the given kind.
|
||||
CodeCompletionContext(enum Kind Kind, QualType T) : Kind(Kind) {
|
||||
if (Kind == CCC_DotMemberAccess || Kind == CCC_ArrowMemberAccess ||
|
||||
Kind == CCC_ObjCPropertyAccess)
|
||||
Kind == CCC_ObjCPropertyAccess || Kind == CCC_ObjCClassMessage ||
|
||||
Kind == CCC_ObjCInstanceMessage)
|
||||
BaseType = T;
|
||||
else
|
||||
PreferredType = T;
|
||||
|
|
|
@ -4955,8 +4955,13 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
|
|||
unsigned NumSelIdents,
|
||||
bool AtArgumentExpression,
|
||||
bool IsSuper) {
|
||||
|
||||
QualType T = this->GetTypeFromParser(Receiver);
|
||||
|
||||
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
|
||||
CodeCompletionContext::CCC_ObjCClassMessage);
|
||||
CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
|
||||
T));
|
||||
|
||||
AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
|
||||
AtArgumentExpression, IsSuper, Results);
|
||||
|
||||
|
@ -4967,7 +4972,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
|
|||
// our preferred type, improving completion results.
|
||||
if (AtArgumentExpression) {
|
||||
QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
|
||||
NumSelIdents);
|
||||
NumSelIdents);
|
||||
if (PreferredType.isNull())
|
||||
CodeCompleteOrdinaryName(S, PCC_Expression);
|
||||
else
|
||||
|
@ -4976,7 +4981,7 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
|
|||
}
|
||||
|
||||
HandleCodeCompleteResults(this, CodeCompleter,
|
||||
CodeCompletionContext::CCC_ObjCClassMessage,
|
||||
Results.getCompletionContext(),
|
||||
Results.data(), Results.size());
|
||||
}
|
||||
|
||||
|
@ -5019,7 +5024,9 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
|
|||
|
||||
// Build the set of methods we can see.
|
||||
ResultBuilder Results(*this, CodeCompleter->getAllocator(),
|
||||
CodeCompletionContext::CCC_ObjCInstanceMessage);
|
||||
CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
|
||||
ReceiverType));
|
||||
|
||||
Results.EnterNewScope();
|
||||
|
||||
// If this is a send-to-super, try to add the special "super" send
|
||||
|
@ -5132,7 +5139,7 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
|
|||
}
|
||||
|
||||
HandleCodeCompleteResults(this, CodeCompleter,
|
||||
CodeCompletionContext::CCC_ObjCInstanceMessage,
|
||||
Results.getCompletionContext(),
|
||||
Results.data(),Results.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,9 @@ Z::operator int() const {
|
|||
// CHECK-MEMBER: CXXDestructor:{ResultType void}{TypedText ~Z}{LeftParen (}{RightParen )}
|
||||
// CHECK-MEMBER: Completion contexts:
|
||||
// CHECK-MEMBER-NEXT: Dot member access
|
||||
// CHECK-MEMBER-NEXT: Container Kind: StructDecl
|
||||
// CHECK-MEMBER-NEXT: Container is complete
|
||||
// CHECK-MEMBER-NEXT: Container USR: c:@S@Z
|
||||
|
||||
// CHECK-OVERLOAD: NotImplemented:{ResultType int &}{Text overloaded}{LeftParen (}{Text Z z}{Comma , }{CurrentParameter int second}{RightParen )}
|
||||
// CHECK-OVERLOAD: NotImplemented:{ResultType float &}{Text overloaded}{LeftParen (}{Text int i}{Comma , }{CurrentParameter long second}{RightParen )}
|
||||
|
|
|
@ -37,11 +37,26 @@ int test_more_props(Sub *s) {
|
|||
// RUN: c-index-test -code-completion-at=%s:21:7 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: ObjCPropertyDecl:{ResultType int}{TypedText prop1}
|
||||
// CHECK-CC1: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp}
|
||||
// CHECK-CC1: Completion contexts:
|
||||
// CHECK-CC1-NEXT: Objective-C property access
|
||||
// CHECK-CC1-NEXT: Container Kind: ObjCInterfaceDecl
|
||||
// CHECK-CC1-NEXT: Container is complete
|
||||
// CHECK-CC1-NEXT: Container USR: c:objc(cs)Int
|
||||
// RUN: c-index-test -code-completion-at=%s:22:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: ObjCIvarDecl:{ResultType int}{TypedText IVar} (35)
|
||||
// CHECK-CC2: ObjCIvarDecl:{ResultType int}{TypedText SuperIVar} (37)
|
||||
// CHECK-CC2: Completion contexts:
|
||||
// CHECK-CC2-NEXT: Arrow member access
|
||||
// CHECK-CC2-NEXT: Container Kind: ObjCInterfaceDecl
|
||||
// CHECK-CC2-NEXT: Container is complete
|
||||
// CHECK-CC2-NEXT: Container USR: c:objc(cs)Int
|
||||
// RUN: c-index-test -code-completion-at=%s:34:12 %s | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// CHECK-CC3: ObjCInstanceMethodDecl:{ResultType int}{TypedText myOtherPropLikeThing} (37)
|
||||
// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText myProp} (35)
|
||||
// CHECK-CC3: ObjCPropertyDecl:{ResultType int}{TypedText prop1} (35)
|
||||
// CHECK-CC3: ObjCPropertyDecl:{ResultType float}{TypedText ProtoProp} (35)
|
||||
// CHECK-CC3: Completion contexts:
|
||||
// CHECK-CC3-NEXT: Objective-C property access
|
||||
// CHECK-CC3-NEXT: Container Kind: ObjCInterfaceDecl
|
||||
// CHECK-CC3-NEXT: Container is complete
|
||||
// CHECK-CC3-NEXT: Container USR: c:objc(cs)Sub
|
|
@ -187,10 +187,20 @@ void test_block_invoke(A *(^block1)(int),
|
|||
// CHECK-CC1: {TypedText classMethod2}
|
||||
// CHECK-CC1: {TypedText new}
|
||||
// CHECK-CC1: {TypedText protocolClassMethod}
|
||||
// CHECK-CC1: Completion contexts:
|
||||
// CHECK-CC1-NEXT: Objective-C class method
|
||||
// CHECK-CC1-NEXT: Container Kind: ObjCInterfaceDecl
|
||||
// CHECK-CC1-NEXT: Container is complete
|
||||
// CHECK-CC1-NEXT: Container USR: c:objc(cs)Foo
|
||||
// RUN: c-index-test -code-completion-at=%s:24:8 %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: {TypedText categoryInstanceMethod}
|
||||
// CHECK-CC2: {TypedText instanceMethod1}
|
||||
// CHECK-CC2: {TypedText protocolInstanceMethod:}{Placeholder (int)}
|
||||
// CHECK-CC2: Completion contexts:
|
||||
// CHECK-CC2-NEXT: Objective-C instance method
|
||||
// CHECK-CC2-NEXT: Container Kind: ObjCInterfaceDecl
|
||||
// CHECK-CC2-NEXT: Container is complete
|
||||
// CHECK-CC2-NEXT: Container USR: c:objc(cs)Foo
|
||||
// RUN: c-index-test -code-completion-at=%s:61:16 %s | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyClassMethod:}{Placeholder (id)}
|
||||
// CHECK-CC3: ObjCClassMethodDecl:{ResultType int}{TypedText MyPrivateMethod}
|
||||
|
|
|
@ -1171,8 +1171,9 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
|
|||
}
|
||||
|
||||
if (results) {
|
||||
unsigned i, n = results->NumResults;
|
||||
unsigned i, n = results->NumResults, containerIsIncomplete = 0;
|
||||
unsigned long long contexts;
|
||||
enum CXCursorKind containerKind;
|
||||
if (!timing_only) {
|
||||
/* Sort the code-completion results based on the typed text. */
|
||||
clang_sortCodeCompletionResults(results->Results, results->NumResults);
|
||||
|
@ -1190,6 +1191,27 @@ int perform_code_completion(int argc, const char **argv, int timing_only) {
|
|||
contexts = clang_codeCompleteGetContexts(results);
|
||||
print_completion_contexts(contexts, stdout);
|
||||
|
||||
containerKind = clang_codeCompleteGetContainerKind(results, &containerIsIncomplete);
|
||||
|
||||
if (containerKind != CXCursor_InvalidCode) {
|
||||
/* We have found a container */
|
||||
CXString containerUSR, containerKindSpelling;
|
||||
containerKindSpelling = clang_getCursorKindSpelling(containerKind);
|
||||
printf("Container Kind: %s\n", clang_getCString(containerKindSpelling));
|
||||
clang_disposeString(containerKindSpelling);
|
||||
|
||||
if (containerIsIncomplete) {
|
||||
printf("Container is incomplete\n");
|
||||
}
|
||||
else {
|
||||
printf("Container is complete\n");
|
||||
}
|
||||
|
||||
containerUSR = clang_codeCompleteGetContainerUSR(results);
|
||||
printf("Container USR: %s\n", clang_getCString(containerUSR));
|
||||
clang_disposeString(containerUSR);
|
||||
}
|
||||
|
||||
clang_disposeCodeCompleteResults(results);
|
||||
}
|
||||
clang_disposeTranslationUnit(TU);
|
||||
|
|
|
@ -15,7 +15,11 @@
|
|||
#include "CIndexer.h"
|
||||
#include "CXTranslationUnit.h"
|
||||
#include "CXString.h"
|
||||
#include "CXCursor.h"
|
||||
#include "CIndexDiagnostic.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Frontend/ASTUnit.h"
|
||||
|
@ -242,6 +246,11 @@ struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
|
|||
/// \brief A bitfield representing the acceptable completions for the
|
||||
/// current context.
|
||||
unsigned long long Contexts;
|
||||
|
||||
enum CXCursorKind ContainerKind;
|
||||
CXString ContainerUSR;
|
||||
|
||||
unsigned ContainerIsIncomplete;
|
||||
};
|
||||
|
||||
/// \brief Tracks the number of code-completion result objects that are
|
||||
|
@ -267,6 +276,8 @@ AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults(
|
|||
AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
|
||||
delete [] Results;
|
||||
|
||||
clang_disposeString(ContainerUSR);
|
||||
|
||||
for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
|
||||
TemporaryFiles[I].eraseFromDisk();
|
||||
for (unsigned I = 0, N = TemporaryBuffers.size(); I != N; ++I)
|
||||
|
@ -455,10 +466,12 @@ namespace {
|
|||
class CaptureCompletionResults : public CodeCompleteConsumer {
|
||||
AllocatedCXCodeCompleteResults &AllocatedResults;
|
||||
llvm::SmallVector<CXCompletionResult, 16> StoredResults;
|
||||
CXTranslationUnit *TU;
|
||||
public:
|
||||
CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results)
|
||||
CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results,
|
||||
CXTranslationUnit *TranslationUnit)
|
||||
: CodeCompleteConsumer(true, false, true, false),
|
||||
AllocatedResults(Results) { }
|
||||
AllocatedResults(Results), TU(TranslationUnit) { }
|
||||
~CaptureCompletionResults() { Finish(); }
|
||||
|
||||
virtual void ProcessCodeCompleteResults(Sema &S,
|
||||
|
@ -477,10 +490,53 @@ namespace {
|
|||
StoredResults.push_back(R);
|
||||
}
|
||||
|
||||
enum CodeCompletionContext::Kind kind = Context.getKind();
|
||||
enum CodeCompletionContext::Kind contextKind = Context.getKind();
|
||||
|
||||
AllocatedResults.ContextKind = kind;
|
||||
AllocatedResults.Contexts = getContextsForContextKind(kind, S);
|
||||
AllocatedResults.ContextKind = contextKind;
|
||||
AllocatedResults.Contexts = getContextsForContextKind(contextKind, S);
|
||||
|
||||
QualType baseType = Context.getBaseType();
|
||||
NamedDecl *D = NULL;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (D != NULL) {
|
||||
CXCursor cursor = cxcursor::MakeCXCursor(D, *TU);
|
||||
|
||||
CXCursorKind cursorKind = clang_getCursorKind(cursor);
|
||||
CXString cursorUSR = clang_getCursorUSR(cursor);
|
||||
|
||||
AllocatedResults.ContainerKind = cursorKind;
|
||||
AllocatedResults.ContainerUSR = cursorUSR;
|
||||
const Type *type = baseType.getTypePtrOrNull();
|
||||
if (type != NULL) {
|
||||
AllocatedResults.ContainerIsIncomplete = type->isIncompleteType();
|
||||
}
|
||||
else {
|
||||
AllocatedResults.ContainerIsIncomplete = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
AllocatedResults.ContainerKind = CXCursor_InvalidCode;
|
||||
AllocatedResults.ContainerUSR = createCXString("");
|
||||
AllocatedResults.ContainerIsIncomplete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
|
||||
|
@ -571,7 +627,7 @@ void clang_codeCompleteAt_Impl(void *UserData) {
|
|||
Results->NumResults = 0;
|
||||
|
||||
// Create a code-completion consumer to capture the results.
|
||||
CaptureCompletionResults Capture(*Results);
|
||||
CaptureCompletionResults Capture(*Results, &TU);
|
||||
|
||||
// Perform completion.
|
||||
AST->CodeComplete(complete_filename, complete_line, complete_column,
|
||||
|
@ -731,6 +787,30 @@ clang_codeCompleteGetContexts(CXCodeCompleteResults *ResultsIn) {
|
|||
return Results->Contexts;
|
||||
}
|
||||
|
||||
enum CXCursorKind clang_codeCompleteGetContainerKind(
|
||||
CXCodeCompleteResults *ResultsIn,
|
||||
unsigned *IsIncomplete) {
|
||||
AllocatedCXCodeCompleteResults *Results =
|
||||
static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
|
||||
if (!Results)
|
||||
return CXCursor_InvalidCode;
|
||||
|
||||
if (IsIncomplete != NULL) {
|
||||
*IsIncomplete = Results->ContainerIsIncomplete;
|
||||
}
|
||||
|
||||
return Results->ContainerKind;
|
||||
}
|
||||
|
||||
CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *ResultsIn) {
|
||||
AllocatedCXCodeCompleteResults *Results =
|
||||
static_cast<AllocatedCXCodeCompleteResults *>(ResultsIn);
|
||||
if (!Results)
|
||||
return createCXString("");
|
||||
|
||||
return createCXString(clang_getCString(Results->ContainerUSR));
|
||||
}
|
||||
|
||||
} // end extern "C"
|
||||
|
||||
/// \brief Simple utility function that appends a \p New string to the given
|
||||
|
|
|
@ -6,6 +6,8 @@ _clang_annotateTokens
|
|||
_clang_codeCompleteAt
|
||||
_clang_codeCompleteGetDiagnostic
|
||||
_clang_codeCompleteGetNumDiagnostics
|
||||
_clang_codeCompleteGetContainerKind
|
||||
_clang_codeCompleteGetContainerUSR
|
||||
_clang_codeCompleteGetContexts
|
||||
_clang_constructUSR_ObjCCategory
|
||||
_clang_constructUSR_ObjCClass
|
||||
|
|
|
@ -6,6 +6,8 @@ clang_annotateTokens
|
|||
clang_codeCompleteAt
|
||||
clang_codeCompleteGetDiagnostic
|
||||
clang_codeCompleteGetNumDiagnostics
|
||||
clang_codeCompleteGetContainerKind
|
||||
clang_codeCompleteGetContainerUSR
|
||||
clang_codeCompleteGetContexts
|
||||
clang_constructUSR_ObjCCategory
|
||||
clang_constructUSR_ObjCClass
|
||||
|
|
Loading…
Reference in New Issue