зеркало из https://github.com/microsoft/clang-1.git
Provide code completion results for the context-sensitive Objective-C
keywords "in", "out", "inout", "byref", "bycopy", and "oneway". git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@111884 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
5967d6228f
Коммит
d32b0225e2
|
@ -908,7 +908,7 @@ private:
|
||||||
|
|
||||||
bool isTokIdentifier_in() const;
|
bool isTokIdentifier_in() const;
|
||||||
|
|
||||||
TypeTy *ParseObjCTypeName(ObjCDeclSpec &DS);
|
TypeTy *ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter);
|
||||||
void ParseObjCMethodRequirement();
|
void ParseObjCMethodRequirement();
|
||||||
Decl *ParseObjCMethodPrototype(Decl *classOrCat,
|
Decl *ParseObjCMethodPrototype(Decl *classOrCat,
|
||||||
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
|
tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword);
|
||||||
|
@ -1185,7 +1185,7 @@ private:
|
||||||
|
|
||||||
void ParseSpecifierQualifierList(DeclSpec &DS);
|
void ParseSpecifierQualifierList(DeclSpec &DS);
|
||||||
|
|
||||||
void ParseObjCTypeQualifierList(ObjCDeclSpec &DS);
|
void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter);
|
||||||
|
|
||||||
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
|
void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS,
|
||||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none);
|
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), AccessSpecifier AS = AS_none);
|
||||||
|
|
|
@ -2782,7 +2782,9 @@ public:
|
||||||
/// \brief Code completion occurs within the body of a function on a
|
/// \brief Code completion occurs within the body of a function on a
|
||||||
/// recovery path, where we do not have a specific handle on our position
|
/// recovery path, where we do not have a specific handle on our position
|
||||||
/// in the grammar.
|
/// in the grammar.
|
||||||
PCC_RecoveryInFunction
|
PCC_RecoveryInFunction,
|
||||||
|
/// \brief Code completion occurs where only a type is permitted.
|
||||||
|
PCC_Type
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Code completion for an ordinary name that occurs within the given
|
/// \brief Code completion for an ordinary name that occurs within the given
|
||||||
|
@ -2999,6 +3001,16 @@ public:
|
||||||
unsigned NumMethods) {
|
unsigned NumMethods) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Code completion for an Objective-C method parameter or return type.
|
||||||
|
///
|
||||||
|
/// This code completion action is invoked when we are parsing the type of
|
||||||
|
/// an Objective-C method parameter or return type.
|
||||||
|
///
|
||||||
|
/// \param S The scope in which the code-completion occurs.
|
||||||
|
/// \param DS The Objective-C declaration specifiers so far.
|
||||||
|
virtual void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS){
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Code completion for the receiver in an Objective-C message send.
|
/// \brief Code completion for the receiver in an Objective-C message send.
|
||||||
///
|
///
|
||||||
/// This code completion action is invoked when we see a '[' that indicates
|
/// This code completion action is invoked when we see a '[' that indicates
|
||||||
|
|
|
@ -4679,6 +4679,7 @@ public:
|
||||||
virtual void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl,
|
virtual void CodeCompleteObjCPropertySetter(Scope *S, Decl *ClassDecl,
|
||||||
Decl **Methods,
|
Decl **Methods,
|
||||||
unsigned NumMethods);
|
unsigned NumMethods);
|
||||||
|
virtual void CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS);
|
||||||
virtual void CodeCompleteObjCMessageReceiver(Scope *S);
|
virtual void CodeCompleteObjCMessageReceiver(Scope *S);
|
||||||
virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
|
virtual void CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
|
||||||
IdentifierInfo **SelIdents,
|
IdentifierInfo **SelIdents,
|
||||||
|
|
|
@ -680,8 +680,13 @@ bool Parser::isTokIdentifier_in() const {
|
||||||
/// objc-type-qualifier
|
/// objc-type-qualifier
|
||||||
/// objc-type-qualifiers objc-type-qualifier
|
/// objc-type-qualifiers objc-type-qualifier
|
||||||
///
|
///
|
||||||
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
|
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter) {
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if (Tok.is(tok::code_completion)) {
|
||||||
|
Actions.CodeCompleteObjCPassingType(getCurScope(), DS);
|
||||||
|
ConsumeCodeCompletionToken();
|
||||||
|
}
|
||||||
|
|
||||||
if (Tok.isNot(tok::identifier))
|
if (Tok.isNot(tok::identifier))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -715,14 +720,14 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS) {
|
||||||
/// '(' objc-type-qualifiers[opt] type-name ')'
|
/// '(' objc-type-qualifiers[opt] type-name ')'
|
||||||
/// '(' objc-type-qualifiers[opt] ')'
|
/// '(' objc-type-qualifiers[opt] ')'
|
||||||
///
|
///
|
||||||
Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
|
Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter) {
|
||||||
assert(Tok.is(tok::l_paren) && "expected (");
|
assert(Tok.is(tok::l_paren) && "expected (");
|
||||||
|
|
||||||
SourceLocation LParenLoc = ConsumeParen();
|
SourceLocation LParenLoc = ConsumeParen();
|
||||||
SourceLocation TypeStartLoc = Tok.getLocation();
|
SourceLocation TypeStartLoc = Tok.getLocation();
|
||||||
|
|
||||||
// Parse type qualifiers, in, inout, etc.
|
// Parse type qualifiers, in, inout, etc.
|
||||||
ParseObjCTypeQualifierList(DS);
|
ParseObjCTypeQualifierList(DS, IsParameter);
|
||||||
|
|
||||||
TypeTy *Ty = 0;
|
TypeTy *Ty = 0;
|
||||||
if (isTypeSpecifierQualifier()) {
|
if (isTypeSpecifierQualifier()) {
|
||||||
|
@ -789,7 +794,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
||||||
TypeTy *ReturnType = 0;
|
TypeTy *ReturnType = 0;
|
||||||
ObjCDeclSpec DSRet;
|
ObjCDeclSpec DSRet;
|
||||||
if (Tok.is(tok::l_paren))
|
if (Tok.is(tok::l_paren))
|
||||||
ReturnType = ParseObjCTypeName(DSRet);
|
ReturnType = ParseObjCTypeName(DSRet, false);
|
||||||
|
|
||||||
// If attributes exist before the method, parse them.
|
// If attributes exist before the method, parse them.
|
||||||
llvm::OwningPtr<AttributeList> MethodAttrs;
|
llvm::OwningPtr<AttributeList> MethodAttrs;
|
||||||
|
@ -849,7 +854,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
|
||||||
|
|
||||||
ArgInfo.Type = 0;
|
ArgInfo.Type = 0;
|
||||||
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
|
if (Tok.is(tok::l_paren)) // Parse the argument type if present.
|
||||||
ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec);
|
ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, true);
|
||||||
|
|
||||||
// If attributes exist before the argument name, parse them.
|
// If attributes exist before the argument name, parse them.
|
||||||
ArgInfo.ArgAttrs = 0;
|
ArgInfo.ArgAttrs = 0;
|
||||||
|
|
|
@ -895,7 +895,10 @@ bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
|
||||||
|
|
||||||
/// \brief Determines whether the given declaration is a type.
|
/// \brief Determines whether the given declaration is a type.
|
||||||
bool ResultBuilder::IsType(NamedDecl *ND) const {
|
bool ResultBuilder::IsType(NamedDecl *ND) const {
|
||||||
return isa<TypeDecl>(ND);
|
if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
|
||||||
|
ND = Using->getTargetDecl();
|
||||||
|
|
||||||
|
return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Determines which members of a class should be visible via
|
/// \brief Determines which members of a class should be visible via
|
||||||
|
@ -1107,6 +1110,7 @@ static void AddFunctionSpecifiers(Action::ParserCompletionContext CCC,
|
||||||
case Action::PCC_ForInit:
|
case Action::PCC_ForInit:
|
||||||
case Action::PCC_Condition:
|
case Action::PCC_Condition:
|
||||||
case Action::PCC_RecoveryInFunction:
|
case Action::PCC_RecoveryInFunction:
|
||||||
|
case Action::PCC_Type:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1147,6 +1151,7 @@ static bool WantTypesInContext(Action::ParserCompletionContext CCC,
|
||||||
case Action::PCC_MemberTemplate:
|
case Action::PCC_MemberTemplate:
|
||||||
case Action::PCC_Statement:
|
case Action::PCC_Statement:
|
||||||
case Action::PCC_RecoveryInFunction:
|
case Action::PCC_RecoveryInFunction:
|
||||||
|
case Action::PCC_Type:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case Action::PCC_ObjCInterface:
|
case Action::PCC_ObjCInterface:
|
||||||
|
@ -1621,12 +1626,15 @@ static void AddOrdinaryNameResults(Action::ParserCompletionContext CCC,
|
||||||
Results.AddResult(Result(Pattern));
|
Results.AddResult(Result(Pattern));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Action::PCC_Type:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
|
if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
|
||||||
AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
|
AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
|
||||||
|
|
||||||
if (SemaRef.getLangOptions().CPlusPlus)
|
if (SemaRef.getLangOptions().CPlusPlus && CCC != Action::PCC_Type)
|
||||||
Results.AddResult(Result("operator"));
|
Results.AddResult(Result("operator"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3526,6 +3534,51 @@ void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl,
|
||||||
Results.data(),Results.size());
|
Results.data(),Results.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS) {
|
||||||
|
typedef CodeCompleteConsumer::Result Result;
|
||||||
|
ResultBuilder Results(*this);
|
||||||
|
Results.EnterNewScope();
|
||||||
|
|
||||||
|
// Add context-sensitive, Objective-C parameter-passing keywords.
|
||||||
|
bool AddedInOut = false;
|
||||||
|
if ((DS.getObjCDeclQualifier() &
|
||||||
|
(ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
|
||||||
|
Results.AddResult("in");
|
||||||
|
Results.AddResult("inout");
|
||||||
|
AddedInOut = true;
|
||||||
|
}
|
||||||
|
if ((DS.getObjCDeclQualifier() &
|
||||||
|
(ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
|
||||||
|
Results.AddResult("out");
|
||||||
|
if (!AddedInOut)
|
||||||
|
Results.AddResult("inout");
|
||||||
|
}
|
||||||
|
if ((DS.getObjCDeclQualifier() &
|
||||||
|
(ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
|
||||||
|
ObjCDeclSpec::DQ_Oneway)) == 0) {
|
||||||
|
Results.AddResult("bycopy");
|
||||||
|
Results.AddResult("byref");
|
||||||
|
Results.AddResult("oneway");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add various builtin type names and specifiers.
|
||||||
|
AddOrdinaryNameResults(PCC_Type, S, *this, Results);
|
||||||
|
Results.ExitScope();
|
||||||
|
|
||||||
|
// Add the various type names
|
||||||
|
Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
|
||||||
|
CodeCompletionDeclConsumer Consumer(Results, CurContext);
|
||||||
|
LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
|
||||||
|
CodeCompleter->includeGlobals());
|
||||||
|
|
||||||
|
if (CodeCompleter->includeMacros())
|
||||||
|
AddMacroResults(PP, Results);
|
||||||
|
|
||||||
|
HandleCodeCompleteResults(this, CodeCompleter,
|
||||||
|
CodeCompletionContext::CCC_Type,
|
||||||
|
Results.data(), Results.size());
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief When we have an expression with type "id", we may assume
|
/// \brief When we have an expression with type "id", we may assume
|
||||||
/// that it has some more-specific class type based on knowledge of
|
/// that it has some more-specific class type based on knowledge of
|
||||||
/// common uses of Objective-C. This routine returns that class type,
|
/// common uses of Objective-C. This routine returns that class type,
|
||||||
|
|
|
@ -53,7 +53,11 @@
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation D
|
@implementation D
|
||||||
- (int)first:(int)x second2:(float)y third:(double)z;
|
- (int)first:(int)x second2:(float)y third:(double)z { }
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface Passing
|
||||||
|
- (oneway void)method:(in id x);
|
||||||
@end
|
@end
|
||||||
|
|
||||||
// RUN: c-index-test -code-completion-at=%s:17:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
// RUN: c-index-test -code-completion-at=%s:17:3 %s | FileCheck -check-prefix=CHECK-CC1 %s
|
||||||
|
@ -116,3 +120,40 @@
|
||||||
// RUN: c-index-test -code-completion-at=%s:56:38 %s | FileCheck -check-prefix=CHECK-CCE %s
|
// RUN: c-index-test -code-completion-at=%s:56:38 %s | FileCheck -check-prefix=CHECK-CCE %s
|
||||||
// CHECK-CCE: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (20)
|
// CHECK-CCE: ObjCInstanceMethodDecl:{ResultType id}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (20)
|
||||||
// CHECK-CCE: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (5)
|
// CHECK-CCE: ObjCInstanceMethodDecl:{ResultType int}{Informative first:}{Informative second2:}{TypedText third:}{Text (double)z} (5)
|
||||||
|
// RUN: c-index-test -code-completion-at=%s:60:4 %s | FileCheck -check-prefix=CHECK-CCF %s
|
||||||
|
// CHECK-CCF: ObjCInterfaceDecl:{TypedText A} (40)
|
||||||
|
// CHECK-CCF: ObjCInterfaceDecl:{TypedText B} (40)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText bycopy} (30)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText byref} (30)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText in} (30)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText inout} (30)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText oneway} (30)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText out} (30)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText unsigned} (40)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText void} (40)
|
||||||
|
// CHECK-CCF: NotImplemented:{TypedText volatile} (40)
|
||||||
|
// RUN: c-index-test -code-completion-at=%s:60:11 %s | FileCheck -check-prefix=CHECK-CCG %s
|
||||||
|
// CHECK-CCG: ObjCInterfaceDecl:{TypedText A} (40)
|
||||||
|
// CHECK-CCG: ObjCInterfaceDecl:{TypedText B} (40)
|
||||||
|
// CHECK-CCG-NOT: NotImplemented:{TypedText bycopy} (30)
|
||||||
|
// CHECK-CCG-NOT: NotImplemented:{TypedText byref} (30)
|
||||||
|
// CHECK-CCG: NotImplemented:{TypedText in} (30)
|
||||||
|
// CHECK-CCG: NotImplemented:{TypedText inout} (30)
|
||||||
|
// CHECK-CCG-NOT: NotImplemented:{TypedText oneway} (30)
|
||||||
|
// CHECK-CCG: NotImplemented:{TypedText out} (30)
|
||||||
|
// CHECK-CCG: NotImplemented:{TypedText unsigned} (40)
|
||||||
|
// CHECK-CCG: NotImplemented:{TypedText void} (40)
|
||||||
|
// CHECK-CCG: NotImplemented:{TypedText volatile} (40)
|
||||||
|
// RUN: c-index-test -code-completion-at=%s:60:24 %s | FileCheck -check-prefix=CHECK-CCF %s
|
||||||
|
// RUN: c-index-test -code-completion-at=%s:60:26 %s | FileCheck -check-prefix=CHECK-CCH %s
|
||||||
|
// CHECK-CCH: ObjCInterfaceDecl:{TypedText A} (40)
|
||||||
|
// CHECK-CCH: ObjCInterfaceDecl:{TypedText B} (40)
|
||||||
|
// CHECK-CCH: NotImplemented:{TypedText bycopy} (30)
|
||||||
|
// CHECK-CCH: NotImplemented:{TypedText byref} (30)
|
||||||
|
// CHECK-CCH-NOT: NotImplemented:{TypedText in} (30)
|
||||||
|
// CHECK-CCH: NotImplemented:{TypedText inout} (30)
|
||||||
|
// CHECK-CCH: NotImplemented:{TypedText oneway} (30)
|
||||||
|
// CHECK-CCH: NotImplemented:{TypedText out} (30)
|
||||||
|
// CHECK-CCH: NotImplemented:{TypedText unsigned} (40)
|
||||||
|
// CHECK-CCH: NotImplemented:{TypedText void} (40)
|
||||||
|
// CHECK-CCH: NotImplemented:{TypedText volatile} (40)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче