r240159 - Code completion for nullability type specifiers.
Douglas Gregor
dgregor at apple.com
Fri Jun 19 11:27:52 PDT 2015
Author: dgregor
Date: Fri Jun 19 13:27:52 2015
New Revision: 240159
URL: http://llvm.org/viewvc/llvm-project?rev=240159&view=rev
Log:
Code completion for nullability type specifiers.
Another part of rdar://problem/18868820.
Modified:
cfe/trunk/lib/AST/DeclPrinter.cpp
cfe/trunk/lib/Sema/SemaCodeComplete.cpp
cfe/trunk/test/Index/complete-method-decls.m
cfe/trunk/test/Index/complete-objc-message.m
cfe/trunk/test/Index/complete-property-flags.m
cfe/trunk/test/Index/complete-stmt.c
Modified: cfe/trunk/lib/AST/DeclPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclPrinter.cpp?rev=240159&r1=240158&r2=240159&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Fri Jun 19 13:27:52 2015
@@ -937,18 +937,6 @@ void DeclPrinter::VisitClassTemplateDecl
// Objective-C declarations
//----------------------------------------------------------------------------
-/// Strip off the top-level nullability annotation, if it's there.
-static Optional<NullabilityKind> stripOuterNullability(QualType &T) {
- if (auto attributed = dyn_cast<AttributedType>(T.getTypePtr())) {
- if (auto nullability = attributed->getImmediateNullability()) {
- T = attributed->getModifiedType();
- return nullability;
- }
- }
-
- return None;
- }
-
void DeclPrinter::PrintObjCMethodType(ASTContext &Ctx,
Decl::ObjCDeclQualifier Quals,
QualType T) {
@@ -966,7 +954,7 @@ void DeclPrinter::PrintObjCMethodType(AS
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_Oneway)
Out << "oneway ";
if (Quals & Decl::ObjCDeclQualifier::OBJC_TQ_CSNullability) {
- if (auto nullability = stripOuterNullability(T)) {
+ if (auto nullability = AttributedType::stripOuterNullability(T)) {
Out << getNullabilitySpelling(*nullability).substr(2) << ' ';
}
}
@@ -1212,7 +1200,7 @@ void DeclPrinter::VisitObjCPropertyDecl(
if (PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_nullability) {
- if (auto nullability = stripOuterNullability(T)) {
+ if (auto nullability = AttributedType::stripOuterNullability(T)) {
if (*nullability == NullabilityKind::Unspecified &&
(PDecl->getPropertyAttributes() &
ObjCPropertyDecl::OBJC_PR_null_resettable)) {
Modified: cfe/trunk/lib/Sema/SemaCodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCodeComplete.cpp?rev=240159&r1=240158&r2=240159&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCodeComplete.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCodeComplete.cpp Fri Jun 19 13:27:52 2015
@@ -1341,6 +1341,11 @@ static void AddTypeSpecifierResults(cons
Builder.AddChunk(CodeCompletionString::CK_RightParen);
Results.AddResult(Result(Builder.TakeString()));
}
+
+ // Nullability
+ Results.AddResult(Result("__nonnull", CCP_Type));
+ Results.AddResult(Result("__null_unspecified", CCP_Type));
+ Results.AddResult(Result("__nullable", CCP_Type));
}
static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
@@ -2097,7 +2102,8 @@ static void MaybeAddSentinel(Preprocesso
}
}
-static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
+static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
+ QualType &Type) {
std::string Result;
if (ObjCQuals & Decl::OBJC_TQ_In)
Result += "in ";
@@ -2111,6 +2117,23 @@ static std::string formatObjCParamQualif
Result += "byref ";
if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Result += "oneway ";
+ if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
+ if (auto nullability = AttributedType::stripOuterNullability(Type)) {
+ switch (*nullability) {
+ case NullabilityKind::NonNull:
+ Result += "nonnull ";
+ break;
+
+ case NullabilityKind::Nullable:
+ Result += "nullable ";
+ break;
+
+ case NullabilityKind::Unspecified:
+ Result += "null_unspecified ";
+ break;
+ }
+ }
+ }
return Result;
}
@@ -2128,13 +2151,15 @@ static std::string FormatFunctionParamet
if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Result = Param->getIdentifier()->getName();
- Param->getType().getAsStringInternal(Result, Policy);
-
+ QualType Type = Param->getType();
if (ObjCMethodParam) {
- Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
- + Result + ")";
+ Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
+ Type);
+ Result += Type.getAsString(Policy) + ")";
if (Param->getIdentifier() && !SuppressName)
Result += Param->getIdentifier()->getName();
+ } else {
+ Type.getAsStringInternal(Result, Policy);
}
return Result;
}
@@ -2182,13 +2207,16 @@ static std::string FormatFunctionParamet
if (!ObjCMethodParam && Param->getIdentifier())
Result = Param->getIdentifier()->getName();
- Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
+ QualType Type = Param->getType().getUnqualifiedType();
if (ObjCMethodParam) {
- Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
- + Result + ")";
+ Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(),
+ Type);
+ Result += Type.getAsString(Policy) + Result + ")";
if (Param->getIdentifier())
Result += Param->getIdentifier()->getName();
+ } else {
+ Type.getAsStringInternal(Result, Policy);
}
return Result;
@@ -2762,9 +2790,10 @@ CodeCompletionResult::CreateCodeCompleti
if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Arg = FormatFunctionParameter(Policy, *P, true);
else {
- (*P)->getType().getAsStringInternal(Arg, Policy);
- Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
- + Arg + ")";
+ QualType Type = (*P)->getType();
+ Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
+ Type);
+ Arg += Type.getAsString(Policy) + ")";
if (IdentifierInfo *II = (*P)->getIdentifier())
if (DeclaringEntity || AllParametersAreInformative)
Arg += II->getName();
@@ -4858,6 +4887,12 @@ void Sema::CodeCompleteObjCPropertyFlags
Getter.AddPlaceholderChunk("method");
Results.AddResult(CodeCompletionResult(Getter.TakeString()));
}
+ if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
+ Results.AddResult(CodeCompletionResult("nonnull"));
+ Results.AddResult(CodeCompletionResult("nullable"));
+ Results.AddResult(CodeCompletionResult("null_unspecified"));
+ Results.AddResult(CodeCompletionResult("null_resettable"));
+ }
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter,
CodeCompletionContext::CCC_Other,
@@ -5107,6 +5142,11 @@ void Sema::CodeCompleteObjCPassingType(S
Results.AddResult("byref");
Results.AddResult("oneway");
}
+ if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
+ Results.AddResult("nonnull");
+ Results.AddResult("nullable");
+ Results.AddResult("null_unspecified");
+ }
// If we're completing the return type of an Objective-C method and the
// identifier IBAction refers to a macro, provide a completion item for
@@ -6279,7 +6319,7 @@ static void AddObjCPassingTypeChunk(Qual
const PrintingPolicy &Policy,
CodeCompletionBuilder &Builder) {
Builder.AddChunk(CodeCompletionString::CK_LeftParen);
- std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
+ std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
if (!Quals.empty())
Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
@@ -7018,7 +7058,12 @@ void Sema::CodeCompleteObjCMethodDecl(Sc
break;
// Add the parameter type.
- AddObjCPassingTypeChunk((*P)->getOriginalType(),
+ QualType ParamType;
+ if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
+ ParamType = (*P)->getType();
+ else
+ ParamType = (*P)->getOriginalType();
+ AddObjCPassingTypeChunk(ParamType,
(*P)->getObjCDeclQualifier(),
Context, Policy,
Builder);
Modified: cfe/trunk/test/Index/complete-method-decls.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-method-decls.m?rev=240159&r1=240158&r2=240159&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-method-decls.m (original)
+++ cfe/trunk/test/Index/complete-method-decls.m Fri Jun 19 13:27:52 2015
@@ -82,6 +82,14 @@ typedef A *MyObjectRef;
@end
@implementation I1
+-(void)foo {}
+ at end
+
+ at interface I2
+-(nonnull I2 *)produceI2:(nullable I2 *)i2;
+ at end
+
+ at implementation I2
-
@end
@@ -153,6 +161,8 @@ typedef A *MyObjectRef;
// CHECK-CCF: NotImplemented:{TypedText byref} (40)
// CHECK-CCF: NotImplemented:{TypedText in} (40)
// CHECK-CCF: NotImplemented:{TypedText inout} (40)
+// CHECK-CCF: NotImplemented:{TypedText nonnull} (40)
+// CHECK-CCF: NotImplemented:{TypedText nullable} (40)
// CHECK-CCF: NotImplemented:{TypedText oneway} (40)
// CHECK-CCF: NotImplemented:{TypedText out} (40)
// CHECK-CCF: NotImplemented:{TypedText unsigned} (50)
@@ -201,3 +211,6 @@ typedef A *MyObjectRef;
// FIXME: It should be "MyObject <P1> *""
// CHECK-CLASSTY: ObjCInstanceMethodDecl:{LeftParen (}{Text A<P1> *}{RightParen )}{TypedText meth2}
// CHECK-CLASSTY: ObjCInstanceMethodDecl:{LeftParen (}{Text MyObjectRef}{RightParen )}{TypedText meth3}
+
+// RUN: c-index-test -code-completion-at=%s:93:2 %s | FileCheck -check-prefix=CHECK-NULLABILITY %s
+// CHECK-NULLABILITY: ObjCInstanceMethodDecl:{LeftParen (}{Text nonnull }{Text I2 *}{RightParen )}{TypedText produceI2}{TypedText :}{LeftParen (}{Text nullable }{Text I2 *}{RightParen )}{Text i2} (40)
Modified: cfe/trunk/test/Index/complete-objc-message.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-objc-message.m?rev=240159&r1=240158&r2=240159&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-objc-message.m (original)
+++ cfe/trunk/test/Index/complete-objc-message.m Fri Jun 19 13:27:52 2015
@@ -189,6 +189,14 @@ void test_DO(DO *d, A* a) {
[d method:a aout:&a];
}
+ at interface Nullability
+- (nonnull A *)method:(nullable A *)param;
+ at end
+
+void test_Nullability(Nullability *n, A* a) {
+ [n method: a];
+}
+
// RUN: c-index-test -code-completion-at=%s:23:19 %s | FileCheck -check-prefix=CHECK-CC1 %s
// CHECK-CC1: {TypedText categoryClassMethod} (35)
// CHECK-CC1: {TypedText classMethod1:}{Placeholder (id)}{HorizontalSpace }{TypedText withKeyword:}{Placeholder (int)} (35)
@@ -335,3 +343,6 @@ void test_DO(DO *d, A* a) {
// RUN: c-index-test -code-completion-at=%s:189:6 %s | FileCheck -check-prefix=CHECK-DISTRIB-OBJECTS %s
// CHECK-DISTRIB-OBJECTS: ObjCInstanceMethodDecl:{ResultType void}{TypedText method:}{Placeholder (in bycopy A *)}{HorizontalSpace }{TypedText result:}{Placeholder (out byref A **)} (35)
+
+// RUN: c-index-test -code-completion-at=%s:197:6 %s | FileCheck -check-prefix=CHECK-NULLABLE %s
+// CHECK-NULLABLE: ObjCInstanceMethodDecl:{ResultType A * __nonnull}{TypedText method:}{Placeholder (nullable A *)}
Modified: cfe/trunk/test/Index/complete-property-flags.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-property-flags.m?rev=240159&r1=240158&r2=240159&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-property-flags.m (original)
+++ cfe/trunk/test/Index/complete-property-flags.m Fri Jun 19 13:27:52 2015
@@ -13,6 +13,10 @@
// CHECK-CC1-NEXT: {TypedText copy}
// CHECK-CC1-NEXT: {TypedText getter}{Text =}{Placeholder method}
// CHECK-CC1-NEXT: {TypedText nonatomic}
+// CHECK-CC1: {TypedText nonnull}
+// CHECK-CC1-NEXT: {TypedText null_resettable}
+// CHECK-CC1-NEXT: {TypedText null_unspecified}
+// CHECK-CC1-NEXT: {TypedText nullable}
// CHECK-CC1-NEXT: {TypedText readonly}
// CHECK-CC1-NEXT: {TypedText readwrite}
// CHECK-CC1-NEXT: {TypedText retain}
@@ -27,6 +31,10 @@
// CHECK-CC1-ARC-NEXT: {TypedText copy}
// CHECK-CC1-ARC-NEXT: {TypedText getter}{Text =}{Placeholder method}
// CHECK-CC1-ARC-NEXT: {TypedText nonatomic}
+// CHECK-CC1-ARC-NEXT: {TypedText nonnull}
+// CHECK-CC1-ARC-NEXT: {TypedText null_resettable}
+// CHECK-CC1-ARC-NEXT: {TypedText null_unspecified}
+// CHECK-CC1-ARC-NEXT: {TypedText nullable}
// CHECK-CC1-ARC-NEXT: {TypedText readonly}
// CHECK-CC1-ARC-NEXT: {TypedText readwrite}
// CHECK-CC1-ARC-NEXT: {TypedText retain}
@@ -38,6 +46,10 @@
// RUN: c-index-test -code-completion-at=%s:8:18 %s | FileCheck -check-prefix=CHECK-CC2 %s
// CHECK-CC2: {TypedText getter}{Text =}{Placeholder method}
// CHECK-CC2-NEXT: {TypedText nonatomic}
+// CHECK-CC2-NEXT: {TypedText nonnull}
+// CHECK-CC2-NEXT: {TypedText null_resettable}
+// CHECK-CC2-NEXT: {TypedText null_unspecified}
+// CHECK-CC2-NEXT: {TypedText nullable}
// CHECK-CC2-NEXT: {TypedText readonly}
// CHECK-CC2-NEXT: {TypedText readwrite}
// CHECK-CC2-NEXT: {TypedText setter}{Text =}{Placeholder method}
Modified: cfe/trunk/test/Index/complete-stmt.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/complete-stmt.c?rev=240159&r1=240158&r2=240159&view=diff
==============================================================================
--- cfe/trunk/test/Index/complete-stmt.c (original)
+++ cfe/trunk/test/Index/complete-stmt.c Fri Jun 19 13:27:52 2015
@@ -16,6 +16,8 @@ void f(int x) {
// CHECK-IF-ELSE-SIMPLE: NotImplemented:{TypedText else}{HorizontalSpace }{Text if}{HorizontalSpace }{LeftParen (}{Placeholder expression}{RightParen )} (40)
// RUN: c-index-test -code-completion-at=%s:6:1 %s | FileCheck -check-prefix=CHECK-STMT %s
+// CHECK-STMT: NotImplemented:{TypedText __nonnull} (50)
+// CHECK-STMT: NotImplemented:{TypedText __nullable} (50)
// CHECK-STMT: NotImplemented:{TypedText char} (50)
// CHECK-STMT: NotImplemented:{TypedText const} (50)
// CHECK-STMT: NotImplemented:{TypedText double} (50)
More information about the cfe-commits
mailing list