зеркало из https://github.com/microsoft/clang-1.git
Introduce new libclang API functions that determine the availability
of a cursor or code-completion result, e.g., whether that result refers to an unavailable, deleted, or deprecated declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111858 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
d097be8f81
Коммит
58ddb60f40
|
@ -97,6 +97,19 @@ struct CXUnsavedFile {
|
|||
unsigned long Length;
|
||||
};
|
||||
|
||||
/// \brief Describes the availability of a particular entity, which indicates
|
||||
/// whether the use of this entity will result in a warning or error due to
|
||||
/// it being deprecated or unavailable.
|
||||
enum CXAvailabilityKind {
|
||||
/// \brief The entity is available.
|
||||
CXAvailability_Available,
|
||||
/// \brief The entity is available, but has been deprecated (and its use is
|
||||
/// not recommended).
|
||||
CXAvailability_Deprecated,
|
||||
/// \brief The entity is not available; any use of it will be an error.
|
||||
CXAvailability_NotAvailable
|
||||
};
|
||||
|
||||
/**
|
||||
* \defgroup CINDEX_STRING String manipulation routines
|
||||
*
|
||||
|
@ -1198,6 +1211,16 @@ enum CXLinkageKind {
|
|||
*/
|
||||
CINDEX_LINKAGE enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
|
||||
|
||||
/**
|
||||
* \brief Determine the availability of the entity that this cursor refers to.
|
||||
*
|
||||
* \param cursor The cursor to query.
|
||||
*
|
||||
* \returns The availability of the cursor.
|
||||
*/
|
||||
CINDEX_LINKAGE enum CXAvailabilityKind
|
||||
clang_getCursorAvailability(CXCursor cursor);
|
||||
|
||||
/**
|
||||
* \brief Describe the "language" of the entity referred to by a cursor.
|
||||
*/
|
||||
|
@ -2072,6 +2095,17 @@ clang_getNumCompletionChunks(CXCompletionString completion_string);
|
|||
CINDEX_LINKAGE unsigned
|
||||
clang_getCompletionPriority(CXCompletionString completion_string);
|
||||
|
||||
/**
|
||||
* \brief Determine the availability of the entity that this code-completion
|
||||
* string refers to.
|
||||
*
|
||||
* \param completion_string The completion string to query.
|
||||
*
|
||||
* \returns The availability of the completion string.
|
||||
*/
|
||||
CINDEX_LINKAGE enum CXAvailabilityKind
|
||||
clang_getCompletionAvailability(CXCompletionString completion_string);
|
||||
|
||||
/**
|
||||
* \brief Contains the results of code-completion.
|
||||
*
|
||||
|
|
|
@ -239,6 +239,9 @@ public:
|
|||
/// result.
|
||||
CXCursorKind Kind;
|
||||
|
||||
/// \brief The availability of this code-completion result.
|
||||
CXAvailabilityKind Availability;
|
||||
|
||||
/// \brief The simplified type class for a non-macro completion result.
|
||||
SimplifiedTypeClass TypeClass;
|
||||
|
||||
|
|
|
@ -476,6 +476,9 @@ public:
|
|||
/// \brief The cursor kind that describes this result.
|
||||
CXCursorKind CursorKind;
|
||||
|
||||
/// \brief The availability of this result.
|
||||
CXAvailabilityKind Availability;
|
||||
|
||||
/// \brief Specifies which parameter (of a function, Objective-C method,
|
||||
/// macro, etc.) we should start with when formatting the result.
|
||||
unsigned StartParameter;
|
||||
|
@ -508,39 +511,43 @@ public:
|
|||
NestedNameSpecifier *Qualifier = 0,
|
||||
bool QualifierIsInformative = false)
|
||||
: Kind(RK_Declaration), Declaration(Declaration),
|
||||
Priority(getPriorityFromDecl(Declaration)), StartParameter(0),
|
||||
Priority(getPriorityFromDecl(Declaration)),
|
||||
Availability(CXAvailability_Available), StartParameter(0),
|
||||
Hidden(false), QualifierIsInformative(QualifierIsInformative),
|
||||
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
|
||||
DeclaringEntity(false), Qualifier(Qualifier) {
|
||||
computeCursorKind();
|
||||
computeCursorKindAndAvailability();
|
||||
}
|
||||
|
||||
/// \brief Build a result that refers to a keyword or symbol.
|
||||
Result(const char *Keyword, unsigned Priority = CCP_Keyword)
|
||||
: Kind(RK_Keyword), Keyword(Keyword), Priority(Priority),
|
||||
Availability(CXAvailability_Available),
|
||||
StartParameter(0), Hidden(false), QualifierIsInformative(0),
|
||||
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
|
||||
DeclaringEntity(false), Qualifier(0) {
|
||||
computeCursorKind();
|
||||
computeCursorKindAndAvailability();
|
||||
}
|
||||
|
||||
/// \brief Build a result that refers to a macro.
|
||||
Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro)
|
||||
: Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0),
|
||||
: Kind(RK_Macro), Macro(Macro), Priority(Priority),
|
||||
Availability(CXAvailability_Available), StartParameter(0),
|
||||
Hidden(false), QualifierIsInformative(0),
|
||||
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
|
||||
DeclaringEntity(false), Qualifier(0) {
|
||||
computeCursorKind();
|
||||
computeCursorKindAndAvailability();
|
||||
}
|
||||
|
||||
/// \brief Build a result that refers to a pattern.
|
||||
Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern,
|
||||
CXCursorKind CursorKind = CXCursor_NotImplemented)
|
||||
CXCursorKind CursorKind = CXCursor_NotImplemented,
|
||||
CXAvailabilityKind Availability = CXAvailability_Available)
|
||||
: Kind(RK_Pattern), Pattern(Pattern), Priority(Priority),
|
||||
CursorKind(CursorKind), StartParameter(0), Hidden(false),
|
||||
QualifierIsInformative(0), StartsNestedNameSpecifier(false),
|
||||
AllParametersAreInformative(false), DeclaringEntity(false),
|
||||
Qualifier(0)
|
||||
CursorKind(CursorKind), Availability(Availability), StartParameter(0),
|
||||
Hidden(false), QualifierIsInformative(0),
|
||||
StartsNestedNameSpecifier(false), AllParametersAreInformative(false),
|
||||
DeclaringEntity(false), Qualifier(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -573,7 +580,7 @@ public:
|
|||
static unsigned getPriorityFromDecl(NamedDecl *ND);
|
||||
|
||||
private:
|
||||
void computeCursorKind();
|
||||
void computeCursorKindAndAvailability();
|
||||
};
|
||||
|
||||
class OverloadCandidate {
|
||||
|
|
|
@ -194,6 +194,7 @@ void ASTUnit::CacheCodeCompletionResults() {
|
|||
IsNestedNameSpecifier);
|
||||
CachedResult.Priority = Results[I].Priority;
|
||||
CachedResult.Kind = Results[I].CursorKind;
|
||||
CachedResult.Availability = Results[I].Availability;
|
||||
|
||||
// Keep track of the type of this completion in an ASTContext-agnostic
|
||||
// way.
|
||||
|
@ -280,6 +281,7 @@ void ASTUnit::CacheCodeCompletionResults() {
|
|||
|
||||
CachedResult.Priority = Results[I].Priority;
|
||||
CachedResult.Kind = Results[I].CursorKind;
|
||||
CachedResult.Availability = Results[I].Availability;
|
||||
CachedResult.TypeClass = STC_Void;
|
||||
CachedResult.Type = 0;
|
||||
CachedCompletionResults.push_back(CachedResult);
|
||||
|
@ -1644,7 +1646,8 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
|
|||
}
|
||||
}
|
||||
|
||||
AllResults.push_back(Result(C->Completion, Priority, C->Kind));
|
||||
AllResults.push_back(Result(C->Completion, Priority, C->Kind,
|
||||
C->Availability));
|
||||
}
|
||||
|
||||
// If we did not add any cached completion results, just forward the
|
||||
|
|
|
@ -496,9 +496,16 @@ PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
|
|||
}
|
||||
}
|
||||
|
||||
void CodeCompleteConsumer::Result::computeCursorKind() {
|
||||
void CodeCompleteConsumer::Result::computeCursorKindAndAvailability() {
|
||||
switch (Kind) {
|
||||
case RK_Declaration:
|
||||
// Set the availability based on attributes.
|
||||
Availability = CXAvailability_Available;
|
||||
if (Declaration->getAttr<UnavailableAttr>())
|
||||
Availability = CXAvailability_NotAvailable;
|
||||
else if (Declaration->getAttr<DeprecatedAttr>())
|
||||
Availability = CXAvailability_Deprecated;
|
||||
|
||||
switch (Declaration->getKind()) {
|
||||
case Decl::Record:
|
||||
case Decl::CXXRecord:
|
||||
|
@ -544,6 +551,8 @@ void CodeCompleteConsumer::Result::computeCursorKind() {
|
|||
case Decl::CXXDestructor:
|
||||
case Decl::CXXConversion:
|
||||
CursorKind = CXCursor_FunctionDecl;
|
||||
if (cast<FunctionDecl>(Declaration)->isDeleted())
|
||||
Availability = CXAvailability_NotAvailable;
|
||||
break;
|
||||
|
||||
case Decl::Var:
|
||||
|
@ -589,10 +598,12 @@ void CodeCompleteConsumer::Result::computeCursorKind() {
|
|||
break;
|
||||
|
||||
case Result::RK_Macro:
|
||||
Availability = CXAvailability_Available;
|
||||
CursorKind = CXCursor_MacroDefinition;
|
||||
break;
|
||||
|
||||
case Result::RK_Keyword:
|
||||
Availability = CXAvailability_Available;
|
||||
CursorKind = CXCursor_NotImplemented;
|
||||
break;
|
||||
|
||||
|
@ -611,6 +622,7 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
|
|||
for (unsigned I = 0; I != NumResults; ++I) {
|
||||
WriteUnsigned(OS, Results[I].CursorKind);
|
||||
WriteUnsigned(OS, Results[I].Priority);
|
||||
WriteUnsigned(OS, Results[I].Availability);
|
||||
CodeCompletionString *CCS = Results[I].CreateCodeCompletionString(SemaRef);
|
||||
assert(CCS && "No code-completion string?");
|
||||
CCS->Serialize(OS);
|
||||
|
@ -626,6 +638,7 @@ CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
|
|||
for (unsigned I = 0; I != NumCandidates; ++I) {
|
||||
WriteUnsigned(OS, CXCursor_NotImplemented);
|
||||
WriteUnsigned(OS, /*Priority=*/0);
|
||||
WriteUnsigned(OS, /*Availability=*/CXAvailability_Available);
|
||||
CodeCompletionString *CCS
|
||||
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef);
|
||||
assert(CCS && "No code-completion string?");
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
__attribute__((iboutlet)) id myoutlet;
|
||||
}
|
||||
- (void) __attribute__((ibaction)) myMessage:(id)msg;
|
||||
- foo;
|
||||
- foo __attribute__((deprecated));
|
||||
+ fooC;
|
||||
|
||||
@end
|
||||
|
@ -78,7 +78,7 @@ struct X0 {};
|
|||
// CHECK: <invalid loc>:0:0: attribute(ibaction)=
|
||||
// CHECK: c-index-api-loadTU-test.m:8:50: ParmDecl=msg:8:50 (Definition) Extent=[8:47 - 8:53]
|
||||
// CHECK: c-index-api-loadTU-test.m:8:47: TypeRef=id:0:0 Extent=[8:47 - 8:49]
|
||||
// CHECK: c-index-api-loadTU-test.m:9:1: ObjCInstanceMethodDecl=foo:9:1 Extent=[9:1 - 9:7]
|
||||
// CHECK: c-index-api-loadTU-test.m:9:1: ObjCInstanceMethodDecl=foo:9:1 (deprecated) Extent=[9:1 - 9:35]
|
||||
// CHECK: c-index-api-loadTU-test.m:10:1: ObjCClassMethodDecl=fooC:10:1 Extent=[10:1 - 10:8]
|
||||
// CHECK: c-index-api-loadTU-test.m:14:12: ObjCInterfaceDecl=Bar:14:12 Extent=[14:1 - 18:5]
|
||||
// CHECK: c-index-api-loadTU-test.m:14:18: ObjCSuperClassRef=Foo:4:12 Extent=[14:18 - 14:21]
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// Note: the run lines follow their respective tests, since line/column
|
||||
// matter in this test.
|
||||
|
||||
int f(int);
|
||||
int f(int) __attribute__((unavailable));
|
||||
|
||||
int test(int i, int j, int k, int l) {
|
||||
return i | j | k & l;
|
||||
}
|
||||
|
||||
struct X f1 = { 17 };
|
||||
struct X __attribute__((deprecated)) f1 = { 17 };
|
||||
void f2() { f1(17); }
|
||||
|
||||
const char *str = "Hello, \nWorld";
|
||||
|
@ -16,7 +16,7 @@ const char *str = "Hello, \nWorld";
|
|||
// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: NotImplemented:{TypedText __PRETTY_FUNCTION__} (60)
|
||||
// CHECK-CC1: macro definition:{TypedText __VERSION__} (70)
|
||||
// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12)
|
||||
// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12) (unavailable)
|
||||
// CHECK-CC1-NOT: NotImplemented:{TypedText float} (40)
|
||||
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (2)
|
||||
// CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
|
@ -44,7 +44,7 @@ const char *str = "Hello, \nWorld";
|
|||
// CHECK-CC2: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
// RUN: c-index-test -code-completion-at=%s:11:16 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC4 %s
|
||||
// CHECK-CC4: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC4: VarDecl:{ResultType struct X}{TypedText f1} (50)
|
||||
// CHECK-CC4: VarDecl:{ResultType struct X}{TypedText f1} (50) (deprecated)
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:13:28 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC5 %s
|
||||
// CHECK-CC5: NotImplemented:{TypedText void} (40)
|
||||
|
|
|
@ -182,6 +182,19 @@ static void PrintCursor(CXCursor Cursor) {
|
|||
|
||||
if (clang_isCursorDefinition(Cursor))
|
||||
printf(" (Definition)");
|
||||
|
||||
switch (clang_getCursorAvailability(Cursor)) {
|
||||
case CXAvailability_Available:
|
||||
break;
|
||||
|
||||
case CXAvailability_Deprecated:
|
||||
printf(" (deprecated)");
|
||||
break;
|
||||
|
||||
case CXAvailability_NotAvailable:
|
||||
printf(" (unavailable)");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -865,8 +878,21 @@ void print_completion_result(CXCompletionResult *completion_result,
|
|||
clang_disposeString(ks);
|
||||
|
||||
print_completion_string(completion_result->CompletionString, file);
|
||||
fprintf(file, " (%u)\n",
|
||||
fprintf(file, " (%u)",
|
||||
clang_getCompletionPriority(completion_result->CompletionString));
|
||||
switch (clang_getCompletionAvailability(completion_result->CompletionString)){
|
||||
case CXAvailability_Available:
|
||||
break;
|
||||
|
||||
case CXAvailability_Deprecated:
|
||||
fprintf(file, " (deprecated)");
|
||||
break;
|
||||
|
||||
case CXAvailability_NotAvailable:
|
||||
fprintf(file, " (unavailable)");
|
||||
break;
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
int perform_code_completion(int argc, const char **argv, int timing_only) {
|
||||
|
|
|
@ -3018,6 +3018,21 @@ static CXLanguageKind getDeclLanguage(const Decl *D) {
|
|||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
|
||||
if (clang_isDeclaration(cursor.kind))
|
||||
if (Decl *D = cxcursor::getCursorDecl(cursor)) {
|
||||
if (D->hasAttr<UnavailableAttr>() ||
|
||||
(isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->isDeleted()))
|
||||
return CXAvailability_Available;
|
||||
|
||||
if (D->hasAttr<DeprecatedAttr>())
|
||||
return CXAvailability_Deprecated;
|
||||
}
|
||||
|
||||
return CXAvailability_Available;
|
||||
}
|
||||
|
||||
CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
|
||||
if (clang_isDeclaration(cursor.kind))
|
||||
return getDeclLanguage(cxcursor::getCursorDecl(cursor));
|
||||
|
|
|
@ -48,11 +48,15 @@ namespace {
|
|||
/// This is the representation behind a CXCompletionString.
|
||||
class CXStoredCodeCompletionString : public CodeCompletionString {
|
||||
unsigned Priority;
|
||||
CXAvailabilityKind Availability;
|
||||
|
||||
public:
|
||||
CXStoredCodeCompletionString(unsigned Priority) : Priority(Priority) { }
|
||||
CXStoredCodeCompletionString(unsigned Priority,
|
||||
CXAvailabilityKind Availability)
|
||||
: Priority(Priority), Availability(Availability) { }
|
||||
|
||||
unsigned getPriority() const { return Priority; }
|
||||
CXAvailabilityKind getAvailability() const { return Availability; }
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -210,6 +214,13 @@ unsigned clang_getCompletionPriority(CXCompletionString completion_string) {
|
|||
return CCStr? CCStr->getPriority() : unsigned(CCP_Unlikely);
|
||||
}
|
||||
|
||||
enum CXAvailabilityKind
|
||||
clang_getCompletionAvailability(CXCompletionString completion_string) {
|
||||
CXStoredCodeCompletionString *CCStr
|
||||
= (CXStoredCodeCompletionString *)completion_string;
|
||||
return CCStr? CCStr->getAvailability() : CXAvailability_Available;
|
||||
}
|
||||
|
||||
static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
|
||||
unsigned &Value) {
|
||||
if (Memory + sizeof(unsigned) > MemoryEnd)
|
||||
|
@ -433,8 +444,13 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
|
|||
if (ReadUnsigned(Str, StrEnd, Priority))
|
||||
break;
|
||||
|
||||
unsigned Availability;
|
||||
if (ReadUnsigned(Str, StrEnd, Availability))
|
||||
break;
|
||||
|
||||
CXStoredCodeCompletionString *CCStr
|
||||
= new CXStoredCodeCompletionString(Priority);
|
||||
= new CXStoredCodeCompletionString(Priority,
|
||||
(CXAvailabilityKind)Availability);
|
||||
if (!CCStr->Deserialize(Str, StrEnd)) {
|
||||
delete CCStr;
|
||||
continue;
|
||||
|
@ -559,7 +575,8 @@ namespace {
|
|||
AllocatedResults.NumResults = NumResults;
|
||||
for (unsigned I = 0; I != NumResults; ++I) {
|
||||
CXStoredCodeCompletionString *StoredCompletion
|
||||
= new CXStoredCodeCompletionString(Results[I].Priority);
|
||||
= new CXStoredCodeCompletionString(Results[I].Priority,
|
||||
Results[I].Availability);
|
||||
(void)Results[I].CreateCodeCompletionString(S, StoredCompletion);
|
||||
AllocatedResults.Results[I].CursorKind = Results[I].CursorKind;
|
||||
AllocatedResults.Results[I].CompletionString = StoredCompletion;
|
||||
|
|
|
@ -32,11 +32,13 @@ _clang_formatDiagnostic
|
|||
_clang_getCString
|
||||
_clang_getCanonicalType
|
||||
_clang_getClangVersion
|
||||
_clang_getCompletionAvailability
|
||||
_clang_getCompletionChunkCompletionString
|
||||
_clang_getCompletionChunkKind
|
||||
_clang_getCompletionChunkText
|
||||
_clang_getCompletionPriority
|
||||
_clang_getCursor
|
||||
_clang_getCursorAvailability
|
||||
_clang_getCursorDefinition
|
||||
_clang_getCursorExtent
|
||||
_clang_getCursorKind
|
||||
|
|
|
@ -32,11 +32,13 @@ clang_formatDiagnostic
|
|||
clang_getCString
|
||||
clang_getCanonicalType
|
||||
clang_getClangVersion
|
||||
clang_getCompletionAvailability
|
||||
clang_getCompletionChunkCompletionString
|
||||
clang_getCompletionChunkKind
|
||||
clang_getCompletionChunkText
|
||||
clang_getCompletionPriority
|
||||
clang_getCursor
|
||||
clang_getCursorAvailability
|
||||
clang_getCursorDefinition
|
||||
clang_getCursorExtent
|
||||
clang_getCursorKind
|
||||
|
|
Загрузка…
Ссылка в новой задаче