mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-24 20:44:09 +00:00
Introduce a new libclang API to determine the parent context of a code
completion item. For example, if the code completion itself represents a declaration in a namespace (say, std::vector), then this API retrieves the cursor kind and name of the namespace (std). Implements <rdar://problem/11121951>. llvm-svn: 153545
This commit is contained in:
parent
43f340f440
commit
78254c8880
@ -3542,6 +3542,26 @@ CINDEX_LINKAGE CXString
|
||||
clang_getCompletionAnnotation(CXCompletionString completion_string,
|
||||
unsigned annotation_number);
|
||||
|
||||
/**
|
||||
* \brief Retrieve the parent context of the given completion string.
|
||||
*
|
||||
* The parent context of a completion string is the semantic parent of
|
||||
* the declaration (if any) that the code completion represents. For example,
|
||||
* a code completion for an Objective-C method would have the method's class
|
||||
* or protocol as its context.
|
||||
*
|
||||
* \param completion_string The code completion string whose parent is
|
||||
* being queried.
|
||||
*
|
||||
* \param kind If non-NULL, will be set to the kind of the parent context,
|
||||
* or CXCursor_NotImplemented if there is no context.
|
||||
*
|
||||
* \param Returns the name of the completion parent, e.g., "NSObject" if
|
||||
* the completion string represents a method in the NSObject class.
|
||||
*/
|
||||
CINDEX_LINKAGE CXString
|
||||
clang_getCompletionParent(CXCompletionString completion_string,
|
||||
enum CXCursorKind *kind);
|
||||
/**
|
||||
* \brief Retrieve a completion string for an arbitrary declaration or macro
|
||||
* definition cursor.
|
||||
|
@ -434,17 +434,24 @@ private:
|
||||
unsigned NumAnnotations : 16;
|
||||
|
||||
/// \brief The priority of this code-completion string.
|
||||
unsigned Priority : 30;
|
||||
unsigned Priority : 16;
|
||||
|
||||
/// \brief The availability of this code-completion result.
|
||||
unsigned Availability : 2;
|
||||
|
||||
/// \brief The kind of the parent context.
|
||||
unsigned ParentKind : 14;
|
||||
|
||||
/// \brief The name of the parent context.
|
||||
StringRef ParentName;
|
||||
|
||||
CodeCompletionString(const CodeCompletionString &); // DO NOT IMPLEMENT
|
||||
CodeCompletionString &operator=(const CodeCompletionString &); // DITTO
|
||||
|
||||
CodeCompletionString(const Chunk *Chunks, unsigned NumChunks,
|
||||
unsigned Priority, CXAvailabilityKind Availability,
|
||||
const char **Annotations, unsigned NumAnnotations);
|
||||
const char **Annotations, unsigned NumAnnotations,
|
||||
CXCursorKind ParentKind, StringRef ParentName);
|
||||
~CodeCompletionString() { }
|
||||
|
||||
friend class CodeCompletionBuilder;
|
||||
@ -477,6 +484,16 @@ public:
|
||||
/// \brief Retrieve the annotation string specified by \c AnnotationNr.
|
||||
const char *getAnnotation(unsigned AnnotationNr) const;
|
||||
|
||||
/// \brief Retrieve parent context's cursor kind.
|
||||
CXCursorKind getParentContextKind() const {
|
||||
return (CXCursorKind)ParentKind;
|
||||
}
|
||||
|
||||
/// \brief Retrieve the name of the parent context.
|
||||
StringRef getParentContextName() const {
|
||||
return ParentName;
|
||||
}
|
||||
|
||||
/// \brief Retrieve a string representation of the code completion string,
|
||||
/// which is mainly useful for debugging.
|
||||
std::string getAsString() const;
|
||||
@ -484,6 +501,8 @@ public:
|
||||
|
||||
/// \brief An allocator used specifically for the purpose of code completion.
|
||||
class CodeCompletionAllocator : public llvm::BumpPtrAllocator {
|
||||
llvm::DenseMap<DeclContext *, StringRef> ParentNames;
|
||||
|
||||
public:
|
||||
/// \brief Copy the given string into this allocator.
|
||||
const char *CopyString(StringRef String);
|
||||
@ -500,6 +519,12 @@ public:
|
||||
const char *CopyString(const std::string &String) {
|
||||
return CopyString(StringRef(String));
|
||||
}
|
||||
|
||||
/// \brief Retrieve the mapping from known parent declaration contexts to
|
||||
/// the (already copied) strings associated with each context.
|
||||
llvm::DenseMap<DeclContext *, StringRef> &getParentNames() {
|
||||
return ParentNames;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
@ -521,7 +546,9 @@ private:
|
||||
CodeCompletionAllocator &Allocator;
|
||||
unsigned Priority;
|
||||
CXAvailabilityKind Availability;
|
||||
|
||||
CXCursorKind ParentKind;
|
||||
StringRef ParentName;
|
||||
|
||||
/// \brief The chunks stored in this string.
|
||||
SmallVector<Chunk, 4> Chunks;
|
||||
|
||||
@ -529,12 +556,13 @@ private:
|
||||
|
||||
public:
|
||||
CodeCompletionBuilder(CodeCompletionAllocator &Allocator)
|
||||
: Allocator(Allocator), Priority(0), Availability(CXAvailability_Available){
|
||||
}
|
||||
: Allocator(Allocator), Priority(0), Availability(CXAvailability_Available),
|
||||
ParentKind(CXCursor_NotImplemented) { }
|
||||
|
||||
CodeCompletionBuilder(CodeCompletionAllocator &Allocator,
|
||||
unsigned Priority, CXAvailabilityKind Availability)
|
||||
: Allocator(Allocator), Priority(Priority), Availability(Availability) { }
|
||||
: Allocator(Allocator), Priority(Priority), Availability(Availability),
|
||||
ParentKind(CXCursor_NotImplemented) { }
|
||||
|
||||
/// \brief Retrieve the allocator into which the code completion
|
||||
/// strings should be allocated.
|
||||
@ -570,6 +598,12 @@ public:
|
||||
void AddChunk(CodeCompletionString::ChunkKind CK, const char *Text = "");
|
||||
|
||||
void AddAnnotation(const char *A) { Annotations.push_back(A); }
|
||||
|
||||
/// \brief Add the parent context information to this code completion.
|
||||
void addParentContext(DeclContext *DC);
|
||||
|
||||
CXCursorKind getParentKind() const { return ParentKind; }
|
||||
StringRef getParentName() const { return ParentName; }
|
||||
};
|
||||
|
||||
/// \brief Captures a result of code completion.
|
||||
@ -586,11 +620,11 @@ public:
|
||||
/// \brief The kind of result stored here.
|
||||
ResultKind Kind;
|
||||
|
||||
union {
|
||||
/// \brief When Kind == RK_Declaration, the declaration we are referring
|
||||
/// to.
|
||||
NamedDecl *Declaration;
|
||||
/// \brief When Kind == RK_Declaration or RK_Pattern, the declaration we are
|
||||
/// referring to. In the latter case, the declaration might be NULL.
|
||||
NamedDecl *Declaration;
|
||||
|
||||
union {
|
||||
/// \brief When Kind == RK_Keyword, the string representing the keyword
|
||||
/// or symbol's spelling.
|
||||
const char *Keyword;
|
||||
@ -655,7 +689,7 @@ public:
|
||||
|
||||
/// \brief Build a result that refers to a keyword or symbol.
|
||||
CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword)
|
||||
: Kind(RK_Keyword), Keyword(Keyword), Priority(Priority),
|
||||
: Kind(RK_Keyword), Declaration(0), Keyword(Keyword), Priority(Priority),
|
||||
Availability(CXAvailability_Available),
|
||||
StartParameter(0), Hidden(false), QualifierIsInformative(0),
|
||||
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
|
||||
@ -665,7 +699,7 @@ public:
|
||||
|
||||
/// \brief Build a result that refers to a macro.
|
||||
CodeCompletionResult(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
|
||||
: Kind(RK_Macro), Macro(Macro), Priority(Priority),
|
||||
: Kind(RK_Macro), Declaration(0), Macro(Macro), Priority(Priority),
|
||||
Availability(CXAvailability_Available), StartParameter(0),
|
||||
Hidden(false), QualifierIsInformative(0),
|
||||
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
|
||||
@ -677,8 +711,9 @@ public:
|
||||
CodeCompletionResult(CodeCompletionString *Pattern,
|
||||
unsigned Priority = CCP_CodePattern,
|
||||
CXCursorKind CursorKind = CXCursor_NotImplemented,
|
||||
CXAvailabilityKind Availability = CXAvailability_Available)
|
||||
: Kind(RK_Pattern), Pattern(Pattern), Priority(Priority),
|
||||
CXAvailabilityKind Availability = CXAvailability_Available,
|
||||
NamedDecl *D = 0)
|
||||
: Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority),
|
||||
CursorKind(CursorKind), Availability(Availability), StartParameter(0),
|
||||
Hidden(false), QualifierIsInformative(0),
|
||||
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
|
||||
@ -686,6 +721,18 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/// \brief Build a result that refers to a pattern with an associated
|
||||
/// declaration.
|
||||
CodeCompletionResult(CodeCompletionString *Pattern, NamedDecl *D,
|
||||
unsigned Priority)
|
||||
: Kind(RK_Pattern), Declaration(D), Pattern(Pattern), Priority(Priority),
|
||||
Availability(CXAvailability_Available), StartParameter(0),
|
||||
Hidden(false), QualifierIsInformative(false),
|
||||
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
|
||||
DeclaringEntity(false), Qualifier(0) {
|
||||
computeCursorKindAndAvailability();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the declaration stored in this result.
|
||||
NamedDecl *getDeclaration() const {
|
||||
assert(Kind == RK_Declaration && "Not a declaration result");
|
||||
|
@ -845,7 +845,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
|
||||
}
|
||||
|
||||
std::string NamedDecl::getQualifiedNameAsString() const {
|
||||
return getQualifiedNameAsString(getASTContext().getLangOpts());
|
||||
return getQualifiedNameAsString(getASTContext().getPrintingPolicy());
|
||||
}
|
||||
|
||||
std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {
|
||||
|
@ -192,9 +192,12 @@ CodeCompletionString::CodeCompletionString(const Chunk *Chunks,
|
||||
unsigned Priority,
|
||||
CXAvailabilityKind Availability,
|
||||
const char **Annotations,
|
||||
unsigned NumAnnotations)
|
||||
: NumChunks(NumChunks), NumAnnotations(NumAnnotations)
|
||||
, Priority(Priority), Availability(Availability)
|
||||
unsigned NumAnnotations,
|
||||
CXCursorKind ParentKind,
|
||||
StringRef ParentName)
|
||||
: NumChunks(NumChunks), NumAnnotations(NumAnnotations),
|
||||
Priority(Priority), Availability(Availability), ParentKind(ParentKind),
|
||||
ParentName(ParentName)
|
||||
{
|
||||
assert(NumChunks <= 0xffff);
|
||||
assert(NumAnnotations <= 0xffff);
|
||||
@ -272,7 +275,8 @@ CodeCompletionString *CodeCompletionBuilder::TakeString() {
|
||||
CodeCompletionString *Result
|
||||
= new (Mem) CodeCompletionString(Chunks.data(), Chunks.size(),
|
||||
Priority, Availability,
|
||||
Annotations.data(), Annotations.size());
|
||||
Annotations.data(), Annotations.size(),
|
||||
ParentKind, ParentName);
|
||||
Chunks.clear();
|
||||
return Result;
|
||||
}
|
||||
@ -311,6 +315,70 @@ void CodeCompletionBuilder::AddChunk(CodeCompletionString::ChunkKind CK,
|
||||
Chunks.push_back(Chunk(CK, Text));
|
||||
}
|
||||
|
||||
void CodeCompletionBuilder::addParentContext(DeclContext *DC) {
|
||||
if (DC->isTranslationUnit()) {
|
||||
ParentKind = CXCursor_TranslationUnit;
|
||||
return;
|
||||
}
|
||||
|
||||
if (DC->isFunctionOrMethod())
|
||||
return;
|
||||
|
||||
NamedDecl *ND = dyn_cast<NamedDecl>(DC);
|
||||
if (!ND)
|
||||
return;
|
||||
|
||||
ParentKind = getCursorKindForDecl(ND);
|
||||
|
||||
// Check whether we've already cached the parent name.
|
||||
StringRef &CachedParentName = Allocator.getParentNames()[DC];
|
||||
if (!CachedParentName.empty()) {
|
||||
ParentName = CachedParentName;
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the interesting names.
|
||||
llvm::SmallVector<DeclContext *, 2> Contexts;
|
||||
while (DC && !DC->isFunctionOrMethod()) {
|
||||
if (NamedDecl *ND = dyn_cast<NamedDecl>(DC)) {
|
||||
if (ND->getIdentifier())
|
||||
Contexts.push_back(DC);
|
||||
}
|
||||
|
||||
DC = DC->getParent();
|
||||
}
|
||||
|
||||
{
|
||||
llvm::SmallString<128> S;
|
||||
llvm::raw_svector_ostream OS(S);
|
||||
bool First = true;
|
||||
for (unsigned I = Contexts.size(); I != 0; --I) {
|
||||
if (First)
|
||||
First = false;
|
||||
else {
|
||||
OS << "::";
|
||||
}
|
||||
|
||||
DeclContext *CurDC = Contexts[I-1];
|
||||
if (ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(CurDC))
|
||||
CurDC = CatImpl->getCategoryDecl();
|
||||
|
||||
if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CurDC)) {
|
||||
ObjCInterfaceDecl *Interface = Cat->getClassInterface();
|
||||
if (!Interface)
|
||||
return;
|
||||
|
||||
OS << Interface->getName() << '(' << Cat->getName() << ')';
|
||||
} else {
|
||||
OS << cast<NamedDecl>(CurDC)->getName();
|
||||
}
|
||||
}
|
||||
|
||||
ParentName = Allocator.CopyString(OS.str());
|
||||
CachedParentName = ParentName;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
|
||||
if (!ND)
|
||||
return CCP_Unlikely;
|
||||
@ -444,6 +512,13 @@ static AvailabilityResult getDeclAvailability(Decl *D) {
|
||||
|
||||
void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
|
||||
switch (Kind) {
|
||||
case RK_Pattern:
|
||||
if (!Declaration) {
|
||||
// Do nothing: Patterns can come with cursor kinds!
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
|
||||
case RK_Declaration: {
|
||||
// Set the availability based on attributes.
|
||||
switch (getDeclAvailability(Declaration)) {
|
||||
@ -488,11 +563,7 @@ void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
|
||||
case RK_Keyword:
|
||||
Availability = CXAvailability_Available;
|
||||
CursorKind = CXCursor_NotImplemented;
|
||||
break;
|
||||
|
||||
case RK_Pattern:
|
||||
// Do nothing: Patterns can come with cursor kinds!
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Accessible)
|
||||
|
@ -2454,6 +2454,13 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
|
||||
if (Kind == RK_Pattern) {
|
||||
Pattern->Priority = Priority;
|
||||
Pattern->Availability = Availability;
|
||||
|
||||
if (Declaration) {
|
||||
Result.addParentContext(Declaration->getDeclContext());
|
||||
Pattern->ParentKind = Result.getParentKind();
|
||||
Pattern->ParentName = Result.getParentName();
|
||||
}
|
||||
|
||||
return Pattern;
|
||||
}
|
||||
|
||||
@ -2509,7 +2516,8 @@ CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
|
||||
|
||||
assert(Kind == RK_Declaration && "Missed a result kind?");
|
||||
NamedDecl *ND = Declaration;
|
||||
|
||||
Result.addParentContext(ND->getDeclContext());
|
||||
|
||||
if (StartsNestedNameSpecifier) {
|
||||
Result.AddTypedTextChunk(
|
||||
Result.getAllocator().CopyString(ND->getNameAsString()));
|
||||
@ -3023,7 +3031,9 @@ static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
|
||||
Builder.AddChunk(CodeCompletionString::CK_RightParen);
|
||||
Results.AddResult(CodeCompletionResult(Builder.TakeString(),
|
||||
CCP_SuperCompletion,
|
||||
CXCursor_CXXMethod));
|
||||
CXCursor_CXXMethod,
|
||||
CXAvailability_Available,
|
||||
Overridden));
|
||||
Results.Ignore(Overridden);
|
||||
}
|
||||
}
|
||||
@ -3342,28 +3352,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
|
||||
Builder.AddTypedTextChunk(
|
||||
Results.getAllocator().CopyString(Name->getName()));
|
||||
|
||||
CXAvailabilityKind Availability = CXAvailability_Available;
|
||||
switch (M->getAvailability()) {
|
||||
case AR_Available:
|
||||
case AR_NotYetIntroduced:
|
||||
Availability = CXAvailability_Available;
|
||||
break;
|
||||
|
||||
case AR_Deprecated:
|
||||
Availability = CXAvailability_Deprecated;
|
||||
break;
|
||||
|
||||
case AR_Unavailable:
|
||||
Availability = CXAvailability_NotAvailable;
|
||||
break;
|
||||
}
|
||||
|
||||
Results.MaybeAddResult(Result(Builder.TakeString(),
|
||||
CCP_MemberDeclaration + CCD_MethodAsProperty,
|
||||
M->isInstanceMethod()
|
||||
? CXCursor_ObjCInstanceMethodDecl
|
||||
: CXCursor_ObjCClassMethodDecl,
|
||||
Availability),
|
||||
Results.MaybeAddResult(Result(Builder.TakeString(), *M,
|
||||
CCP_MemberDeclaration + CCD_MethodAsProperty),
|
||||
CurContext);
|
||||
}
|
||||
}
|
||||
@ -4028,7 +4018,8 @@ void Sema::CodeCompleteNamespaceDecl(Scope *S) {
|
||||
// namespace to the list of results.
|
||||
Results.EnterNewScope();
|
||||
for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
|
||||
NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
|
||||
NS = OrigToLatest.begin(),
|
||||
NSEnd = OrigToLatest.end();
|
||||
NS != NSEnd; ++NS)
|
||||
Results.AddResult(CodeCompletionResult(NS->second, 0),
|
||||
CurContext, 0, false);
|
||||
@ -4188,7 +4179,9 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
|
||||
Results.AddResult(CodeCompletionResult(Builder.TakeString(),
|
||||
SawLastInitializer? CCP_NextInitializer
|
||||
: CCP_MemberDeclaration,
|
||||
CXCursor_MemberRef));
|
||||
CXCursor_MemberRef,
|
||||
CXAvailability_Available,
|
||||
*Field));
|
||||
SawLastInitializer = false;
|
||||
}
|
||||
Results.ExitScope();
|
||||
@ -5057,10 +5050,8 @@ static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
|
||||
}
|
||||
}
|
||||
|
||||
Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
|
||||
SuperMethod->isInstanceMethod()
|
||||
? CXCursor_ObjCInstanceMethodDecl
|
||||
: CXCursor_ObjCClassMethodDecl));
|
||||
Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
|
||||
CCP_SuperCompletion));
|
||||
return SuperMethod;
|
||||
}
|
||||
|
||||
@ -6747,10 +6738,7 @@ void Sema::CodeCompleteObjCMethodDecl(Scope *S,
|
||||
if (!M->second.second)
|
||||
Priority += CCD_InBaseClass;
|
||||
|
||||
Results.AddResult(Result(Builder.TakeString(), Priority,
|
||||
Method->isInstanceMethod()
|
||||
? CXCursor_ObjCInstanceMethodDecl
|
||||
: CXCursor_ObjCClassMethodDecl));
|
||||
Results.AddResult(Result(Builder.TakeString(), Method, Priority));
|
||||
}
|
||||
|
||||
// Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
|
||||
|
@ -34,6 +34,17 @@ void X::f() const {
|
||||
|
||||
}
|
||||
|
||||
namespace N {
|
||||
int x;
|
||||
class C {
|
||||
int member;
|
||||
|
||||
int f(int param) {
|
||||
return member;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:20:2 %s -std=c++0x | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_COMPLETION_CACHING=1 c-index-test -code-completion-at=%s:20:2 -std=c++0x %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: NotImplemented:{ResultType size_t}{TypedText alignof}{LeftParen (}{Placeholder type}{RightParen )} (40)
|
||||
@ -65,3 +76,9 @@ void X::f() const {
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:34:1 %s -std=c++0x | FileCheck -check-prefix=CHECK-CC4 %s
|
||||
// CHECK-CC4: NotImplemented:{ResultType const X *}{TypedText this} (40)
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:43:14 %s | FileCheck -check-prefix=CHECK-CC5 %s
|
||||
// CHECK-CC5: FieldDecl:{ResultType int}{TypedText member} (8) (parent: ClassDecl 'N::C')
|
||||
// CHECK-CC5: ParmDecl:{ResultType int}{TypedText param} (8)
|
||||
// CHECK-CC5: StructDecl:{TypedText X} (50) (parent: TranslationUnit '(null)')
|
||||
// CHECK-CC5: VarDecl:{ResultType int}{TypedText x} (12) (parent: Namespace 'N')
|
||||
|
@ -69,11 +69,11 @@
|
||||
@end
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:17:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText abc}
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getInt}
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf}
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{TypedText second:}{LeftParen (}{Text int}{RightParen )}{Text y}
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText abc} (40) (parent: ObjCProtocolDecl 'P1')
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText getInt} (40) (parent: ObjCProtocolDecl 'P1')
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText getSelf} (40) (parent: ObjCProtocolDecl 'P1')
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithInt}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x} (40) (parent: ObjCProtocolDecl 'P1')
|
||||
// CHECK-CC1: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{TypedText second:}{LeftParen (}{Text int}{RightParen )}{Text y} (40) (parent: ObjCProtocolDecl 'P1')
|
||||
// RUN: c-index-test -code-completion-at=%s:17:7 %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: ObjCInstanceMethodDecl:{TypedText abc}
|
||||
// CHECK-CC2-NEXT: ObjCInstanceMethodDecl:{TypedText getSelf}
|
||||
@ -94,8 +94,8 @@
|
||||
// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text id}{RightParen )}{TypedText initWithTwoInts}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{TypedText second:}{LeftParen (}{Text int}{RightParen )}{Text y}{HorizontalSpace }{LeftBrace {}{VerticalSpace
|
||||
// CHECK-CC4: ObjCInstanceMethodDecl:{LeftParen (}{Text int}{RightParen )}{TypedText setValue}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
|
||||
// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:33:8 %s | FileCheck -check-prefix=CHECK-CC5 %s
|
||||
// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getInt}{HorizontalSpace }{LeftBrace {}{VerticalSpace
|
||||
// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getSecondValue}{HorizontalSpace }{LeftBrace {}{VerticalSpace
|
||||
// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getInt}{HorizontalSpace }{LeftBrace {}{VerticalSpace }{Text return}{HorizontalSpace }{Placeholder expression}{SemiColon ;}{VerticalSpace }{RightBrace }} (42) (parent: ObjCProtocolDecl 'P1')
|
||||
// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText getSecondValue}{HorizontalSpace }{LeftBrace {}{VerticalSpace }{Text return}{HorizontalSpace }{Placeholder expression}{SemiColon ;}{VerticalSpace }{RightBrace }} (40) (parent: ObjCInterfaceDecl 'B')
|
||||
// CHECK-CC5-NOT: {TypedText getSelf}{HorizontalSpace }{LeftBrace {}{VerticalSpace
|
||||
// CHECK-CC5: ObjCInstanceMethodDecl:{TypedText setValue}{TypedText :}{LeftParen (}{Text int}{RightParen )}{Text x}{HorizontalSpace }{LeftBrace {}{VerticalSpace
|
||||
// RUN: env CINDEXTEST_CODE_COMPLETE_PATTERNS=1 c-index-test -code-completion-at=%s:37:7 %s | FileCheck -check-prefix=CHECK-CC6 %s
|
||||
|
@ -190,11 +190,11 @@ void test_DO(DO *d, A* a) {
|
||||
}
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: {TypedText categoryClassMethod}
|
||||
// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)}{HorizontalSpace }{TypedText withKeyword:}{Placeholder (int)}
|
||||
// CHECK-CC1: {TypedText classMethod2}
|
||||
// CHECK-CC1: {TypedText new}
|
||||
// CHECK-CC1: {TypedText protocolClassMethod}
|
||||
// CHECK-CC1: {TypedText categoryClassMethod} (35) (parent: ObjCCategoryDecl 'Foo(FooTestCategory)')
|
||||
// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)}{HorizontalSpace }{TypedText withKeyword:}{Placeholder (int)} (35) (parent: ObjCInterfaceDecl 'Foo')
|
||||
// CHECK-CC1: {TypedText classMethod2} (35) (parent: ObjCInterfaceDecl 'Foo')
|
||||
// CHECK-CC1: {TypedText new} (35) (parent: ObjCInterfaceDecl 'Foo')
|
||||
// CHECK-CC1: {TypedText protocolClassMethod} (37) (parent: ObjCProtocolDecl 'FooTestProtocol')
|
||||
// CHECK-CC1: Completion contexts:
|
||||
// CHECK-CC1-NEXT: Objective-C class method
|
||||
// CHECK-CC1-NEXT: Container Kind: ObjCInterfaceDecl
|
||||
@ -309,7 +309,7 @@ void test_DO(DO *d, A* a) {
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:170:16 %s | FileCheck -check-prefix=CHECK-CLASS-RESULT %s
|
||||
// CHECK-CLASS-RESULT: ObjCClassMethodDecl:{ResultType void}{TypedText class_method3} (35)
|
||||
// CHECK-CLASS-RESULT: ObjCClassMethodDecl:{ResultType void}{TypedText class_method4} (35)
|
||||
// CHECK-CLASS-RESULT: ObjCClassMethodDecl:{ResultType void}{TypedText class_method4} (35) (parent: ObjCCategoryDecl 'A(Cat)')
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:181:4 %s | FileCheck -check-prefix=CHECK-BLOCK-RECEIVER %s
|
||||
// CHECK-BLOCK-RECEIVER: ObjCInterfaceDecl:{TypedText A} (50)
|
||||
|
@ -14,7 +14,7 @@ void foo()
|
||||
Foo::
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:14:8 %s -o - | FileCheck -check-prefix=CC1 %s
|
||||
// CHECK-CC1: FieldDecl:{ResultType C<Foo, class Bar>}{TypedText c} (35)
|
||||
// CHECK-CC1: ClassDecl:{TypedText Foo} (35)
|
||||
// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}{LeftParen (}{Placeholder const Foo &}{RightParen )} (35)
|
||||
// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo}{LeftParen (}{RightParen )} (35)
|
||||
// CHECK-CC1: FieldDecl:{ResultType C<Foo, class Bar>}{TypedText c} (35) (parent: ClassDecl 'Foo')
|
||||
// CHECK-CC1: ClassDecl:{TypedText Foo} (35) (parent: ClassDecl 'Foo')
|
||||
// CHECK-CC1: CXXMethod:{ResultType Foo &}{TypedText operator=}{LeftParen (}{Placeholder const Foo &}{RightParen )} (35) (parent: ClassDecl 'Foo')
|
||||
// CHECK-CC1: CXXDestructor:{ResultType void}{TypedText ~Foo}{LeftParen (}{RightParen )} (35) (parent: ClassDecl 'Foo')
|
||||
|
@ -1082,7 +1082,9 @@ void print_completion_result(CXCompletionResult *completion_result,
|
||||
FILE *file = (FILE *)client_data;
|
||||
CXString ks = clang_getCursorKindSpelling(completion_result->CursorKind);
|
||||
unsigned annotationCount;
|
||||
|
||||
enum CXCursorKind ParentKind;
|
||||
CXString ParentName;
|
||||
|
||||
fprintf(file, "%s:", clang_getCString(ks));
|
||||
clang_disposeString(ks);
|
||||
|
||||
@ -1121,6 +1123,19 @@ void print_completion_result(CXCompletionResult *completion_result,
|
||||
fprintf(file, ")");
|
||||
}
|
||||
|
||||
if (!getenv("CINDEXTEST_NO_COMPLETION_PARENTS")) {
|
||||
ParentName = clang_getCompletionParent(completion_result->CompletionString,
|
||||
&ParentKind);
|
||||
if (ParentKind != CXCursor_NotImplemented) {
|
||||
CXString KindSpelling = clang_getCursorKindSpelling(ParentKind);
|
||||
fprintf(file, " (parent: %s '%s')",
|
||||
clang_getCString(KindSpelling),
|
||||
clang_getCString(ParentName));
|
||||
clang_disposeString(KindSpelling);
|
||||
}
|
||||
clang_disposeString(ParentName);
|
||||
}
|
||||
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
|
@ -213,7 +213,21 @@ CXString clang_getCompletionAnnotation(CXCompletionString completion_string,
|
||||
: createCXString((const char *) 0);
|
||||
}
|
||||
|
||||
|
||||
CXString
|
||||
clang_getCompletionParent(CXCompletionString completion_string,
|
||||
CXCursorKind *kind) {
|
||||
if (kind)
|
||||
*kind = CXCursor_NotImplemented;
|
||||
|
||||
CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
|
||||
if (!CCStr)
|
||||
return createCXString((const char *)0);
|
||||
|
||||
if (kind)
|
||||
*kind = CCStr->getParentContextKind();
|
||||
return createCXString(CCStr->getParentContextName(), /*DupString=*/false);
|
||||
}
|
||||
|
||||
/// \brief The CXCodeCompleteResults structure we allocate internally;
|
||||
/// the client only sees the initial CXCodeCompleteResults structure.
|
||||
struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
|
||||
|
@ -65,6 +65,7 @@ clang_getCompletionChunkCompletionString
|
||||
clang_getCompletionChunkKind
|
||||
clang_getCompletionChunkText
|
||||
clang_getCompletionNumAnnotations
|
||||
clang_getCompletionParent
|
||||
clang_getCompletionPriority
|
||||
clang_getCursor
|
||||
clang_getCursorAvailability
|
||||
|
Loading…
x
Reference in New Issue
Block a user