diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-06 17:30:22 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-06 17:30:22 +0000 |
commit | 719770dcfcb3987e8a2377dcca97955301445eb5 (patch) | |
tree | 1da28b7f8b75c29bbc67187c5c4c96423db57f14 | |
parent | 52d9ae3220c08fcbb80f213a364a88e4e0067242 (diff) |
Make code-completion for Objective-C message sends to "id" work in the
presence of precompiled headers by forcibly loading all of the
methods we know about from the PCH file before constructing our
code-completion list.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100535 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ExternalASTSource.h | 7 | ||||
-rw-r--r-- | include/clang/Frontend/PCHReader.h | 3 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 38 | ||||
-rw-r--r-- | test/Index/Inputs/complete-pch.h | 10 | ||||
-rw-r--r-- | test/Index/complete-pch.m | 26 |
6 files changed, 88 insertions, 4 deletions
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index b8d80bc897..79e44511d3 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -66,6 +66,13 @@ public: /// building a new declaration. virtual Decl *GetDecl(uint32_t ID) = 0; + /// \brief Resolve a selector ID into a selector. + virtual Selector GetSelector(uint32_t ID) = 0; + + /// \brief Returns the number of selectors known to the external AST + /// source. + virtual uint32_t GetNumKnownSelectors() = 0; + /// \brief Resolve the offset of a statement in the decl stream into a /// statement. /// diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 73c1bf4cce..e324228e92 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -688,6 +688,9 @@ public: Selector DecodeSelector(unsigned Idx); + virtual Selector GetSelector(uint32_t ID); + virtual uint32_t GetNumKnownSelectors(); + Selector GetSelector(const RecordData &Record, unsigned &Idx) { return DecodeSelector(Record[Idx++]); } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index b96c04d0a8..41e06661fa 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -2843,6 +2843,14 @@ Selector PCHReader::DecodeSelector(unsigned ID) { return SelectorsLoaded[Index]; } +Selector PCHReader::GetSelector(uint32_t ID) { + return DecodeSelector(ID); +} + +uint32_t PCHReader::GetNumKnownSelectors() { + return TotalNumSelectors + 1; +} + DeclarationName PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index d29cab4ca1..ac56fab9e8 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -13,6 +13,7 @@ #include "Sema.h" #include "Lookup.h" #include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/ExternalSemaSource.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/Lex/MacroInfo.h" @@ -2977,13 +2978,26 @@ void Sema::CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, else if (FName->isStr("id")) { // We're messaging "id" as a type; provide all class/factory methods. - // FIXME: Load the entire class method pool from the PCH file + // If we have an external source, load the entire class method + // pool from the PCH file. + if (ExternalSource) { + for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N; + ++I) { + Selector Sel = ExternalSource->GetSelector(I); + if (Sel.isNull() || FactoryMethodPool.count(Sel) || + InstanceMethodPool.count(Sel)) + continue; + + ReadMethodPool(Sel, /*isInstance=*/false); + } + } + for (llvm::DenseMap<Selector, ObjCMethodList>::iterator M = FactoryMethodPool.begin(), MEnd = FactoryMethodPool.end(); M != MEnd; ++M) { - for (ObjCMethodList *MethList = &M->second; MethList; + for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; MethList = MethList->Next) { if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, NumSelIdents)) @@ -3056,13 +3070,29 @@ void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver, } // Handle messages to "id". else if (ReceiverType->isObjCIdType()) { - // FIXME: Load the entire instance method pool from the PCH file + // We're messaging "id", so provide all instance methods we know + // about as code-completion results. + + // If we have an external source, load the entire class method + // pool from the PCH file. + if (ExternalSource) { + for (uint32_t I = 0, N = ExternalSource->GetNumKnownSelectors(); I != N; + ++I) { + Selector Sel = ExternalSource->GetSelector(I); + if (Sel.isNull() || InstanceMethodPool.count(Sel) || + FactoryMethodPool.count(Sel)) + continue; + + ReadMethodPool(Sel, /*isInstance=*/true); + } + } + for (llvm::DenseMap<Selector, ObjCMethodList>::iterator M = InstanceMethodPool.begin(), MEnd = InstanceMethodPool.end(); M != MEnd; ++M) { - for (ObjCMethodList *MethList = &M->second; MethList; + for (ObjCMethodList *MethList = &M->second; MethList && MethList->Method; MethList = MethList->Next) { if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, NumSelIdents)) diff --git a/test/Index/Inputs/complete-pch.h b/test/Index/Inputs/complete-pch.h new file mode 100644 index 0000000000..ddf5253c13 --- /dev/null +++ b/test/Index/Inputs/complete-pch.h @@ -0,0 +1,10 @@ +@interface A +- (int)instanceMethod1:(int)x; ++ (int)classMethod1:(double)d; +@end + +@interface B +- (int)instanceMethod2:(int)x; ++ (int)classMethod2:(float)f; +@end + diff --git a/test/Index/complete-pch.m b/test/Index/complete-pch.m new file mode 100644 index 0000000000..09192ae113 --- /dev/null +++ b/test/Index/complete-pch.m @@ -0,0 +1,26 @@ +// Note: the run lines follow their respective tests, since line/column +// matter in this test. + +@interface C +- (int)instanceMethod3:(int)x; ++ (int)classMethod3:(float)f; +@end + +void msg_id(id x) { + [id classMethod1:1.0]; + [x instanceMethod1:5]; +} + +// Build the precompiled header +// RUN: %clang -x objective-c-header -o %t.h.pch %S/Inputs/complete-pch.h + +// Run the actual tests +// RUN: c-index-test -code-completion-at=%s:10:7 -include %t.h %s | FileCheck -check-prefix=CHECK-CC1 %s +// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod1:}{Placeholder (double)d} +// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod2:}{Placeholder (float)f} +// CHECK-CC1: ObjCClassMethodDecl:{ResultType int}{TypedText classMethod3:}{Placeholder (float)f} + +// RUN: c-index-test -code-completion-at=%s:11:6 -include %t.h %s | FileCheck -check-prefix=CHECK-CC2 %s +// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod1:}{Placeholder (int)x} +// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod2:}{Placeholder (int)x} +// CHECK-CC2: ObjCInstanceMethodDecl:{ResultType int}{TypedText instanceMethod3:}{Placeholder (int)x} |