forked from OSchip/llvm-project
Teach code completion to adjust its completion priorities based on the
type that we expect to see at a given point in the grammar, e.g., when initializing a variable, returning a result, or calling a function. We don't prune the candidate set at all, just adjust priorities to favor things that should type-check, using an ultra-simplified type system. llvm-svn: 105128
This commit is contained in:
parent
0e15c9aef6
commit
7aa6b229fe
|
@ -2729,7 +2729,27 @@ public:
|
|||
/// \param NumArgs the number of arguments in \p Args.
|
||||
virtual void CodeCompleteCall(Scope *S, ExprTy *Fn,
|
||||
ExprTy **Args, unsigned NumArgs) { }
|
||||
|
||||
|
||||
/// \brief Code completion for the initializer of a variable declaration.
|
||||
///
|
||||
/// \param S The scope in which the initializer occurs.
|
||||
///
|
||||
/// \param D The declaration being initialized.
|
||||
virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D) { }
|
||||
|
||||
/// \brief Code completion after the "return" keyword within a function.
|
||||
///
|
||||
/// \param S The scope in which the return statement occurs.
|
||||
virtual void CodeCompleteReturn(Scope *S) { }
|
||||
|
||||
/// \brief Code completion for the right-hand side of an assignment or
|
||||
/// compound assignment operator.
|
||||
///
|
||||
/// \param S The scope in which the assignment occurs.
|
||||
///
|
||||
/// \param LHS The left-hand side of the assignment expression.
|
||||
virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { }
|
||||
|
||||
/// \brief Code completion for a C++ nested-name-specifier that precedes a
|
||||
/// qualified-id of some form.
|
||||
///
|
||||
|
|
|
@ -59,6 +59,18 @@ enum {
|
|||
CCD_InBaseClass = 2
|
||||
};
|
||||
|
||||
/// \brief Priority value factors by which we will divide or multiply the
|
||||
/// priority of a code-completion result.
|
||||
enum {
|
||||
/// \brief Divide by this factor when a code-completion result's type exactly
|
||||
/// matches the type we expect.
|
||||
CCF_ExactTypeMatch = 4,
|
||||
/// \brief Divide by this factor when a code-completion result's type is
|
||||
/// similar to the type we expect (e.g., both arithmetic types, both
|
||||
/// Objective-C object pointer types).
|
||||
CCF_SimilarTypeMatch = 2
|
||||
};
|
||||
|
||||
class FunctionDecl;
|
||||
class FunctionType;
|
||||
class FunctionTemplateDecl;
|
||||
|
|
|
@ -556,6 +556,13 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
|
|||
Actions.ActOnCXXEnterDeclInitializer(CurScope, ThisDecl);
|
||||
}
|
||||
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteInitializer(CurScope, ThisDecl);
|
||||
ConsumeCodeCompletionToken();
|
||||
SkipUntil(tok::comma, true, true);
|
||||
return ThisDecl;
|
||||
}
|
||||
|
||||
OwningExprResult Init(ParseInitializer());
|
||||
|
||||
if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) {
|
||||
|
|
|
@ -343,6 +343,14 @@ Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, prec::Level MinPrec) {
|
|||
}
|
||||
}
|
||||
|
||||
// Code completion for the right-hand side of an assignment expression
|
||||
// goes through a special hook that takes the left-hand side into account.
|
||||
if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) {
|
||||
Actions.CodeCompleteAssignmentRHS(CurScope, LHS.get());
|
||||
ConsumeCodeCompletionToken();
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
// Parse another leaf here for the RHS of the operator.
|
||||
// ParseCastExpression works here because all RHS expressions in C have it
|
||||
// as a prefix, at least. However, in C++, an assignment-expression could
|
||||
|
|
|
@ -1199,6 +1199,13 @@ Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
|
|||
|
||||
OwningExprResult R(Actions);
|
||||
if (Tok.isNot(tok::semi)) {
|
||||
if (Tok.is(tok::code_completion)) {
|
||||
Actions.CodeCompleteReturn(CurScope);
|
||||
ConsumeCodeCompletionToken();
|
||||
SkipUntil(tok::semi, false, true);
|
||||
return StmtError();
|
||||
}
|
||||
|
||||
R = ParseExpression();
|
||||
if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
|
||||
SkipUntil(tok::semi, false, true);
|
||||
|
|
|
@ -4417,6 +4417,7 @@ public:
|
|||
//@{
|
||||
virtual void CodeCompleteOrdinaryName(Scope *S,
|
||||
CodeCompletionContext CompletionContext);
|
||||
virtual void CodeCompleteExpression(Scope *S, QualType T);
|
||||
virtual void CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *Base,
|
||||
SourceLocation OpLoc,
|
||||
bool IsArrow);
|
||||
|
@ -4424,6 +4425,10 @@ public:
|
|||
virtual void CodeCompleteCase(Scope *S);
|
||||
virtual void CodeCompleteCall(Scope *S, ExprTy *Fn,
|
||||
ExprTy **Args, unsigned NumArgs);
|
||||
virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D);
|
||||
virtual void CodeCompleteReturn(Scope *S);
|
||||
virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS);
|
||||
|
||||
virtual void CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
|
||||
bool EnteringContext);
|
||||
virtual void CodeCompleteUsing(Scope *S);
|
||||
|
|
|
@ -119,6 +119,13 @@ namespace {
|
|||
/// nested-name-specifiers that would otherwise be filtered out.
|
||||
bool AllowNestedNameSpecifiers;
|
||||
|
||||
/// \brief If set, the type that we would prefer our resulting value
|
||||
/// declarations to have.
|
||||
///
|
||||
/// Closely matching the preferred type gives a boost to a result's
|
||||
/// priority.
|
||||
CanQualType PreferredType;
|
||||
|
||||
/// \brief A list of shadow maps, which is used to model name hiding at
|
||||
/// different levels of, e.g., the inheritance hierarchy.
|
||||
std::list<ShadowMap> ShadowMaps;
|
||||
|
@ -147,6 +154,11 @@ namespace {
|
|||
unsigned size() const { return Results.size(); }
|
||||
bool empty() const { return Results.empty(); }
|
||||
|
||||
/// \brief Specify the preferred type.
|
||||
void setPreferredType(QualType T) {
|
||||
PreferredType = SemaRef.Context.getCanonicalType(T);
|
||||
}
|
||||
|
||||
/// \brief Specify whether nested-name-specifiers are allowed.
|
||||
void allowNestedNameSpecifiers(bool Allow = true) {
|
||||
AllowNestedNameSpecifiers = Allow;
|
||||
|
@ -565,6 +577,118 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
|
|||
Results.push_back(R);
|
||||
}
|
||||
|
||||
enum SimplifiedTypeClass {
|
||||
STC_Arithmetic,
|
||||
STC_Array,
|
||||
STC_Block,
|
||||
STC_Function,
|
||||
STC_ObjectiveC,
|
||||
STC_Other,
|
||||
STC_Pointer,
|
||||
STC_Record,
|
||||
STC_Void
|
||||
};
|
||||
|
||||
/// \brief A simplified classification of types used to determine whether two
|
||||
/// types are "similar enough" when adjusting priorities.
|
||||
static SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T) {
|
||||
switch (T->getTypeClass()) {
|
||||
case Type::Builtin:
|
||||
switch (cast<BuiltinType>(T)->getKind()) {
|
||||
case BuiltinType::Void:
|
||||
return STC_Void;
|
||||
|
||||
case BuiltinType::NullPtr:
|
||||
return STC_Pointer;
|
||||
|
||||
case BuiltinType::Overload:
|
||||
case BuiltinType::Dependent:
|
||||
case BuiltinType::UndeducedAuto:
|
||||
return STC_Other;
|
||||
|
||||
case BuiltinType::ObjCId:
|
||||
case BuiltinType::ObjCClass:
|
||||
case BuiltinType::ObjCSel:
|
||||
return STC_ObjectiveC;
|
||||
|
||||
default:
|
||||
return STC_Arithmetic;
|
||||
}
|
||||
return STC_Other;
|
||||
|
||||
case Type::Complex:
|
||||
return STC_Arithmetic;
|
||||
|
||||
case Type::Pointer:
|
||||
return STC_Pointer;
|
||||
|
||||
case Type::BlockPointer:
|
||||
return STC_Block;
|
||||
|
||||
case Type::LValueReference:
|
||||
case Type::RValueReference:
|
||||
return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
|
||||
|
||||
case Type::ConstantArray:
|
||||
case Type::IncompleteArray:
|
||||
case Type::VariableArray:
|
||||
case Type::DependentSizedArray:
|
||||
return STC_Array;
|
||||
|
||||
case Type::DependentSizedExtVector:
|
||||
case Type::Vector:
|
||||
case Type::ExtVector:
|
||||
return STC_Arithmetic;
|
||||
|
||||
case Type::FunctionProto:
|
||||
case Type::FunctionNoProto:
|
||||
return STC_Function;
|
||||
|
||||
case Type::Record:
|
||||
return STC_Record;
|
||||
|
||||
case Type::Enum:
|
||||
return STC_Arithmetic;
|
||||
|
||||
case Type::ObjCObject:
|
||||
case Type::ObjCInterface:
|
||||
case Type::ObjCObjectPointer:
|
||||
return STC_ObjectiveC;
|
||||
|
||||
default:
|
||||
return STC_Other;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Get the type that a given expression will have if this declaration
|
||||
/// is used as an expression in its "typical" code-completion form.
|
||||
static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) {
|
||||
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
|
||||
|
||||
if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
|
||||
return C.getTypeDeclType(Type);
|
||||
if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
|
||||
return C.getObjCInterfaceType(Iface);
|
||||
|
||||
QualType T;
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
|
||||
T = Function->getResultType();
|
||||
else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
|
||||
T = Method->getResultType();
|
||||
else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
|
||||
T = FunTmpl->getTemplatedDecl()->getResultType();
|
||||
else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
|
||||
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
|
||||
else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
|
||||
T = Property->getType();
|
||||
else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
|
||||
T = Value->getType();
|
||||
else
|
||||
return QualType();
|
||||
|
||||
return T.getNonReferenceType();
|
||||
}
|
||||
|
||||
void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
|
||||
NamedDecl *Hiding, bool InBaseClass = false) {
|
||||
if (R.Kind != Result::RK_Declaration) {
|
||||
|
@ -618,6 +742,21 @@ void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
|
|||
if (InBaseClass)
|
||||
R.Priority += CCD_InBaseClass;
|
||||
|
||||
if (!PreferredType.isNull()) {
|
||||
if (ValueDecl *Value = dyn_cast<ValueDecl>(R.Declaration)) {
|
||||
CanQualType T = SemaRef.Context.getCanonicalType(
|
||||
getDeclUsageType(SemaRef.Context, Value));
|
||||
// Check for exactly-matching types (modulo qualifiers).
|
||||
if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, T))
|
||||
R.Priority /= CCF_ExactTypeMatch;
|
||||
// Check for nearly-matching types, based on classification of each.
|
||||
else if ((getSimplifiedTypeClass(PreferredType)
|
||||
== getSimplifiedTypeClass(T)) &&
|
||||
!(PreferredType->isEnumeralType() && T->isEnumeralType()))
|
||||
R.Priority /= CCF_SimilarTypeMatch;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert this result into the set of results.
|
||||
Results.push_back(R);
|
||||
}
|
||||
|
@ -755,35 +894,6 @@ bool ResultBuilder::IsMember(NamedDecl *ND) const {
|
|||
isa<ObjCPropertyDecl>(ND);
|
||||
}
|
||||
|
||||
/// \brief Get the type that a given expression will have if this declaration
|
||||
/// is used as an expression in its "typical" code-completion form.
|
||||
static QualType getDeclUsageType(ASTContext &C, NamedDecl *ND) {
|
||||
ND = cast<NamedDecl>(ND->getUnderlyingDecl());
|
||||
|
||||
if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
|
||||
return C.getTypeDeclType(Type);
|
||||
if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
|
||||
return C.getObjCInterfaceType(Iface);
|
||||
|
||||
QualType T;
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
|
||||
T = Function->getResultType();
|
||||
else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
|
||||
T = Method->getResultType();
|
||||
else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
|
||||
T = FunTmpl->getTemplatedDecl()->getResultType();
|
||||
else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
|
||||
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
|
||||
else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
|
||||
T = Property->getType();
|
||||
else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
|
||||
T = Value->getType();
|
||||
else
|
||||
return QualType();
|
||||
|
||||
return T.getNonReferenceType();
|
||||
}
|
||||
|
||||
static bool isObjCReceiverType(ASTContext &C, QualType T) {
|
||||
T = C.getCanonicalType(T);
|
||||
switch (T->getTypeClass()) {
|
||||
|
@ -2131,6 +2241,31 @@ void Sema::CodeCompleteOrdinaryName(Scope *S,
|
|||
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
|
||||
}
|
||||
|
||||
/// \brief Perform code-completion in an expression context when we know what
|
||||
/// type we're looking for.
|
||||
void Sema::CodeCompleteExpression(Scope *S, QualType T) {
|
||||
typedef CodeCompleteConsumer::Result Result;
|
||||
ResultBuilder Results(*this);
|
||||
|
||||
if (WantTypesInContext(CCC_Expression, getLangOptions()))
|
||||
Results.setFilter(&ResultBuilder::IsOrdinaryName);
|
||||
else
|
||||
Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
|
||||
Results.setPreferredType(T.getNonReferenceType());
|
||||
|
||||
CodeCompletionDeclConsumer Consumer(Results, CurContext);
|
||||
LookupVisibleDecls(S, LookupOrdinaryName, Consumer);
|
||||
|
||||
Results.EnterNewScope();
|
||||
AddOrdinaryNameResults(CCC_Expression, S, *this, Results);
|
||||
Results.ExitScope();
|
||||
|
||||
if (CodeCompleter->includeMacros())
|
||||
AddMacroResults(PP, Results);
|
||||
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
|
||||
}
|
||||
|
||||
|
||||
static void AddObjCProperties(ObjCContainerDecl *Container,
|
||||
bool AllowCategories,
|
||||
DeclContext *CurContext,
|
||||
|
@ -2447,6 +2582,8 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
|
|||
}
|
||||
}
|
||||
|
||||
QualType ParamType;
|
||||
|
||||
if (!CandidateSet.empty()) {
|
||||
// Sort the overload candidate set by placing the best overloads first.
|
||||
std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
|
||||
|
@ -2459,14 +2596,85 @@ void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
|
|||
if (Cand->Viable)
|
||||
Results.push_back(ResultCandidate(Cand->Function));
|
||||
}
|
||||
|
||||
// From the viable candidates, try to determine the type of this parameter.
|
||||
for (unsigned I = 0, N = Results.size(); I != N; ++I) {
|
||||
if (const FunctionType *FType = Results[I].getFunctionType())
|
||||
if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
|
||||
if (NumArgs < Proto->getNumArgs()) {
|
||||
if (ParamType.isNull())
|
||||
ParamType = Proto->getArgType(NumArgs);
|
||||
else if (!Context.hasSameUnqualifiedType(
|
||||
ParamType.getNonReferenceType(),
|
||||
Proto->getArgType(NumArgs).getNonReferenceType())) {
|
||||
ParamType = QualType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Try to determine the parameter type from the type of the expression
|
||||
// being called.
|
||||
QualType FunctionType = Fn->getType();
|
||||
if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
|
||||
FunctionType = Ptr->getPointeeType();
|
||||
else if (const BlockPointerType *BlockPtr
|
||||
= FunctionType->getAs<BlockPointerType>())
|
||||
FunctionType = BlockPtr->getPointeeType();
|
||||
else if (const MemberPointerType *MemPtr
|
||||
= FunctionType->getAs<MemberPointerType>())
|
||||
FunctionType = MemPtr->getPointeeType();
|
||||
|
||||
if (const FunctionProtoType *Proto
|
||||
= FunctionType->getAs<FunctionProtoType>()) {
|
||||
if (NumArgs < Proto->getNumArgs())
|
||||
ParamType = Proto->getArgType(NumArgs);
|
||||
}
|
||||
}
|
||||
|
||||
CodeCompleteOrdinaryName(S, CCC_Expression);
|
||||
if (ParamType.isNull())
|
||||
CodeCompleteOrdinaryName(S, CCC_Expression);
|
||||
else
|
||||
CodeCompleteExpression(S, ParamType);
|
||||
|
||||
if (!Results.empty())
|
||||
CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
|
||||
Results.size());
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteInitializer(Scope *S, DeclPtrTy D) {
|
||||
ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D.getAs<Decl>());
|
||||
if (!VD) {
|
||||
CodeCompleteOrdinaryName(S, CCC_Expression);
|
||||
return;
|
||||
}
|
||||
|
||||
CodeCompleteExpression(S, VD->getType());
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteReturn(Scope *S) {
|
||||
QualType ResultType;
|
||||
if (isa<BlockDecl>(CurContext)) {
|
||||
if (BlockScopeInfo *BSI = getCurBlock())
|
||||
ResultType = BSI->ReturnType;
|
||||
} else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
|
||||
ResultType = Function->getResultType();
|
||||
else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
|
||||
ResultType = Method->getResultType();
|
||||
|
||||
if (ResultType.isNull())
|
||||
CodeCompleteOrdinaryName(S, CCC_Expression);
|
||||
else
|
||||
CodeCompleteExpression(S, ResultType);
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
|
||||
if (LHS)
|
||||
CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
|
||||
else
|
||||
CodeCompleteOrdinaryName(S, CCC_Expression);
|
||||
}
|
||||
|
||||
void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
|
||||
bool EnteringContext) {
|
||||
if (!SS.getScopeRep() || !CodeCompleter)
|
||||
|
|
|
@ -9,13 +9,19 @@ int test(int i, int j, int k, int l) {
|
|||
|
||||
// RUN: c-index-test -code-completion-at=%s:7:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: macro definition:{TypedText __VERSION__} (70)
|
||||
// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (12)
|
||||
// CHECK-CC1-NOT: NotImplemented:{TypedText float} (40)
|
||||
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (8)
|
||||
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText j} (2)
|
||||
// CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:7:14 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// CHECK-CC3: macro definition:{TypedText __VERSION__} (70)
|
||||
// CHECK-CC3: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC3-NOT: NotImplemented:{TypedText float} (40)
|
||||
// CHECK-CC3: ParmDecl:{ResultType int}{TypedText j} (8)
|
||||
// CHECK-CC3: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expressio
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:7:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:7:22 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:7:2 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: macro definition:{TypedText __VERSION__} (70)
|
||||
// CHECK-CC2: FunctionDecl:{ResultType int}{TypedText f}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/* Run lines are at the end, since line/column matter in this test. */
|
||||
|
||||
enum Color {
|
||||
Red, Green, Blue
|
||||
};
|
||||
|
||||
enum Priority {
|
||||
Low,
|
||||
High
|
||||
};
|
||||
|
||||
int func1(enum Color);
|
||||
enum Priority func2(int);
|
||||
void func3(float);
|
||||
enum Priority test1(enum Priority priority, enum Color color, int integer) {
|
||||
int i = integer;
|
||||
enum Color c = color;
|
||||
return priority;
|
||||
func1(c);
|
||||
void (^block)(enum Color, int);
|
||||
block(c, 17);
|
||||
c = color;
|
||||
}
|
||||
|
||||
// FIXME: It would be great for message sends to have the same
|
||||
// benefits as function calls, but we don't quite have the
|
||||
// infrastructure yet.
|
||||
|
||||
// RUN: c-index-test -code-completion-at=%s:16:11 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||
// CHECK-CC1: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (30)
|
||||
// CHECK-CC1: ParmDecl:{ResultType enum Color}{TypedText color} (4)
|
||||
// CHECK-CC1: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (12)
|
||||
// CHECK-CC1: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (25)
|
||||
// CHECK-CC1: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (30)
|
||||
// CHECK-CC1: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (30)
|
||||
// CHECK-CC1: VarDecl:{ResultType int}{TypedText i} (2)
|
||||
// CHECK-CC1: ParmDecl:{ResultType int}{TypedText integer} (2)
|
||||
// CHECK-CC1: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (30)
|
||||
// CHECK-CC1: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70)
|
||||
// CHECK-CC1: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70)
|
||||
// CHECK-CC1: ParmDecl:{ResultType enum Priority}{TypedText priority} (4)
|
||||
// CHECK-CC1: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (30)
|
||||
// CHECK-CC1: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
// CHECK-CC1: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (25)
|
||||
// RUN: c-index-test -code-completion-at=%s:17:18 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC2 %s
|
||||
// CHECK-CC2: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (15)
|
||||
// CHECK-CC2: VarDecl:{ResultType enum Color}{TypedText c} (2)
|
||||
// CHECK-CC2: ParmDecl:{ResultType enum Color}{TypedText color} (2)
|
||||
// CHECK-CC2: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25)
|
||||
// CHECK-CC2: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC2: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (15)
|
||||
// CHECK-CC2: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (60)
|
||||
// CHECK-CC2: VarDecl:{ResultType int}{TypedText i} (4)
|
||||
// CHECK-CC2: ParmDecl:{ResultType int}{TypedText integer} (4)
|
||||
// CHECK-CC2: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (60)
|
||||
// CHECK-CC2: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70)
|
||||
// CHECK-CC2: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70)
|
||||
// CHECK-CC2: ParmDecl:{ResultType enum Priority}{TypedText priority} (8)
|
||||
// CHECK-CC2: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (15)
|
||||
// CHECK-CC2: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
// CHECK-CC2: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (50)
|
||||
// RUN: c-index-test -code-completion-at=%s:18:10 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC3 %s
|
||||
// CHECK-CC3: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (60)
|
||||
// CHECK-CC3: VarDecl:{ResultType enum Color}{TypedText c} (8)
|
||||
// CHECK-CC3: ParmDecl:{ResultType enum Color}{TypedText color} (8)
|
||||
// CHECK-CC3: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25)
|
||||
// CHECK-CC3: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (12)
|
||||
// CHECK-CC3: FunctionDecl:{ResultType void}{TypedText func3}{LeftParen (}{Placeholder float}{RightParen )} (50)
|
||||
// CHECK-CC3: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (60)
|
||||
// CHECK-CC3: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (15)
|
||||
// CHECK-CC3: VarDecl:{ResultType int}{TypedText i} (4)
|
||||
// CHECK-CC3: ParmDecl:{ResultType int}{TypedText integer} (4)
|
||||
// CHECK-CC3: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (15)
|
||||
// CHECK-CC3: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70)
|
||||
// CHECK-CC3: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70)
|
||||
// CHECK-CC3: ParmDecl:{ResultType enum Priority}{TypedText priority} (2)
|
||||
// CHECK-CC3: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (60)
|
||||
// CHECK-CC3: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
// CHECK-CC3: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (12)
|
||||
// RUN: c-index-test -code-completion-at=%s:19:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC4 %s
|
||||
// CHECK-CC4: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (15)
|
||||
// CHECK-CC4: VarDecl:{ResultType enum Color}{TypedText c} (2)
|
||||
// CHECK-CC4: ParmDecl:{ResultType enum Color}{TypedText color} (2)
|
||||
// CHECK-CC4: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25)
|
||||
// CHECK-CC4: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC4: FunctionDecl:{ResultType void}{TypedText func3}{LeftParen (}{Placeholder float}{RightParen )} (50)
|
||||
// CHECK-CC4: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (15)
|
||||
// CHECK-CC4: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (60)
|
||||
// CHECK-CC4: VarDecl:{ResultType int}{TypedText i} (4)
|
||||
// CHECK-CC4: ParmDecl:{ResultType int}{TypedText integer} (4)
|
||||
// CHECK-CC4: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (60)
|
||||
// CHECK-CC4: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70)
|
||||
// CHECK-CC4: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70)
|
||||
// CHECK-CC4: ParmDecl:{ResultType enum Priority}{TypedText priority} (8)
|
||||
// CHECK-CC4: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (15)
|
||||
// CHECK-CC4: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
// CHECK-CC4: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (50)
|
||||
// RUN: c-index-test -code-completion-at=%s:21:9 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC4 %s
|
||||
// RUN: c-index-test -code-completion-at=%s:22:7 -Xclang -code-completion-patterns %s | FileCheck -check-prefix=CHECK-CC6 %s
|
||||
// CHECK-CC6: VarDecl:{ResultType void (^)(enum Color, int)}{TypedText block} (8)
|
||||
// CHECK-CC6: EnumConstantDecl:{ResultType enum Color}{TypedText Blue} (15)
|
||||
// CHECK-CC6: VarDecl:{ResultType enum Color}{TypedText c} (2)
|
||||
// CHECK-CC6: ParmDecl:{ResultType enum Color}{TypedText color} (2)
|
||||
// CHECK-CC6: FunctionDecl:{ResultType int}{TypedText func1}{LeftParen (}{Placeholder enum Color}{RightParen )} (25)
|
||||
// CHECK-CC6: FunctionDecl:{ResultType enum Priority}{TypedText func2}{LeftParen (}{Placeholder int}{RightParen )} (50)
|
||||
// CHECK-CC6: FunctionDecl:{ResultType void}{TypedText func3}{LeftParen (}{Placeholder float}{RightParen )} (50)
|
||||
// CHECK-CC6: EnumConstantDecl:{ResultType enum Color}{TypedText Green} (15)
|
||||
// CHECK-CC6: EnumConstantDecl:{ResultType enum Priority}{TypedText High} (60)
|
||||
// CHECK-CC6: VarDecl:{ResultType int}{TypedText i} (4)
|
||||
// CHECK-CC6: ParmDecl:{ResultType int}{TypedText integer} (4)
|
||||
// CHECK-CC6: EnumConstantDecl:{ResultType enum Priority}{TypedText Low} (60)
|
||||
// CHECK-CC6: macro definition:{TypedText OBJC_NEW_PROPERTIES} (70)
|
||||
// CHECK-CC6: macro definition:{TypedText OBJC_ZEROCOST_EXCEPTIONS} (70)
|
||||
// CHECK-CC6: ParmDecl:{ResultType enum Priority}{TypedText priority} (8)
|
||||
// CHECK-CC6: EnumConstantDecl:{ResultType enum Color}{TypedText Red} (15)
|
||||
// CHECK-CC6: NotImplemented:{TypedText sizeof}{LeftParen (}{Placeholder expression-or-type}{RightParen )} (30)
|
||||
// CHECK-CC6: FunctionDecl:{ResultType enum Priority}{TypedText test1}{LeftParen (}{Placeholder enum Priority priority}{Comma , }{Placeholder enum Color color}{Comma , }{Placeholder int integer}{RightParen )} (50)
|
Loading…
Reference in New Issue