1198092Srdivacky//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===// 2198092Srdivacky// 3198092Srdivacky// The LLVM Compiler Infrastructure 4198092Srdivacky// 5198092Srdivacky// This file is distributed under the University of Illinois Open Source 6198092Srdivacky// License. See LICENSE.TXT for details. 7198092Srdivacky// 8198092Srdivacky//===----------------------------------------------------------------------===// 9198092Srdivacky// 10198092Srdivacky// This file defines the code-completion semantic actions. 11198092Srdivacky// 12198092Srdivacky//===----------------------------------------------------------------------===// 13212904Sdim#include "clang/Sema/SemaInternal.h" 14212904Sdim#include "clang/AST/DeclObjC.h" 15198092Srdivacky#include "clang/AST/ExprCXX.h" 16199482Srdivacky#include "clang/AST/ExprObjC.h" 17249423Sdim#include "clang/Basic/CharInfo.h" 18234353Sdim#include "clang/Lex/HeaderSearch.h" 19198893Srdivacky#include "clang/Lex/MacroInfo.h" 20198893Srdivacky#include "clang/Lex/Preprocessor.h" 21249423Sdim#include "clang/Sema/CodeCompleteConsumer.h" 22249423Sdim#include "clang/Sema/ExternalSemaSource.h" 23249423Sdim#include "clang/Sema/Lookup.h" 24249423Sdim#include "clang/Sema/Overload.h" 25249423Sdim#include "clang/Sema/Scope.h" 26249423Sdim#include "clang/Sema/ScopeInfo.h" 27218893Sdim#include "llvm/ADT/DenseSet.h" 28234353Sdim#include "llvm/ADT/SmallBitVector.h" 29198092Srdivacky#include "llvm/ADT/SmallPtrSet.h" 30234353Sdim#include "llvm/ADT/SmallString.h" 31198092Srdivacky#include "llvm/ADT/StringExtras.h" 32207619Srdivacky#include "llvm/ADT/StringSwitch.h" 33212904Sdim#include "llvm/ADT/Twine.h" 34198092Srdivacky#include <list> 35198092Srdivacky#include <map> 36198092Srdivacky#include <vector> 37198092Srdivacky 38198092Srdivackyusing namespace clang; 39212904Sdimusing namespace sema; 40198092Srdivacky 41198092Srdivackynamespace { 42198092Srdivacky /// \brief A container of code-completion results. 43198092Srdivacky class ResultBuilder { 44198092Srdivacky public: 45198092Srdivacky /// \brief The type of a name-lookup filter, which can be provided to the 46198092Srdivacky /// name-lookup routines to specify which declarations should be included in 47198092Srdivacky /// the result set (when it returns true) and which declarations should be 48198092Srdivacky /// filtered out (returns false). 49249423Sdim typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; 50198092Srdivacky 51212904Sdim typedef CodeCompletionResult Result; 52198092Srdivacky 53198092Srdivacky private: 54198092Srdivacky /// \brief The actual results we have found. 55198092Srdivacky std::vector<Result> Results; 56198092Srdivacky 57198092Srdivacky /// \brief A record of all of the declarations we have found and placed 58198092Srdivacky /// into the result set, used to ensure that no declaration ever gets into 59198092Srdivacky /// the result set twice. 60249423Sdim llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound; 61198092Srdivacky 62249423Sdim typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair; 63200583Srdivacky 64200583Srdivacky /// \brief An entry in the shadow map, which is optimized to store 65200583Srdivacky /// a single (declaration, index) mapping (the common case) but 66200583Srdivacky /// can also store a list of (declaration, index) mappings. 67200583Srdivacky class ShadowMapEntry { 68226633Sdim typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector; 69200583Srdivacky 70200583Srdivacky /// \brief Contains either the solitary NamedDecl * or a vector 71200583Srdivacky /// of (declaration, index) pairs. 72249423Sdim llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector; 73200583Srdivacky 74200583Srdivacky /// \brief When the entry contains a single declaration, this is 75200583Srdivacky /// the index associated with that entry. 76200583Srdivacky unsigned SingleDeclIndex; 77200583Srdivacky 78200583Srdivacky public: 79200583Srdivacky ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { } 80200583Srdivacky 81249423Sdim void Add(const NamedDecl *ND, unsigned Index) { 82200583Srdivacky if (DeclOrVector.isNull()) { 83200583Srdivacky // 0 - > 1 elements: just set the single element information. 84200583Srdivacky DeclOrVector = ND; 85200583Srdivacky SingleDeclIndex = Index; 86200583Srdivacky return; 87200583Srdivacky } 88200583Srdivacky 89249423Sdim if (const NamedDecl *PrevND = 90249423Sdim DeclOrVector.dyn_cast<const NamedDecl *>()) { 91200583Srdivacky // 1 -> 2 elements: create the vector of results and push in the 92200583Srdivacky // existing declaration. 93200583Srdivacky DeclIndexPairVector *Vec = new DeclIndexPairVector; 94200583Srdivacky Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); 95200583Srdivacky DeclOrVector = Vec; 96200583Srdivacky } 97200583Srdivacky 98200583Srdivacky // Add the new element to the end of the vector. 99200583Srdivacky DeclOrVector.get<DeclIndexPairVector*>()->push_back( 100200583Srdivacky DeclIndexPair(ND, Index)); 101200583Srdivacky } 102200583Srdivacky 103200583Srdivacky void Destroy() { 104200583Srdivacky if (DeclIndexPairVector *Vec 105200583Srdivacky = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) { 106200583Srdivacky delete Vec; 107200583Srdivacky DeclOrVector = ((NamedDecl *)0); 108200583Srdivacky } 109200583Srdivacky } 110200583Srdivacky 111200583Srdivacky // Iteration. 112200583Srdivacky class iterator; 113200583Srdivacky iterator begin() const; 114200583Srdivacky iterator end() const; 115200583Srdivacky }; 116200583Srdivacky 117198092Srdivacky /// \brief A mapping from declaration names to the declarations that have 118198092Srdivacky /// this name within a particular scope and their index within the list of 119198092Srdivacky /// results. 120200583Srdivacky typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; 121198092Srdivacky 122198092Srdivacky /// \brief The semantic analysis object for which results are being 123198092Srdivacky /// produced. 124198092Srdivacky Sema &SemaRef; 125218893Sdim 126218893Sdim /// \brief The allocator used to allocate new code-completion strings. 127218893Sdim CodeCompletionAllocator &Allocator; 128234353Sdim 129234353Sdim CodeCompletionTUInfo &CCTUInfo; 130198092Srdivacky 131198092Srdivacky /// \brief If non-NULL, a filter function used to remove any code-completion 132198092Srdivacky /// results that are not desirable. 133198092Srdivacky LookupFilter Filter; 134202379Srdivacky 135202379Srdivacky /// \brief Whether we should allow declarations as 136202379Srdivacky /// nested-name-specifiers that would otherwise be filtered out. 137202379Srdivacky bool AllowNestedNameSpecifiers; 138202379Srdivacky 139210299Sed /// \brief If set, the type that we would prefer our resulting value 140210299Sed /// declarations to have. 141210299Sed /// 142210299Sed /// Closely matching the preferred type gives a boost to a result's 143210299Sed /// priority. 144210299Sed CanQualType PreferredType; 145210299Sed 146198092Srdivacky /// \brief A list of shadow maps, which is used to model name hiding at 147198092Srdivacky /// different levels of, e.g., the inheritance hierarchy. 148198092Srdivacky std::list<ShadowMap> ShadowMaps; 149198092Srdivacky 150212904Sdim /// \brief If we're potentially referring to a C++ member function, the set 151212904Sdim /// of qualifiers applied to the object type. 152212904Sdim Qualifiers ObjectTypeQualifiers; 153212904Sdim 154212904Sdim /// \brief Whether the \p ObjectTypeQualifiers field is active. 155212904Sdim bool HasObjectTypeQualifiers; 156212904Sdim 157212904Sdim /// \brief The selector that we prefer. 158212904Sdim Selector PreferredSelector; 159212904Sdim 160218893Sdim /// \brief The completion context in which we are gathering results. 161218893Sdim CodeCompletionContext CompletionContext; 162218893Sdim 163239462Sdim /// \brief If we are in an instance method definition, the \@implementation 164218893Sdim /// object. 165218893Sdim ObjCImplementationDecl *ObjCImplementation; 166249423Sdim 167218893Sdim void AdjustResultPriorityForDecl(Result &R); 168210299Sed 169218893Sdim void MaybeAddConstructorResults(Result R); 170218893Sdim 171198092Srdivacky public: 172218893Sdim explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, 173234353Sdim CodeCompletionTUInfo &CCTUInfo, 174218893Sdim const CodeCompletionContext &CompletionContext, 175218893Sdim LookupFilter Filter = 0) 176234353Sdim : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo), 177234353Sdim Filter(Filter), 178218893Sdim AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false), 179218893Sdim CompletionContext(CompletionContext), 180218893Sdim ObjCImplementation(0) 181218893Sdim { 182218893Sdim // If this is an Objective-C instance method definition, dig out the 183218893Sdim // corresponding implementation. 184218893Sdim switch (CompletionContext.getKind()) { 185218893Sdim case CodeCompletionContext::CCC_Expression: 186218893Sdim case CodeCompletionContext::CCC_ObjCMessageReceiver: 187218893Sdim case CodeCompletionContext::CCC_ParenthesizedExpression: 188218893Sdim case CodeCompletionContext::CCC_Statement: 189218893Sdim case CodeCompletionContext::CCC_Recovery: 190218893Sdim if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) 191218893Sdim if (Method->isInstanceMethod()) 192218893Sdim if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) 193218893Sdim ObjCImplementation = Interface->getImplementation(); 194218893Sdim break; 195218893Sdim 196218893Sdim default: 197218893Sdim break; 198218893Sdim } 199218893Sdim } 200249423Sdim 201249423Sdim /// \brief Determine the priority for a reference to the given declaration. 202249423Sdim unsigned getBasePriority(const NamedDecl *D); 203249423Sdim 204208600Srdivacky /// \brief Whether we should include code patterns in the completion 205208600Srdivacky /// results. 206208600Srdivacky bool includeCodePatterns() const { 207208600Srdivacky return SemaRef.CodeCompleter && 208212904Sdim SemaRef.CodeCompleter->includeCodePatterns(); 209208600Srdivacky } 210208600Srdivacky 211198092Srdivacky /// \brief Set the filter used for code-completion results. 212198092Srdivacky void setFilter(LookupFilter Filter) { 213198092Srdivacky this->Filter = Filter; 214198092Srdivacky } 215198092Srdivacky 216198092Srdivacky Result *data() { return Results.empty()? 0 : &Results.front(); } 217198092Srdivacky unsigned size() const { return Results.size(); } 218198092Srdivacky bool empty() const { return Results.empty(); } 219198092Srdivacky 220210299Sed /// \brief Specify the preferred type. 221210299Sed void setPreferredType(QualType T) { 222210299Sed PreferredType = SemaRef.Context.getCanonicalType(T); 223210299Sed } 224210299Sed 225212904Sdim /// \brief Set the cv-qualifiers on the object type, for us in filtering 226212904Sdim /// calls to member functions. 227212904Sdim /// 228212904Sdim /// When there are qualifiers in this set, they will be used to filter 229212904Sdim /// out member functions that aren't available (because there will be a 230212904Sdim /// cv-qualifier mismatch) or prefer functions with an exact qualifier 231212904Sdim /// match. 232212904Sdim void setObjectTypeQualifiers(Qualifiers Quals) { 233212904Sdim ObjectTypeQualifiers = Quals; 234212904Sdim HasObjectTypeQualifiers = true; 235212904Sdim } 236212904Sdim 237212904Sdim /// \brief Set the preferred selector. 238212904Sdim /// 239212904Sdim /// When an Objective-C method declaration result is added, and that 240212904Sdim /// method's selector matches this preferred selector, we give that method 241212904Sdim /// a slight priority boost. 242212904Sdim void setPreferredSelector(Selector Sel) { 243212904Sdim PreferredSelector = Sel; 244212904Sdim } 245218893Sdim 246218893Sdim /// \brief Retrieve the code-completion context for which results are 247218893Sdim /// being collected. 248218893Sdim const CodeCompletionContext &getCompletionContext() const { 249218893Sdim return CompletionContext; 250218893Sdim } 251212904Sdim 252202379Srdivacky /// \brief Specify whether nested-name-specifiers are allowed. 253202379Srdivacky void allowNestedNameSpecifiers(bool Allow = true) { 254202379Srdivacky AllowNestedNameSpecifiers = Allow; 255202379Srdivacky } 256202379Srdivacky 257218893Sdim /// \brief Return the semantic analysis object for which we are collecting 258218893Sdim /// code completion results. 259218893Sdim Sema &getSema() const { return SemaRef; } 260218893Sdim 261218893Sdim /// \brief Retrieve the allocator used to allocate code completion strings. 262218893Sdim CodeCompletionAllocator &getAllocator() const { return Allocator; } 263234353Sdim 264234353Sdim CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } 265218893Sdim 266202379Srdivacky /// \brief Determine whether the given declaration is at all interesting 267202379Srdivacky /// as a code-completion result. 268202379Srdivacky /// 269202379Srdivacky /// \param ND the declaration that we are inspecting. 270202379Srdivacky /// 271202379Srdivacky /// \param AsNestedNameSpecifier will be set true if this declaration is 272202379Srdivacky /// only interesting when it is a nested-name-specifier. 273249423Sdim bool isInterestingDecl(const NamedDecl *ND, 274249423Sdim bool &AsNestedNameSpecifier) const; 275202379Srdivacky 276202379Srdivacky /// \brief Check whether the result is hidden by the Hiding declaration. 277202379Srdivacky /// 278202379Srdivacky /// \returns true if the result is hidden and cannot be found, false if 279202379Srdivacky /// the hidden result could still be found. When false, \p R may be 280202379Srdivacky /// modified to describe how the result can be found (e.g., via extra 281202379Srdivacky /// qualification). 282202379Srdivacky bool CheckHiddenResult(Result &R, DeclContext *CurContext, 283249423Sdim const NamedDecl *Hiding); 284202379Srdivacky 285198092Srdivacky /// \brief Add a new result to this result set (if it isn't already in one 286198092Srdivacky /// of the shadow maps), or replace an existing result (for, e.g., a 287198092Srdivacky /// redeclaration). 288198092Srdivacky /// 289234353Sdim /// \param R the result to add (if it is unique). 290198092Srdivacky /// 291234353Sdim /// \param CurContext the context in which this result will be named. 292198092Srdivacky void MaybeAddResult(Result R, DeclContext *CurContext = 0); 293198092Srdivacky 294202379Srdivacky /// \brief Add a new result to this result set, where we already know 295202379Srdivacky /// the hiding declation (if any). 296202379Srdivacky /// 297202379Srdivacky /// \param R the result to add (if it is unique). 298202379Srdivacky /// 299202379Srdivacky /// \param CurContext the context in which this result will be named. 300202379Srdivacky /// 301202379Srdivacky /// \param Hiding the declaration that hides the result. 302202379Srdivacky /// 303202379Srdivacky /// \param InBaseClass whether the result was found in a base 304202379Srdivacky /// class of the searched context. 305202379Srdivacky void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, 306202379Srdivacky bool InBaseClass); 307202379Srdivacky 308202379Srdivacky /// \brief Add a new non-declaration result to this result set. 309202379Srdivacky void AddResult(Result R); 310202379Srdivacky 311198092Srdivacky /// \brief Enter into a new scope. 312198092Srdivacky void EnterNewScope(); 313198092Srdivacky 314198092Srdivacky /// \brief Exit from the current scope. 315198092Srdivacky void ExitScope(); 316198092Srdivacky 317199482Srdivacky /// \brief Ignore this declaration, if it is seen again. 318249423Sdim void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } 319199482Srdivacky 320198092Srdivacky /// \name Name lookup predicates 321198092Srdivacky /// 322198092Srdivacky /// These predicates can be passed to the name lookup functions to filter the 323198092Srdivacky /// results of name lookup. All of the predicates have the same type, so that 324198092Srdivacky /// 325198092Srdivacky //@{ 326249423Sdim bool IsOrdinaryName(const NamedDecl *ND) const; 327249423Sdim bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; 328249423Sdim bool IsIntegralConstantValue(const NamedDecl *ND) const; 329249423Sdim bool IsOrdinaryNonValueName(const NamedDecl *ND) const; 330249423Sdim bool IsNestedNameSpecifier(const NamedDecl *ND) const; 331249423Sdim bool IsEnum(const NamedDecl *ND) const; 332249423Sdim bool IsClassOrStruct(const NamedDecl *ND) const; 333249423Sdim bool IsUnion(const NamedDecl *ND) const; 334249423Sdim bool IsNamespace(const NamedDecl *ND) const; 335249423Sdim bool IsNamespaceOrAlias(const NamedDecl *ND) const; 336249423Sdim bool IsType(const NamedDecl *ND) const; 337249423Sdim bool IsMember(const NamedDecl *ND) const; 338249423Sdim bool IsObjCIvar(const NamedDecl *ND) const; 339249423Sdim bool IsObjCMessageReceiver(const NamedDecl *ND) const; 340249423Sdim bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; 341249423Sdim bool IsObjCCollection(const NamedDecl *ND) const; 342249423Sdim bool IsImpossibleToSatisfy(const NamedDecl *ND) const; 343198092Srdivacky //@} 344198092Srdivacky }; 345198092Srdivacky} 346198092Srdivacky 347200583Srdivackyclass ResultBuilder::ShadowMapEntry::iterator { 348249423Sdim llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator; 349200583Srdivacky unsigned SingleDeclIndex; 350200583Srdivacky 351200583Srdivackypublic: 352200583Srdivacky typedef DeclIndexPair value_type; 353200583Srdivacky typedef value_type reference; 354200583Srdivacky typedef std::ptrdiff_t difference_type; 355200583Srdivacky typedef std::input_iterator_tag iterator_category; 356200583Srdivacky 357200583Srdivacky class pointer { 358200583Srdivacky DeclIndexPair Value; 359200583Srdivacky 360200583Srdivacky public: 361200583Srdivacky pointer(const DeclIndexPair &Value) : Value(Value) { } 362200583Srdivacky 363200583Srdivacky const DeclIndexPair *operator->() const { 364200583Srdivacky return &Value; 365200583Srdivacky } 366200583Srdivacky }; 367200583Srdivacky 368200583Srdivacky iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { } 369200583Srdivacky 370249423Sdim iterator(const NamedDecl *SingleDecl, unsigned Index) 371200583Srdivacky : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { } 372200583Srdivacky 373200583Srdivacky iterator(const DeclIndexPair *Iterator) 374200583Srdivacky : DeclOrIterator(Iterator), SingleDeclIndex(0) { } 375200583Srdivacky 376200583Srdivacky iterator &operator++() { 377249423Sdim if (DeclOrIterator.is<const NamedDecl *>()) { 378200583Srdivacky DeclOrIterator = (NamedDecl *)0; 379200583Srdivacky SingleDeclIndex = 0; 380200583Srdivacky return *this; 381200583Srdivacky } 382200583Srdivacky 383200583Srdivacky const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>(); 384200583Srdivacky ++I; 385200583Srdivacky DeclOrIterator = I; 386200583Srdivacky return *this; 387200583Srdivacky } 388200583Srdivacky 389218893Sdim /*iterator operator++(int) { 390200583Srdivacky iterator tmp(*this); 391200583Srdivacky ++(*this); 392200583Srdivacky return tmp; 393218893Sdim }*/ 394200583Srdivacky 395200583Srdivacky reference operator*() const { 396249423Sdim if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>()) 397200583Srdivacky return reference(ND, SingleDeclIndex); 398200583Srdivacky 399200583Srdivacky return *DeclOrIterator.get<const DeclIndexPair*>(); 400200583Srdivacky } 401200583Srdivacky 402200583Srdivacky pointer operator->() const { 403200583Srdivacky return pointer(**this); 404200583Srdivacky } 405200583Srdivacky 406200583Srdivacky friend bool operator==(const iterator &X, const iterator &Y) { 407200583Srdivacky return X.DeclOrIterator.getOpaqueValue() 408200583Srdivacky == Y.DeclOrIterator.getOpaqueValue() && 409200583Srdivacky X.SingleDeclIndex == Y.SingleDeclIndex; 410200583Srdivacky } 411200583Srdivacky 412200583Srdivacky friend bool operator!=(const iterator &X, const iterator &Y) { 413200583Srdivacky return !(X == Y); 414200583Srdivacky } 415200583Srdivacky}; 416200583Srdivacky 417200583SrdivackyResultBuilder::ShadowMapEntry::iterator 418200583SrdivackyResultBuilder::ShadowMapEntry::begin() const { 419200583Srdivacky if (DeclOrVector.isNull()) 420200583Srdivacky return iterator(); 421200583Srdivacky 422249423Sdim if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>()) 423200583Srdivacky return iterator(ND, SingleDeclIndex); 424200583Srdivacky 425200583Srdivacky return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin()); 426200583Srdivacky} 427200583Srdivacky 428200583SrdivackyResultBuilder::ShadowMapEntry::iterator 429200583SrdivackyResultBuilder::ShadowMapEntry::end() const { 430249423Sdim if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull()) 431200583Srdivacky return iterator(); 432200583Srdivacky 433200583Srdivacky return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end()); 434200583Srdivacky} 435200583Srdivacky 436198092Srdivacky/// \brief Compute the qualification required to get from the current context 437198092Srdivacky/// (\p CurContext) to the target context (\p TargetContext). 438198092Srdivacky/// 439198092Srdivacky/// \param Context the AST context in which the qualification will be used. 440198092Srdivacky/// 441198092Srdivacky/// \param CurContext the context where an entity is being named, which is 442198092Srdivacky/// typically based on the current scope. 443198092Srdivacky/// 444198092Srdivacky/// \param TargetContext the context in which the named entity actually 445198092Srdivacky/// resides. 446198092Srdivacky/// 447198092Srdivacky/// \returns a nested name specifier that refers into the target context, or 448198092Srdivacky/// NULL if no qualification is needed. 449198092Srdivackystatic NestedNameSpecifier * 450198092SrdivackygetRequiredQualification(ASTContext &Context, 451249423Sdim const DeclContext *CurContext, 452249423Sdim const DeclContext *TargetContext) { 453249423Sdim SmallVector<const DeclContext *, 4> TargetParents; 454198092Srdivacky 455249423Sdim for (const DeclContext *CommonAncestor = TargetContext; 456198092Srdivacky CommonAncestor && !CommonAncestor->Encloses(CurContext); 457198092Srdivacky CommonAncestor = CommonAncestor->getLookupParent()) { 458198092Srdivacky if (CommonAncestor->isTransparentContext() || 459198092Srdivacky CommonAncestor->isFunctionOrMethod()) 460198092Srdivacky continue; 461198092Srdivacky 462198092Srdivacky TargetParents.push_back(CommonAncestor); 463198092Srdivacky } 464198092Srdivacky 465198092Srdivacky NestedNameSpecifier *Result = 0; 466198092Srdivacky while (!TargetParents.empty()) { 467249423Sdim const DeclContext *Parent = TargetParents.back(); 468198092Srdivacky TargetParents.pop_back(); 469198092Srdivacky 470249423Sdim if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) { 471212904Sdim if (!Namespace->getIdentifier()) 472212904Sdim continue; 473212904Sdim 474198092Srdivacky Result = NestedNameSpecifier::Create(Context, Result, Namespace); 475212904Sdim } 476249423Sdim else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent)) 477198092Srdivacky Result = NestedNameSpecifier::Create(Context, Result, 478198092Srdivacky false, 479198092Srdivacky Context.getTypeDeclType(TD).getTypePtr()); 480199482Srdivacky } 481198092Srdivacky return Result; 482198092Srdivacky} 483198092Srdivacky 484249423Sdimbool ResultBuilder::isInterestingDecl(const NamedDecl *ND, 485202379Srdivacky bool &AsNestedNameSpecifier) const { 486202379Srdivacky AsNestedNameSpecifier = false; 487198092Srdivacky 488202379Srdivacky ND = ND->getUnderlyingDecl(); 489202379Srdivacky unsigned IDNS = ND->getIdentifierNamespace(); 490202379Srdivacky 491198092Srdivacky // Skip unnamed entities. 492202379Srdivacky if (!ND->getDeclName()) 493202379Srdivacky return false; 494198092Srdivacky 495198092Srdivacky // Friend declarations and declarations introduced due to friends are never 496198092Srdivacky // added as results. 497205219Srdivacky if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend)) 498202379Srdivacky return false; 499202379Srdivacky 500200583Srdivacky // Class template (partial) specializations are never added as results. 501202379Srdivacky if (isa<ClassTemplateSpecializationDecl>(ND) || 502202379Srdivacky isa<ClassTemplatePartialSpecializationDecl>(ND)) 503202379Srdivacky return false; 504198092Srdivacky 505200583Srdivacky // Using declarations themselves are never added as results. 506202379Srdivacky if (isa<UsingDecl>(ND)) 507202379Srdivacky return false; 508202379Srdivacky 509202379Srdivacky // Some declarations have reserved names that we don't want to ever show. 510202379Srdivacky if (const IdentifierInfo *Id = ND->getIdentifier()) { 511198092Srdivacky // __va_list_tag is a freak of nature. Find it and skip it. 512198092Srdivacky if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list")) 513202379Srdivacky return false; 514198092Srdivacky 515198092Srdivacky // Filter out names reserved for the implementation (C99 7.1.3, 516210299Sed // C++ [lib.global.names]) if they come from a system header. 517198398Srdivacky // 518198398Srdivacky // FIXME: Add predicate for this. 519198092Srdivacky if (Id->getLength() >= 2) { 520198398Srdivacky const char *Name = Id->getNameStart(); 521198092Srdivacky if (Name[0] == '_' && 522210299Sed (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) && 523210299Sed (ND->getLocation().isInvalid() || 524210299Sed SemaRef.SourceMgr.isInSystemHeader( 525210299Sed SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))) 526202379Srdivacky return false; 527198092Srdivacky } 528198092Srdivacky } 529218893Sdim 530212904Sdim if (Filter == &ResultBuilder::IsNestedNameSpecifier || 531212904Sdim ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) && 532212904Sdim Filter != &ResultBuilder::IsNamespace && 533218893Sdim Filter != &ResultBuilder::IsNamespaceOrAlias && 534218893Sdim Filter != 0)) 535212904Sdim AsNestedNameSpecifier = true; 536212904Sdim 537198092Srdivacky // Filter out any unwanted results. 538202379Srdivacky if (Filter && !(this->*Filter)(ND)) { 539202379Srdivacky // Check whether it is interesting as a nested-name-specifier. 540234353Sdim if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && 541202379Srdivacky IsNestedNameSpecifier(ND) && 542202379Srdivacky (Filter != &ResultBuilder::IsMember || 543202379Srdivacky (isa<CXXRecordDecl>(ND) && 544202379Srdivacky cast<CXXRecordDecl>(ND)->isInjectedClassName()))) { 545202379Srdivacky AsNestedNameSpecifier = true; 546202379Srdivacky return true; 547202379Srdivacky } 548202379Srdivacky 549202379Srdivacky return false; 550212904Sdim } 551202379Srdivacky // ... then it must be interesting! 552202379Srdivacky return true; 553202379Srdivacky} 554202379Srdivacky 555202379Srdivackybool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, 556249423Sdim const NamedDecl *Hiding) { 557202379Srdivacky // In C, there is no way to refer to a hidden name. 558202379Srdivacky // FIXME: This isn't true; we can find a tag name hidden by an ordinary 559202379Srdivacky // name if we introduce the tag type. 560234353Sdim if (!SemaRef.getLangOpts().CPlusPlus) 561202379Srdivacky return true; 562202379Srdivacky 563249423Sdim const DeclContext *HiddenCtx = 564249423Sdim R.Declaration->getDeclContext()->getRedeclContext(); 565202379Srdivacky 566202379Srdivacky // There is no way to qualify a name declared in a function or method. 567202379Srdivacky if (HiddenCtx->isFunctionOrMethod()) 568202379Srdivacky return true; 569202379Srdivacky 570212904Sdim if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext()) 571202379Srdivacky return true; 572202379Srdivacky 573202379Srdivacky // We can refer to the result with the appropriate qualification. Do it. 574202379Srdivacky R.Hidden = true; 575202379Srdivacky R.QualifierIsInformative = false; 576202379Srdivacky 577202379Srdivacky if (!R.Qualifier) 578202379Srdivacky R.Qualifier = getRequiredQualification(SemaRef.Context, 579202379Srdivacky CurContext, 580202379Srdivacky R.Declaration->getDeclContext()); 581202379Srdivacky return false; 582202379Srdivacky} 583202379Srdivacky 584210299Sed/// \brief A simplified classification of types used to determine whether two 585210299Sed/// types are "similar enough" when adjusting priorities. 586212904SdimSimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { 587210299Sed switch (T->getTypeClass()) { 588210299Sed case Type::Builtin: 589210299Sed switch (cast<BuiltinType>(T)->getKind()) { 590210299Sed case BuiltinType::Void: 591210299Sed return STC_Void; 592210299Sed 593210299Sed case BuiltinType::NullPtr: 594210299Sed return STC_Pointer; 595210299Sed 596210299Sed case BuiltinType::Overload: 597210299Sed case BuiltinType::Dependent: 598210299Sed return STC_Other; 599210299Sed 600210299Sed case BuiltinType::ObjCId: 601210299Sed case BuiltinType::ObjCClass: 602210299Sed case BuiltinType::ObjCSel: 603210299Sed return STC_ObjectiveC; 604210299Sed 605210299Sed default: 606210299Sed return STC_Arithmetic; 607210299Sed } 608234353Sdim 609210299Sed case Type::Complex: 610210299Sed return STC_Arithmetic; 611210299Sed 612210299Sed case Type::Pointer: 613210299Sed return STC_Pointer; 614210299Sed 615210299Sed case Type::BlockPointer: 616210299Sed return STC_Block; 617210299Sed 618210299Sed case Type::LValueReference: 619210299Sed case Type::RValueReference: 620210299Sed return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType()); 621210299Sed 622210299Sed case Type::ConstantArray: 623210299Sed case Type::IncompleteArray: 624210299Sed case Type::VariableArray: 625210299Sed case Type::DependentSizedArray: 626210299Sed return STC_Array; 627210299Sed 628210299Sed case Type::DependentSizedExtVector: 629210299Sed case Type::Vector: 630210299Sed case Type::ExtVector: 631210299Sed return STC_Arithmetic; 632210299Sed 633210299Sed case Type::FunctionProto: 634210299Sed case Type::FunctionNoProto: 635210299Sed return STC_Function; 636210299Sed 637210299Sed case Type::Record: 638210299Sed return STC_Record; 639210299Sed 640210299Sed case Type::Enum: 641210299Sed return STC_Arithmetic; 642210299Sed 643210299Sed case Type::ObjCObject: 644210299Sed case Type::ObjCInterface: 645210299Sed case Type::ObjCObjectPointer: 646210299Sed return STC_ObjectiveC; 647210299Sed 648210299Sed default: 649210299Sed return STC_Other; 650210299Sed } 651210299Sed} 652210299Sed 653210299Sed/// \brief Get the type that a given expression will have if this declaration 654210299Sed/// is used as an expression in its "typical" code-completion form. 655249423SdimQualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { 656210299Sed ND = cast<NamedDecl>(ND->getUnderlyingDecl()); 657210299Sed 658249423Sdim if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND)) 659210299Sed return C.getTypeDeclType(Type); 660249423Sdim if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) 661210299Sed return C.getObjCInterfaceType(Iface); 662210299Sed 663210299Sed QualType T; 664249423Sdim if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) 665210299Sed T = Function->getCallResultType(); 666249423Sdim else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) 667210299Sed T = Method->getSendResultType(); 668249423Sdim else if (const FunctionTemplateDecl *FunTmpl = 669249423Sdim dyn_cast<FunctionTemplateDecl>(ND)) 670210299Sed T = FunTmpl->getTemplatedDecl()->getCallResultType(); 671249423Sdim else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) 672210299Sed T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); 673249423Sdim else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) 674210299Sed T = Property->getType(); 675249423Sdim else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) 676210299Sed T = Value->getType(); 677210299Sed else 678210299Sed return QualType(); 679221345Sdim 680221345Sdim // Dig through references, function pointers, and block pointers to 681221345Sdim // get down to the likely type of an expression when the entity is 682221345Sdim // used. 683221345Sdim do { 684221345Sdim if (const ReferenceType *Ref = T->getAs<ReferenceType>()) { 685221345Sdim T = Ref->getPointeeType(); 686221345Sdim continue; 687221345Sdim } 688221345Sdim 689221345Sdim if (const PointerType *Pointer = T->getAs<PointerType>()) { 690221345Sdim if (Pointer->getPointeeType()->isFunctionType()) { 691221345Sdim T = Pointer->getPointeeType(); 692221345Sdim continue; 693221345Sdim } 694221345Sdim 695221345Sdim break; 696221345Sdim } 697221345Sdim 698221345Sdim if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) { 699221345Sdim T = Block->getPointeeType(); 700221345Sdim continue; 701221345Sdim } 702221345Sdim 703221345Sdim if (const FunctionType *Function = T->getAs<FunctionType>()) { 704221345Sdim T = Function->getResultType(); 705221345Sdim continue; 706221345Sdim } 707221345Sdim 708221345Sdim break; 709221345Sdim } while (true); 710221345Sdim 711221345Sdim return T; 712210299Sed} 713210299Sed 714249423Sdimunsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { 715249423Sdim if (!ND) 716249423Sdim return CCP_Unlikely; 717249423Sdim 718249423Sdim // Context-based decisions. 719249423Sdim const DeclContext *DC = ND->getDeclContext()->getRedeclContext(); 720249423Sdim if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) { 721249423Sdim // _cmd is relatively rare 722249423Sdim if (const ImplicitParamDecl *ImplicitParam = 723249423Sdim dyn_cast<ImplicitParamDecl>(ND)) 724249423Sdim if (ImplicitParam->getIdentifier() && 725249423Sdim ImplicitParam->getIdentifier()->isStr("_cmd")) 726249423Sdim return CCP_ObjC_cmd; 727249423Sdim 728249423Sdim return CCP_LocalDeclaration; 729249423Sdim } 730249423Sdim if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) 731249423Sdim return CCP_MemberDeclaration; 732249423Sdim 733249423Sdim // Content-based decisions. 734249423Sdim if (isa<EnumConstantDecl>(ND)) 735249423Sdim return CCP_Constant; 736249423Sdim 737249423Sdim // Use CCP_Type for type declarations unless we're in a statement, Objective-C 738249423Sdim // message receiver, or parenthesized expression context. There, it's as 739249423Sdim // likely that the user will want to write a type as other declarations. 740249423Sdim if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) && 741249423Sdim !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement || 742249423Sdim CompletionContext.getKind() 743249423Sdim == CodeCompletionContext::CCC_ObjCMessageReceiver || 744249423Sdim CompletionContext.getKind() 745249423Sdim == CodeCompletionContext::CCC_ParenthesizedExpression)) 746249423Sdim return CCP_Type; 747249423Sdim 748249423Sdim return CCP_Declaration; 749249423Sdim} 750249423Sdim 751218893Sdimvoid ResultBuilder::AdjustResultPriorityForDecl(Result &R) { 752218893Sdim // If this is an Objective-C method declaration whose selector matches our 753218893Sdim // preferred selector, give it a priority boost. 754218893Sdim if (!PreferredSelector.isNull()) 755249423Sdim if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) 756218893Sdim if (PreferredSelector == Method->getSelector()) 757218893Sdim R.Priority += CCD_SelectorMatch; 758210299Sed 759218893Sdim // If we have a preferred type, adjust the priority for results with exactly- 760218893Sdim // matching or nearly-matching types. 761218893Sdim if (!PreferredType.isNull()) { 762218893Sdim QualType T = getDeclUsageType(SemaRef.Context, R.Declaration); 763218893Sdim if (!T.isNull()) { 764218893Sdim CanQualType TC = SemaRef.Context.getCanonicalType(T); 765218893Sdim // Check for exactly-matching types (modulo qualifiers). 766218893Sdim if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) 767218893Sdim R.Priority /= CCF_ExactTypeMatch; 768218893Sdim // Check for nearly-matching types, based on classification of each. 769218893Sdim else if ((getSimplifiedTypeClass(PreferredType) 770210299Sed == getSimplifiedTypeClass(TC)) && 771218893Sdim !(PreferredType->isEnumeralType() && TC->isEnumeralType())) 772218893Sdim R.Priority /= CCF_SimilarTypeMatch; 773218893Sdim } 774218893Sdim } 775210299Sed} 776210299Sed 777218893Sdimvoid ResultBuilder::MaybeAddConstructorResults(Result R) { 778234353Sdim if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration || 779218893Sdim !CompletionContext.wantConstructorResults()) 780218893Sdim return; 781218893Sdim 782218893Sdim ASTContext &Context = SemaRef.Context; 783249423Sdim const NamedDecl *D = R.Declaration; 784249423Sdim const CXXRecordDecl *Record = 0; 785249423Sdim if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) 786218893Sdim Record = ClassTemplate->getTemplatedDecl(); 787218893Sdim else if ((Record = dyn_cast<CXXRecordDecl>(D))) { 788218893Sdim // Skip specializations and partial specializations. 789218893Sdim if (isa<ClassTemplateSpecializationDecl>(Record)) 790218893Sdim return; 791218893Sdim } else { 792218893Sdim // There are no constructors here. 793218893Sdim return; 794218893Sdim } 795218893Sdim 796218893Sdim Record = Record->getDefinition(); 797218893Sdim if (!Record) 798218893Sdim return; 799218893Sdim 800218893Sdim 801218893Sdim QualType RecordTy = Context.getTypeDeclType(Record); 802218893Sdim DeclarationName ConstructorName 803218893Sdim = Context.DeclarationNames.getCXXConstructorName( 804218893Sdim Context.getCanonicalType(RecordTy)); 805249423Sdim DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName); 806249423Sdim for (DeclContext::lookup_const_iterator I = Ctors.begin(), 807249423Sdim E = Ctors.end(); 808249423Sdim I != E; ++I) { 809249423Sdim R.Declaration = *I; 810218893Sdim R.CursorKind = getCursorKindForDecl(R.Declaration); 811218893Sdim Results.push_back(R); 812218893Sdim } 813218893Sdim} 814218893Sdim 815202379Srdivackyvoid ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { 816202379Srdivacky assert(!ShadowMaps.empty() && "Must enter into a results scope"); 817202379Srdivacky 818202379Srdivacky if (R.Kind != Result::RK_Declaration) { 819202379Srdivacky // For non-declaration results, just add the result. 820202379Srdivacky Results.push_back(R); 821198092Srdivacky return; 822202379Srdivacky } 823202379Srdivacky 824202379Srdivacky // Look through using declarations. 825249423Sdim if (const UsingShadowDecl *Using = 826249423Sdim dyn_cast<UsingShadowDecl>(R.Declaration)) { 827249423Sdim MaybeAddResult(Result(Using->getTargetDecl(), 828249423Sdim getBasePriority(Using->getTargetDecl()), 829249423Sdim R.Qualifier), 830249423Sdim CurContext); 831202379Srdivacky return; 832202379Srdivacky } 833198092Srdivacky 834249423Sdim const Decl *CanonDecl = R.Declaration->getCanonicalDecl(); 835202379Srdivacky unsigned IDNS = CanonDecl->getIdentifierNamespace(); 836202379Srdivacky 837202379Srdivacky bool AsNestedNameSpecifier = false; 838202379Srdivacky if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) 839202379Srdivacky return; 840202379Srdivacky 841218893Sdim // C++ constructors are never found by name lookup. 842218893Sdim if (isa<CXXConstructorDecl>(R.Declaration)) 843218893Sdim return; 844218893Sdim 845198092Srdivacky ShadowMap &SMap = ShadowMaps.back(); 846200583Srdivacky ShadowMapEntry::iterator I, IEnd; 847200583Srdivacky ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName()); 848200583Srdivacky if (NamePos != SMap.end()) { 849200583Srdivacky I = NamePos->second.begin(); 850200583Srdivacky IEnd = NamePos->second.end(); 851200583Srdivacky } 852200583Srdivacky 853200583Srdivacky for (; I != IEnd; ++I) { 854249423Sdim const NamedDecl *ND = I->first; 855200583Srdivacky unsigned Index = I->second; 856198092Srdivacky if (ND->getCanonicalDecl() == CanonDecl) { 857198092Srdivacky // This is a redeclaration. Always pick the newer declaration. 858198092Srdivacky Results[Index].Declaration = R.Declaration; 859198092Srdivacky 860198092Srdivacky // We're done. 861198092Srdivacky return; 862198092Srdivacky } 863198092Srdivacky } 864198092Srdivacky 865198092Srdivacky // This is a new declaration in this scope. However, check whether this 866198092Srdivacky // declaration name is hidden by a similarly-named declaration in an outer 867198092Srdivacky // scope. 868198092Srdivacky std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end(); 869198092Srdivacky --SMEnd; 870198092Srdivacky for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) { 871200583Srdivacky ShadowMapEntry::iterator I, IEnd; 872200583Srdivacky ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName()); 873200583Srdivacky if (NamePos != SM->end()) { 874200583Srdivacky I = NamePos->second.begin(); 875200583Srdivacky IEnd = NamePos->second.end(); 876200583Srdivacky } 877200583Srdivacky for (; I != IEnd; ++I) { 878198092Srdivacky // A tag declaration does not hide a non-tag declaration. 879207619Srdivacky if (I->first->hasTagIdentifierNamespace() && 880198092Srdivacky (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | 881198092Srdivacky Decl::IDNS_ObjCProtocol))) 882198092Srdivacky continue; 883198092Srdivacky 884198092Srdivacky // Protocols are in distinct namespaces from everything else. 885200583Srdivacky if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) 886198092Srdivacky || (IDNS & Decl::IDNS_ObjCProtocol)) && 887200583Srdivacky I->first->getIdentifierNamespace() != IDNS) 888198092Srdivacky continue; 889198092Srdivacky 890198092Srdivacky // The newly-added result is hidden by an entry in the shadow map. 891202379Srdivacky if (CheckHiddenResult(R, CurContext, I->first)) 892198092Srdivacky return; 893198092Srdivacky 894198092Srdivacky break; 895198092Srdivacky } 896198092Srdivacky } 897198092Srdivacky 898198092Srdivacky // Make sure that any given declaration only shows up in the result set once. 899198092Srdivacky if (!AllDeclsFound.insert(CanonDecl)) 900198092Srdivacky return; 901212904Sdim 902198092Srdivacky // If the filter is for nested-name-specifiers, then this result starts a 903198092Srdivacky // nested-name-specifier. 904208600Srdivacky if (AsNestedNameSpecifier) { 905198092Srdivacky R.StartsNestedNameSpecifier = true; 906208600Srdivacky R.Priority = CCP_NestedNameSpecifier; 907218893Sdim } else 908218893Sdim AdjustResultPriorityForDecl(R); 909212904Sdim 910198092Srdivacky // If this result is supposed to have an informative qualifier, add one. 911198092Srdivacky if (R.QualifierIsInformative && !R.Qualifier && 912198092Srdivacky !R.StartsNestedNameSpecifier) { 913249423Sdim const DeclContext *Ctx = R.Declaration->getDeclContext(); 914249423Sdim if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) 915198092Srdivacky R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); 916249423Sdim else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) 917198092Srdivacky R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, 918198092Srdivacky SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); 919198092Srdivacky else 920198092Srdivacky R.QualifierIsInformative = false; 921198092Srdivacky } 922198092Srdivacky 923198092Srdivacky // Insert this result into the set of results and into the current shadow 924198092Srdivacky // map. 925200583Srdivacky SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size()); 926198092Srdivacky Results.push_back(R); 927218893Sdim 928218893Sdim if (!AsNestedNameSpecifier) 929218893Sdim MaybeAddConstructorResults(R); 930198092Srdivacky} 931198092Srdivacky 932202379Srdivackyvoid ResultBuilder::AddResult(Result R, DeclContext *CurContext, 933202379Srdivacky NamedDecl *Hiding, bool InBaseClass = false) { 934202379Srdivacky if (R.Kind != Result::RK_Declaration) { 935202379Srdivacky // For non-declaration results, just add the result. 936202379Srdivacky Results.push_back(R); 937202379Srdivacky return; 938202379Srdivacky } 939202379Srdivacky 940202379Srdivacky // Look through using declarations. 941249423Sdim if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { 942249423Sdim AddResult(Result(Using->getTargetDecl(), 943249423Sdim getBasePriority(Using->getTargetDecl()), 944249423Sdim R.Qualifier), 945249423Sdim CurContext, Hiding); 946202379Srdivacky return; 947202379Srdivacky } 948202379Srdivacky 949202379Srdivacky bool AsNestedNameSpecifier = false; 950202379Srdivacky if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) 951202379Srdivacky return; 952202379Srdivacky 953218893Sdim // C++ constructors are never found by name lookup. 954218893Sdim if (isa<CXXConstructorDecl>(R.Declaration)) 955218893Sdim return; 956218893Sdim 957202379Srdivacky if (Hiding && CheckHiddenResult(R, CurContext, Hiding)) 958202379Srdivacky return; 959234353Sdim 960202379Srdivacky // Make sure that any given declaration only shows up in the result set once. 961202379Srdivacky if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl())) 962202379Srdivacky return; 963202379Srdivacky 964202379Srdivacky // If the filter is for nested-name-specifiers, then this result starts a 965202379Srdivacky // nested-name-specifier. 966208600Srdivacky if (AsNestedNameSpecifier) { 967202379Srdivacky R.StartsNestedNameSpecifier = true; 968208600Srdivacky R.Priority = CCP_NestedNameSpecifier; 969208600Srdivacky } 970202379Srdivacky else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass && 971202379Srdivacky isa<CXXRecordDecl>(R.Declaration->getDeclContext() 972212904Sdim ->getRedeclContext())) 973202379Srdivacky R.QualifierIsInformative = true; 974202379Srdivacky 975202379Srdivacky // If this result is supposed to have an informative qualifier, add one. 976202379Srdivacky if (R.QualifierIsInformative && !R.Qualifier && 977202379Srdivacky !R.StartsNestedNameSpecifier) { 978249423Sdim const DeclContext *Ctx = R.Declaration->getDeclContext(); 979249423Sdim if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) 980202379Srdivacky R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace); 981249423Sdim else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) 982202379Srdivacky R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false, 983202379Srdivacky SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); 984202379Srdivacky else 985202379Srdivacky R.QualifierIsInformative = false; 986202379Srdivacky } 987202379Srdivacky 988208600Srdivacky // Adjust the priority if this result comes from a base class. 989208600Srdivacky if (InBaseClass) 990208600Srdivacky R.Priority += CCD_InBaseClass; 991208600Srdivacky 992218893Sdim AdjustResultPriorityForDecl(R); 993210299Sed 994212904Sdim if (HasObjectTypeQualifiers) 995249423Sdim if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) 996212904Sdim if (Method->isInstance()) { 997212904Sdim Qualifiers MethodQuals 998212904Sdim = Qualifiers::fromCVRMask(Method->getTypeQualifiers()); 999212904Sdim if (ObjectTypeQualifiers == MethodQuals) 1000212904Sdim R.Priority += CCD_ObjectQualifierMatch; 1001212904Sdim else if (ObjectTypeQualifiers - MethodQuals) { 1002212904Sdim // The method cannot be invoked, because doing so would drop 1003212904Sdim // qualifiers. 1004212904Sdim return; 1005212904Sdim } 1006212904Sdim } 1007212904Sdim 1008202379Srdivacky // Insert this result into the set of results. 1009202379Srdivacky Results.push_back(R); 1010218893Sdim 1011218893Sdim if (!AsNestedNameSpecifier) 1012218893Sdim MaybeAddConstructorResults(R); 1013202379Srdivacky} 1014202379Srdivacky 1015202379Srdivackyvoid ResultBuilder::AddResult(Result R) { 1016202379Srdivacky assert(R.Kind != Result::RK_Declaration && 1017202379Srdivacky "Declaration results need more context"); 1018202379Srdivacky Results.push_back(R); 1019202379Srdivacky} 1020202379Srdivacky 1021198092Srdivacky/// \brief Enter into a new scope. 1022198092Srdivackyvoid ResultBuilder::EnterNewScope() { 1023198092Srdivacky ShadowMaps.push_back(ShadowMap()); 1024198092Srdivacky} 1025198092Srdivacky 1026198092Srdivacky/// \brief Exit from the current scope. 1027198092Srdivackyvoid ResultBuilder::ExitScope() { 1028200583Srdivacky for (ShadowMap::iterator E = ShadowMaps.back().begin(), 1029200583Srdivacky EEnd = ShadowMaps.back().end(); 1030200583Srdivacky E != EEnd; 1031200583Srdivacky ++E) 1032200583Srdivacky E->second.Destroy(); 1033200583Srdivacky 1034198092Srdivacky ShadowMaps.pop_back(); 1035198092Srdivacky} 1036198092Srdivacky 1037198092Srdivacky/// \brief Determines whether this given declaration will be found by 1038198092Srdivacky/// ordinary name lookup. 1039249423Sdimbool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { 1040210299Sed ND = cast<NamedDecl>(ND->getUnderlyingDecl()); 1041210299Sed 1042198092Srdivacky unsigned IDNS = Decl::IDNS_Ordinary; 1043234353Sdim if (SemaRef.getLangOpts().CPlusPlus) 1044210299Sed IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; 1045234353Sdim else if (SemaRef.getLangOpts().ObjC1) { 1046218893Sdim if (isa<ObjCIvarDecl>(ND)) 1047218893Sdim return true; 1048218893Sdim } 1049218893Sdim 1050198092Srdivacky return ND->getIdentifierNamespace() & IDNS; 1051198092Srdivacky} 1052198092Srdivacky 1053202379Srdivacky/// \brief Determines whether this given declaration will be found by 1054210299Sed/// ordinary name lookup but is not a type name. 1055249423Sdimbool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { 1056210299Sed ND = cast<NamedDecl>(ND->getUnderlyingDecl()); 1057210299Sed if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) 1058210299Sed return false; 1059210299Sed 1060210299Sed unsigned IDNS = Decl::IDNS_Ordinary; 1061234353Sdim if (SemaRef.getLangOpts().CPlusPlus) 1062210299Sed IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; 1063234353Sdim else if (SemaRef.getLangOpts().ObjC1) { 1064218893Sdim if (isa<ObjCIvarDecl>(ND)) 1065218893Sdim return true; 1066218893Sdim } 1067218893Sdim 1068210299Sed return ND->getIdentifierNamespace() & IDNS; 1069210299Sed} 1070210299Sed 1071249423Sdimbool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { 1072212904Sdim if (!IsOrdinaryNonTypeName(ND)) 1073212904Sdim return 0; 1074212904Sdim 1075249423Sdim if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) 1076212904Sdim if (VD->getType()->isIntegralOrEnumerationType()) 1077212904Sdim return true; 1078212904Sdim 1079212904Sdim return false; 1080212904Sdim} 1081212904Sdim 1082210299Sed/// \brief Determines whether this given declaration will be found by 1083202379Srdivacky/// ordinary name lookup. 1084249423Sdimbool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { 1085210299Sed ND = cast<NamedDecl>(ND->getUnderlyingDecl()); 1086210299Sed 1087202379Srdivacky unsigned IDNS = Decl::IDNS_Ordinary; 1088234353Sdim if (SemaRef.getLangOpts().CPlusPlus) 1089207619Srdivacky IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; 1090202379Srdivacky 1091202379Srdivacky return (ND->getIdentifierNamespace() & IDNS) && 1092210299Sed !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) && 1093210299Sed !isa<ObjCPropertyDecl>(ND); 1094202379Srdivacky} 1095202379Srdivacky 1096198092Srdivacky/// \brief Determines whether the given declaration is suitable as the 1097198092Srdivacky/// start of a C++ nested-name-specifier, e.g., a class or namespace. 1098249423Sdimbool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const { 1099198092Srdivacky // Allow us to find class templates, too. 1100249423Sdim if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) 1101198092Srdivacky ND = ClassTemplate->getTemplatedDecl(); 1102198092Srdivacky 1103198092Srdivacky return SemaRef.isAcceptableNestedNameSpecifier(ND); 1104198092Srdivacky} 1105198092Srdivacky 1106198092Srdivacky/// \brief Determines whether the given declaration is an enumeration. 1107249423Sdimbool ResultBuilder::IsEnum(const NamedDecl *ND) const { 1108198092Srdivacky return isa<EnumDecl>(ND); 1109198092Srdivacky} 1110198092Srdivacky 1111198092Srdivacky/// \brief Determines whether the given declaration is a class or struct. 1112249423Sdimbool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { 1113198092Srdivacky // Allow us to find class templates, too. 1114249423Sdim if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) 1115198092Srdivacky ND = ClassTemplate->getTemplatedDecl(); 1116243830Sdim 1117243830Sdim // For purposes of this check, interfaces match too. 1118249423Sdim if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) 1119208600Srdivacky return RD->getTagKind() == TTK_Class || 1120243830Sdim RD->getTagKind() == TTK_Struct || 1121243830Sdim RD->getTagKind() == TTK_Interface; 1122198092Srdivacky 1123198092Srdivacky return false; 1124198092Srdivacky} 1125198092Srdivacky 1126198092Srdivacky/// \brief Determines whether the given declaration is a union. 1127249423Sdimbool ResultBuilder::IsUnion(const NamedDecl *ND) const { 1128198092Srdivacky // Allow us to find class templates, too. 1129249423Sdim if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) 1130198092Srdivacky ND = ClassTemplate->getTemplatedDecl(); 1131198092Srdivacky 1132249423Sdim if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) 1133208600Srdivacky return RD->getTagKind() == TTK_Union; 1134198092Srdivacky 1135198092Srdivacky return false; 1136198092Srdivacky} 1137198092Srdivacky 1138198092Srdivacky/// \brief Determines whether the given declaration is a namespace. 1139249423Sdimbool ResultBuilder::IsNamespace(const NamedDecl *ND) const { 1140198092Srdivacky return isa<NamespaceDecl>(ND); 1141198092Srdivacky} 1142198092Srdivacky 1143198092Srdivacky/// \brief Determines whether the given declaration is a namespace or 1144198092Srdivacky/// namespace alias. 1145249423Sdimbool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const { 1146198092Srdivacky return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND); 1147198092Srdivacky} 1148198092Srdivacky 1149200583Srdivacky/// \brief Determines whether the given declaration is a type. 1150249423Sdimbool ResultBuilder::IsType(const NamedDecl *ND) const { 1151249423Sdim if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND)) 1152212904Sdim ND = Using->getTargetDecl(); 1153212904Sdim 1154212904Sdim return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); 1155198092Srdivacky} 1156198092Srdivacky 1157200583Srdivacky/// \brief Determines which members of a class should be visible via 1158200583Srdivacky/// "." or "->". Only value declarations, nested name specifiers, and 1159200583Srdivacky/// using declarations thereof should show up. 1160249423Sdimbool ResultBuilder::IsMember(const NamedDecl *ND) const { 1161249423Sdim if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND)) 1162200583Srdivacky ND = Using->getTargetDecl(); 1163200583Srdivacky 1164200583Srdivacky return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) || 1165200583Srdivacky isa<ObjCPropertyDecl>(ND); 1166198092Srdivacky} 1167198092Srdivacky 1168210299Sedstatic bool isObjCReceiverType(ASTContext &C, QualType T) { 1169210299Sed T = C.getCanonicalType(T); 1170210299Sed switch (T->getTypeClass()) { 1171210299Sed case Type::ObjCObject: 1172210299Sed case Type::ObjCInterface: 1173210299Sed case Type::ObjCObjectPointer: 1174210299Sed return true; 1175210299Sed 1176210299Sed case Type::Builtin: 1177210299Sed switch (cast<BuiltinType>(T)->getKind()) { 1178210299Sed case BuiltinType::ObjCId: 1179210299Sed case BuiltinType::ObjCClass: 1180210299Sed case BuiltinType::ObjCSel: 1181210299Sed return true; 1182210299Sed 1183210299Sed default: 1184210299Sed break; 1185210299Sed } 1186210299Sed return false; 1187210299Sed 1188210299Sed default: 1189210299Sed break; 1190210299Sed } 1191210299Sed 1192234353Sdim if (!C.getLangOpts().CPlusPlus) 1193210299Sed return false; 1194210299Sed 1195210299Sed // FIXME: We could perform more analysis here to determine whether a 1196210299Sed // particular class type has any conversions to Objective-C types. For now, 1197210299Sed // just accept all class types. 1198210299Sed return T->isDependentType() || T->isRecordType(); 1199210299Sed} 1200210299Sed 1201249423Sdimbool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { 1202210299Sed QualType T = getDeclUsageType(SemaRef.Context, ND); 1203210299Sed if (T.isNull()) 1204210299Sed return false; 1205210299Sed 1206210299Sed T = SemaRef.Context.getBaseElementType(T); 1207210299Sed return isObjCReceiverType(SemaRef.Context, T); 1208210299Sed} 1209210299Sed 1210249423Sdimbool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const { 1211234353Sdim if (IsObjCMessageReceiver(ND)) 1212234353Sdim return true; 1213234353Sdim 1214249423Sdim const VarDecl *Var = dyn_cast<VarDecl>(ND); 1215234353Sdim if (!Var) 1216234353Sdim return false; 1217234353Sdim 1218234353Sdim return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>(); 1219234353Sdim} 1220234353Sdim 1221249423Sdimbool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const { 1222234353Sdim if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) || 1223234353Sdim (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND))) 1224212904Sdim return false; 1225212904Sdim 1226212904Sdim QualType T = getDeclUsageType(SemaRef.Context, ND); 1227212904Sdim if (T.isNull()) 1228212904Sdim return false; 1229212904Sdim 1230212904Sdim T = SemaRef.Context.getBaseElementType(T); 1231212904Sdim return T->isObjCObjectType() || T->isObjCObjectPointerType() || 1232212904Sdim T->isObjCIdType() || 1233234353Sdim (SemaRef.getLangOpts().CPlusPlus && T->isRecordType()); 1234212904Sdim} 1235210299Sed 1236249423Sdimbool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const { 1237218893Sdim return false; 1238218893Sdim} 1239218893Sdim 1240239462Sdim/// \brief Determines whether the given declaration is an Objective-C 1241202379Srdivacky/// instance variable. 1242249423Sdimbool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const { 1243202379Srdivacky return isa<ObjCIvarDecl>(ND); 1244198092Srdivacky} 1245198092Srdivacky 1246202379Srdivackynamespace { 1247202379Srdivacky /// \brief Visible declaration consumer that adds a code-completion result 1248202379Srdivacky /// for each visible declaration. 1249202379Srdivacky class CodeCompletionDeclConsumer : public VisibleDeclConsumer { 1250202379Srdivacky ResultBuilder &Results; 1251202379Srdivacky DeclContext *CurContext; 1252198092Srdivacky 1253202379Srdivacky public: 1254202379Srdivacky CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext) 1255202379Srdivacky : Results(Results), CurContext(CurContext) { } 1256202379Srdivacky 1257226633Sdim virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, 1258226633Sdim bool InBaseClass) { 1259226633Sdim bool Accessible = true; 1260234353Sdim if (Ctx) 1261234353Sdim Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx); 1262234353Sdim 1263249423Sdim ResultBuilder::Result Result(ND, Results.getBasePriority(ND), 0, false, 1264249423Sdim Accessible); 1265226633Sdim Results.AddResult(Result, CurContext, Hiding, InBaseClass); 1266198092Srdivacky } 1267202379Srdivacky }; 1268198092Srdivacky} 1269198092Srdivacky 1270198092Srdivacky/// \brief Add type specifiers for the current language as keyword results. 1271202379Srdivackystatic void AddTypeSpecifierResults(const LangOptions &LangOpts, 1272198092Srdivacky ResultBuilder &Results) { 1273212904Sdim typedef CodeCompletionResult Result; 1274208600Srdivacky Results.AddResult(Result("short", CCP_Type)); 1275208600Srdivacky Results.AddResult(Result("long", CCP_Type)); 1276208600Srdivacky Results.AddResult(Result("signed", CCP_Type)); 1277208600Srdivacky Results.AddResult(Result("unsigned", CCP_Type)); 1278208600Srdivacky Results.AddResult(Result("void", CCP_Type)); 1279208600Srdivacky Results.AddResult(Result("char", CCP_Type)); 1280208600Srdivacky Results.AddResult(Result("int", CCP_Type)); 1281208600Srdivacky Results.AddResult(Result("float", CCP_Type)); 1282208600Srdivacky Results.AddResult(Result("double", CCP_Type)); 1283208600Srdivacky Results.AddResult(Result("enum", CCP_Type)); 1284208600Srdivacky Results.AddResult(Result("struct", CCP_Type)); 1285208600Srdivacky Results.AddResult(Result("union", CCP_Type)); 1286208600Srdivacky Results.AddResult(Result("const", CCP_Type)); 1287208600Srdivacky Results.AddResult(Result("volatile", CCP_Type)); 1288202379Srdivacky 1289198092Srdivacky if (LangOpts.C99) { 1290198092Srdivacky // C99-specific 1291208600Srdivacky Results.AddResult(Result("_Complex", CCP_Type)); 1292208600Srdivacky Results.AddResult(Result("_Imaginary", CCP_Type)); 1293208600Srdivacky Results.AddResult(Result("_Bool", CCP_Type)); 1294208600Srdivacky Results.AddResult(Result("restrict", CCP_Type)); 1295198092Srdivacky } 1296198092Srdivacky 1297234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 1298234353Sdim Results.getCodeCompletionTUInfo()); 1299198092Srdivacky if (LangOpts.CPlusPlus) { 1300198092Srdivacky // C++-specific 1301218893Sdim Results.AddResult(Result("bool", CCP_Type + 1302218893Sdim (LangOpts.ObjC1? CCD_bool_in_ObjC : 0))); 1303208600Srdivacky Results.AddResult(Result("class", CCP_Type)); 1304208600Srdivacky Results.AddResult(Result("wchar_t", CCP_Type)); 1305198092Srdivacky 1306210299Sed // typename qualified-id 1307218893Sdim Builder.AddTypedTextChunk("typename"); 1308218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1309218893Sdim Builder.AddPlaceholderChunk("qualifier"); 1310218893Sdim Builder.AddTextChunk("::"); 1311218893Sdim Builder.AddPlaceholderChunk("name"); 1312218893Sdim Results.AddResult(Result(Builder.TakeString())); 1313208600Srdivacky 1314249423Sdim if (LangOpts.CPlusPlus11) { 1315208600Srdivacky Results.AddResult(Result("auto", CCP_Type)); 1316208600Srdivacky Results.AddResult(Result("char16_t", CCP_Type)); 1317208600Srdivacky Results.AddResult(Result("char32_t", CCP_Type)); 1318210299Sed 1319218893Sdim Builder.AddTypedTextChunk("decltype"); 1320218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1321218893Sdim Builder.AddPlaceholderChunk("expression"); 1322218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1323218893Sdim Results.AddResult(Result(Builder.TakeString())); 1324198092Srdivacky } 1325198092Srdivacky } 1326198092Srdivacky 1327198092Srdivacky // GNU extensions 1328198092Srdivacky if (LangOpts.GNUMode) { 1329198092Srdivacky // FIXME: Enable when we actually support decimal floating point. 1330202379Srdivacky // Results.AddResult(Result("_Decimal32")); 1331202379Srdivacky // Results.AddResult(Result("_Decimal64")); 1332202379Srdivacky // Results.AddResult(Result("_Decimal128")); 1333202379Srdivacky 1334218893Sdim Builder.AddTypedTextChunk("typeof"); 1335218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1336218893Sdim Builder.AddPlaceholderChunk("expression"); 1337218893Sdim Results.AddResult(Result(Builder.TakeString())); 1338210299Sed 1339218893Sdim Builder.AddTypedTextChunk("typeof"); 1340218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1341218893Sdim Builder.AddPlaceholderChunk("type"); 1342218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1343218893Sdim Results.AddResult(Result(Builder.TakeString())); 1344198092Srdivacky } 1345198092Srdivacky} 1346198092Srdivacky 1347212904Sdimstatic void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, 1348202379Srdivacky const LangOptions &LangOpts, 1349202379Srdivacky ResultBuilder &Results) { 1350212904Sdim typedef CodeCompletionResult Result; 1351202379Srdivacky // Note: we don't suggest either "auto" or "register", because both 1352202379Srdivacky // are pointless as storage specifiers. Elsewhere, we suggest "auto" 1353202379Srdivacky // in C++0x as a type specifier. 1354202379Srdivacky Results.AddResult(Result("extern")); 1355202379Srdivacky Results.AddResult(Result("static")); 1356202379Srdivacky} 1357202379Srdivacky 1358212904Sdimstatic void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, 1359202379Srdivacky const LangOptions &LangOpts, 1360202379Srdivacky ResultBuilder &Results) { 1361212904Sdim typedef CodeCompletionResult Result; 1362202379Srdivacky switch (CCC) { 1363212904Sdim case Sema::PCC_Class: 1364212904Sdim case Sema::PCC_MemberTemplate: 1365202379Srdivacky if (LangOpts.CPlusPlus) { 1366202379Srdivacky Results.AddResult(Result("explicit")); 1367202379Srdivacky Results.AddResult(Result("friend")); 1368202379Srdivacky Results.AddResult(Result("mutable")); 1369202379Srdivacky Results.AddResult(Result("virtual")); 1370202379Srdivacky } 1371202379Srdivacky // Fall through 1372202379Srdivacky 1373212904Sdim case Sema::PCC_ObjCInterface: 1374212904Sdim case Sema::PCC_ObjCImplementation: 1375212904Sdim case Sema::PCC_Namespace: 1376212904Sdim case Sema::PCC_Template: 1377202379Srdivacky if (LangOpts.CPlusPlus || LangOpts.C99) 1378202379Srdivacky Results.AddResult(Result("inline")); 1379202379Srdivacky break; 1380202379Srdivacky 1381212904Sdim case Sema::PCC_ObjCInstanceVariableList: 1382212904Sdim case Sema::PCC_Expression: 1383212904Sdim case Sema::PCC_Statement: 1384212904Sdim case Sema::PCC_ForInit: 1385212904Sdim case Sema::PCC_Condition: 1386212904Sdim case Sema::PCC_RecoveryInFunction: 1387212904Sdim case Sema::PCC_Type: 1388218893Sdim case Sema::PCC_ParenthesizedExpression: 1389218893Sdim case Sema::PCC_LocalDeclarationSpecifiers: 1390202379Srdivacky break; 1391202379Srdivacky } 1392202379Srdivacky} 1393202379Srdivacky 1394202379Srdivackystatic void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt); 1395202379Srdivackystatic void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt); 1396202379Srdivackystatic void AddObjCVisibilityResults(const LangOptions &LangOpts, 1397202379Srdivacky ResultBuilder &Results, 1398202379Srdivacky bool NeedAt); 1399202379Srdivackystatic void AddObjCImplementationResults(const LangOptions &LangOpts, 1400202379Srdivacky ResultBuilder &Results, 1401202379Srdivacky bool NeedAt); 1402202379Srdivackystatic void AddObjCInterfaceResults(const LangOptions &LangOpts, 1403202379Srdivacky ResultBuilder &Results, 1404202379Srdivacky bool NeedAt); 1405202379Srdivackystatic void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); 1406202379Srdivacky 1407210299Sedstatic void AddTypedefResult(ResultBuilder &Results) { 1408234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 1409234353Sdim Results.getCodeCompletionTUInfo()); 1410218893Sdim Builder.AddTypedTextChunk("typedef"); 1411218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1412218893Sdim Builder.AddPlaceholderChunk("type"); 1413218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1414218893Sdim Builder.AddPlaceholderChunk("name"); 1415218893Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString())); 1416210299Sed} 1417210299Sed 1418212904Sdimstatic bool WantTypesInContext(Sema::ParserCompletionContext CCC, 1419210299Sed const LangOptions &LangOpts) { 1420210299Sed switch (CCC) { 1421212904Sdim case Sema::PCC_Namespace: 1422212904Sdim case Sema::PCC_Class: 1423212904Sdim case Sema::PCC_ObjCInstanceVariableList: 1424212904Sdim case Sema::PCC_Template: 1425212904Sdim case Sema::PCC_MemberTemplate: 1426212904Sdim case Sema::PCC_Statement: 1427212904Sdim case Sema::PCC_RecoveryInFunction: 1428212904Sdim case Sema::PCC_Type: 1429218893Sdim case Sema::PCC_ParenthesizedExpression: 1430218893Sdim case Sema::PCC_LocalDeclarationSpecifiers: 1431210299Sed return true; 1432210299Sed 1433218893Sdim case Sema::PCC_Expression: 1434218893Sdim case Sema::PCC_Condition: 1435218893Sdim return LangOpts.CPlusPlus; 1436218893Sdim 1437212904Sdim case Sema::PCC_ObjCInterface: 1438212904Sdim case Sema::PCC_ObjCImplementation: 1439210299Sed return false; 1440210299Sed 1441212904Sdim case Sema::PCC_ForInit: 1442218893Sdim return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99; 1443210299Sed } 1444234353Sdim 1445234353Sdim llvm_unreachable("Invalid ParserCompletionContext!"); 1446234353Sdim} 1447234353Sdim 1448234353Sdimstatic PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context, 1449234353Sdim const Preprocessor &PP) { 1450234353Sdim PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP); 1451234353Sdim Policy.AnonymousTagLocations = false; 1452234353Sdim Policy.SuppressStrongLifetime = true; 1453234353Sdim Policy.SuppressUnwrittenScope = true; 1454234353Sdim return Policy; 1455234353Sdim} 1456234353Sdim 1457234353Sdim/// \brief Retrieve a printing policy suitable for code completion. 1458234353Sdimstatic PrintingPolicy getCompletionPrintingPolicy(Sema &S) { 1459234353Sdim return getCompletionPrintingPolicy(S.Context, S.PP); 1460234353Sdim} 1461234353Sdim 1462234353Sdim/// \brief Retrieve the string representation of the given type as a string 1463234353Sdim/// that has the appropriate lifetime for code completion. 1464234353Sdim/// 1465234353Sdim/// This routine provides a fast path where we provide constant strings for 1466234353Sdim/// common type names. 1467234353Sdimstatic const char *GetCompletionTypeString(QualType T, 1468234353Sdim ASTContext &Context, 1469234353Sdim const PrintingPolicy &Policy, 1470234353Sdim CodeCompletionAllocator &Allocator) { 1471234353Sdim if (!T.getLocalQualifiers()) { 1472234353Sdim // Built-in type names are constant strings. 1473234353Sdim if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) 1474239462Sdim return BT->getNameAsCString(Policy); 1475234353Sdim 1476234353Sdim // Anonymous tag types are constant strings. 1477234353Sdim if (const TagType *TagT = dyn_cast<TagType>(T)) 1478234353Sdim if (TagDecl *Tag = TagT->getDecl()) 1479249423Sdim if (!Tag->hasNameForLinkage()) { 1480234353Sdim switch (Tag->getTagKind()) { 1481234353Sdim case TTK_Struct: return "struct <anonymous>"; 1482243830Sdim case TTK_Interface: return "__interface <anonymous>"; 1483243830Sdim case TTK_Class: return "class <anonymous>"; 1484234353Sdim case TTK_Union: return "union <anonymous>"; 1485234353Sdim case TTK_Enum: return "enum <anonymous>"; 1486234353Sdim } 1487234353Sdim } 1488234353Sdim } 1489210299Sed 1490234353Sdim // Slow path: format the type as a string. 1491234353Sdim std::string Result; 1492234353Sdim T.getAsStringInternal(Result, Policy); 1493234353Sdim return Allocator.CopyString(Result); 1494210299Sed} 1495210299Sed 1496234353Sdim/// \brief Add a completion for "this", if we're in a member function. 1497234353Sdimstatic void addThisCompletion(Sema &S, ResultBuilder &Results) { 1498234353Sdim QualType ThisTy = S.getCurrentThisType(); 1499234353Sdim if (ThisTy.isNull()) 1500234353Sdim return; 1501234353Sdim 1502234353Sdim CodeCompletionAllocator &Allocator = Results.getAllocator(); 1503234353Sdim CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); 1504234353Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(S); 1505234353Sdim Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy, 1506234353Sdim S.Context, 1507234353Sdim Policy, 1508234353Sdim Allocator)); 1509234353Sdim Builder.AddTypedTextChunk("this"); 1510243830Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString())); 1511234353Sdim} 1512234353Sdim 1513202379Srdivacky/// \brief Add language constructs that show up for "ordinary" names. 1514212904Sdimstatic void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, 1515202379Srdivacky Scope *S, 1516202379Srdivacky Sema &SemaRef, 1517202379Srdivacky ResultBuilder &Results) { 1518234353Sdim CodeCompletionAllocator &Allocator = Results.getAllocator(); 1519234353Sdim CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); 1520234353Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef); 1521218893Sdim 1522212904Sdim typedef CodeCompletionResult Result; 1523202379Srdivacky switch (CCC) { 1524212904Sdim case Sema::PCC_Namespace: 1525234353Sdim if (SemaRef.getLangOpts().CPlusPlus) { 1526210299Sed if (Results.includeCodePatterns()) { 1527210299Sed // namespace <identifier> { declarations } 1528218893Sdim Builder.AddTypedTextChunk("namespace"); 1529218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1530218893Sdim Builder.AddPlaceholderChunk("identifier"); 1531218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 1532218893Sdim Builder.AddPlaceholderChunk("declarations"); 1533218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1534218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 1535218893Sdim Results.AddResult(Result(Builder.TakeString())); 1536210299Sed } 1537210299Sed 1538202379Srdivacky // namespace identifier = identifier ; 1539218893Sdim Builder.AddTypedTextChunk("namespace"); 1540218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1541218893Sdim Builder.AddPlaceholderChunk("name"); 1542218893Sdim Builder.AddChunk(CodeCompletionString::CK_Equal); 1543218893Sdim Builder.AddPlaceholderChunk("namespace"); 1544218893Sdim Results.AddResult(Result(Builder.TakeString())); 1545202379Srdivacky 1546202379Srdivacky // Using directives 1547218893Sdim Builder.AddTypedTextChunk("using"); 1548218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1549218893Sdim Builder.AddTextChunk("namespace"); 1550218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1551218893Sdim Builder.AddPlaceholderChunk("identifier"); 1552218893Sdim Results.AddResult(Result(Builder.TakeString())); 1553202379Srdivacky 1554202379Srdivacky // asm(string-literal) 1555218893Sdim Builder.AddTypedTextChunk("asm"); 1556218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1557218893Sdim Builder.AddPlaceholderChunk("string-literal"); 1558218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1559218893Sdim Results.AddResult(Result(Builder.TakeString())); 1560202379Srdivacky 1561210299Sed if (Results.includeCodePatterns()) { 1562210299Sed // Explicit template instantiation 1563218893Sdim Builder.AddTypedTextChunk("template"); 1564218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1565218893Sdim Builder.AddPlaceholderChunk("declaration"); 1566218893Sdim Results.AddResult(Result(Builder.TakeString())); 1567210299Sed } 1568202379Srdivacky } 1569202379Srdivacky 1570234353Sdim if (SemaRef.getLangOpts().ObjC1) 1571202379Srdivacky AddObjCTopLevelResults(Results, true); 1572202379Srdivacky 1573210299Sed AddTypedefResult(Results); 1574202379Srdivacky // Fall through 1575202379Srdivacky 1576212904Sdim case Sema::PCC_Class: 1577234353Sdim if (SemaRef.getLangOpts().CPlusPlus) { 1578202379Srdivacky // Using declaration 1579218893Sdim Builder.AddTypedTextChunk("using"); 1580218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1581218893Sdim Builder.AddPlaceholderChunk("qualifier"); 1582218893Sdim Builder.AddTextChunk("::"); 1583218893Sdim Builder.AddPlaceholderChunk("name"); 1584218893Sdim Results.AddResult(Result(Builder.TakeString())); 1585202379Srdivacky 1586210299Sed // using typename qualifier::name (only in a dependent context) 1587202379Srdivacky if (SemaRef.CurContext->isDependentContext()) { 1588218893Sdim Builder.AddTypedTextChunk("using"); 1589218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1590218893Sdim Builder.AddTextChunk("typename"); 1591218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1592218893Sdim Builder.AddPlaceholderChunk("qualifier"); 1593218893Sdim Builder.AddTextChunk("::"); 1594218893Sdim Builder.AddPlaceholderChunk("name"); 1595218893Sdim Results.AddResult(Result(Builder.TakeString())); 1596202379Srdivacky } 1597202379Srdivacky 1598212904Sdim if (CCC == Sema::PCC_Class) { 1599210299Sed AddTypedefResult(Results); 1600210299Sed 1601202379Srdivacky // public: 1602218893Sdim Builder.AddTypedTextChunk("public"); 1603234353Sdim if (Results.includeCodePatterns()) 1604234353Sdim Builder.AddChunk(CodeCompletionString::CK_Colon); 1605218893Sdim Results.AddResult(Result(Builder.TakeString())); 1606202379Srdivacky 1607202379Srdivacky // protected: 1608218893Sdim Builder.AddTypedTextChunk("protected"); 1609234353Sdim if (Results.includeCodePatterns()) 1610234353Sdim Builder.AddChunk(CodeCompletionString::CK_Colon); 1611218893Sdim Results.AddResult(Result(Builder.TakeString())); 1612202379Srdivacky 1613202379Srdivacky // private: 1614218893Sdim Builder.AddTypedTextChunk("private"); 1615234353Sdim if (Results.includeCodePatterns()) 1616234353Sdim Builder.AddChunk(CodeCompletionString::CK_Colon); 1617218893Sdim Results.AddResult(Result(Builder.TakeString())); 1618202379Srdivacky } 1619202379Srdivacky } 1620202379Srdivacky // Fall through 1621202379Srdivacky 1622212904Sdim case Sema::PCC_Template: 1623212904Sdim case Sema::PCC_MemberTemplate: 1624234353Sdim if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) { 1625202379Srdivacky // template < parameters > 1626218893Sdim Builder.AddTypedTextChunk("template"); 1627218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftAngle); 1628218893Sdim Builder.AddPlaceholderChunk("parameters"); 1629218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightAngle); 1630218893Sdim Results.AddResult(Result(Builder.TakeString())); 1631202379Srdivacky } 1632202379Srdivacky 1633234353Sdim AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); 1634234353Sdim AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); 1635202379Srdivacky break; 1636202379Srdivacky 1637212904Sdim case Sema::PCC_ObjCInterface: 1638234353Sdim AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true); 1639234353Sdim AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); 1640234353Sdim AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); 1641202379Srdivacky break; 1642202379Srdivacky 1643212904Sdim case Sema::PCC_ObjCImplementation: 1644234353Sdim AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true); 1645234353Sdim AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); 1646234353Sdim AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); 1647202379Srdivacky break; 1648202379Srdivacky 1649212904Sdim case Sema::PCC_ObjCInstanceVariableList: 1650234353Sdim AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true); 1651202379Srdivacky break; 1652202379Srdivacky 1653212904Sdim case Sema::PCC_RecoveryInFunction: 1654212904Sdim case Sema::PCC_Statement: { 1655210299Sed AddTypedefResult(Results); 1656202379Srdivacky 1657234353Sdim if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() && 1658234353Sdim SemaRef.getLangOpts().CXXExceptions) { 1659218893Sdim Builder.AddTypedTextChunk("try"); 1660218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 1661218893Sdim Builder.AddPlaceholderChunk("statements"); 1662218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1663218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 1664218893Sdim Builder.AddTextChunk("catch"); 1665218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1666218893Sdim Builder.AddPlaceholderChunk("declaration"); 1667218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1668218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 1669218893Sdim Builder.AddPlaceholderChunk("statements"); 1670218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1671218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 1672218893Sdim Results.AddResult(Result(Builder.TakeString())); 1673202379Srdivacky } 1674234353Sdim if (SemaRef.getLangOpts().ObjC1) 1675202379Srdivacky AddObjCStatementResults(Results, true); 1676202379Srdivacky 1677208600Srdivacky if (Results.includeCodePatterns()) { 1678208600Srdivacky // if (condition) { statements } 1679218893Sdim Builder.AddTypedTextChunk("if"); 1680218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1681234353Sdim if (SemaRef.getLangOpts().CPlusPlus) 1682218893Sdim Builder.AddPlaceholderChunk("condition"); 1683208600Srdivacky else 1684218893Sdim Builder.AddPlaceholderChunk("expression"); 1685218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1686218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 1687218893Sdim Builder.AddPlaceholderChunk("statements"); 1688218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1689218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 1690218893Sdim Results.AddResult(Result(Builder.TakeString())); 1691202379Srdivacky 1692208600Srdivacky // switch (condition) { } 1693218893Sdim Builder.AddTypedTextChunk("switch"); 1694218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1695234353Sdim if (SemaRef.getLangOpts().CPlusPlus) 1696218893Sdim Builder.AddPlaceholderChunk("condition"); 1697208600Srdivacky else 1698218893Sdim Builder.AddPlaceholderChunk("expression"); 1699218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1700218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 1701218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1702218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 1703218893Sdim Results.AddResult(Result(Builder.TakeString())); 1704208600Srdivacky } 1705208600Srdivacky 1706202379Srdivacky // Switch-specific statements. 1707212904Sdim if (!SemaRef.getCurFunction()->SwitchStack.empty()) { 1708202379Srdivacky // case expression: 1709218893Sdim Builder.AddTypedTextChunk("case"); 1710218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1711218893Sdim Builder.AddPlaceholderChunk("expression"); 1712218893Sdim Builder.AddChunk(CodeCompletionString::CK_Colon); 1713218893Sdim Results.AddResult(Result(Builder.TakeString())); 1714202379Srdivacky 1715202379Srdivacky // default: 1716218893Sdim Builder.AddTypedTextChunk("default"); 1717218893Sdim Builder.AddChunk(CodeCompletionString::CK_Colon); 1718218893Sdim Results.AddResult(Result(Builder.TakeString())); 1719202379Srdivacky } 1720202379Srdivacky 1721208600Srdivacky if (Results.includeCodePatterns()) { 1722208600Srdivacky /// while (condition) { statements } 1723218893Sdim Builder.AddTypedTextChunk("while"); 1724218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1725234353Sdim if (SemaRef.getLangOpts().CPlusPlus) 1726218893Sdim Builder.AddPlaceholderChunk("condition"); 1727208600Srdivacky else 1728218893Sdim Builder.AddPlaceholderChunk("expression"); 1729218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1730218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 1731218893Sdim Builder.AddPlaceholderChunk("statements"); 1732218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1733218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 1734218893Sdim Results.AddResult(Result(Builder.TakeString())); 1735208600Srdivacky 1736208600Srdivacky // do { statements } while ( expression ); 1737218893Sdim Builder.AddTypedTextChunk("do"); 1738218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 1739218893Sdim Builder.AddPlaceholderChunk("statements"); 1740218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1741218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 1742218893Sdim Builder.AddTextChunk("while"); 1743218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1744218893Sdim Builder.AddPlaceholderChunk("expression"); 1745218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1746218893Sdim Results.AddResult(Result(Builder.TakeString())); 1747202379Srdivacky 1748208600Srdivacky // for ( for-init-statement ; condition ; expression ) { statements } 1749218893Sdim Builder.AddTypedTextChunk("for"); 1750218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1751234353Sdim if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99) 1752218893Sdim Builder.AddPlaceholderChunk("init-statement"); 1753208600Srdivacky else 1754218893Sdim Builder.AddPlaceholderChunk("init-expression"); 1755218893Sdim Builder.AddChunk(CodeCompletionString::CK_SemiColon); 1756218893Sdim Builder.AddPlaceholderChunk("condition"); 1757218893Sdim Builder.AddChunk(CodeCompletionString::CK_SemiColon); 1758218893Sdim Builder.AddPlaceholderChunk("inc-expression"); 1759218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1760218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 1761218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1762218893Sdim Builder.AddPlaceholderChunk("statements"); 1763218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 1764218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 1765218893Sdim Results.AddResult(Result(Builder.TakeString())); 1766208600Srdivacky } 1767202379Srdivacky 1768202379Srdivacky if (S->getContinueParent()) { 1769202379Srdivacky // continue ; 1770218893Sdim Builder.AddTypedTextChunk("continue"); 1771218893Sdim Results.AddResult(Result(Builder.TakeString())); 1772202379Srdivacky } 1773202379Srdivacky 1774202379Srdivacky if (S->getBreakParent()) { 1775202379Srdivacky // break ; 1776218893Sdim Builder.AddTypedTextChunk("break"); 1777218893Sdim Results.AddResult(Result(Builder.TakeString())); 1778202379Srdivacky } 1779202379Srdivacky 1780202379Srdivacky // "return expression ;" or "return ;", depending on whether we 1781202379Srdivacky // know the function is void or not. 1782202379Srdivacky bool isVoid = false; 1783202379Srdivacky if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext)) 1784202379Srdivacky isVoid = Function->getResultType()->isVoidType(); 1785202379Srdivacky else if (ObjCMethodDecl *Method 1786202379Srdivacky = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext)) 1787202379Srdivacky isVoid = Method->getResultType()->isVoidType(); 1788204643Srdivacky else if (SemaRef.getCurBlock() && 1789204643Srdivacky !SemaRef.getCurBlock()->ReturnType.isNull()) 1790204643Srdivacky isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType(); 1791218893Sdim Builder.AddTypedTextChunk("return"); 1792204643Srdivacky if (!isVoid) { 1793218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1794218893Sdim Builder.AddPlaceholderChunk("expression"); 1795204643Srdivacky } 1796218893Sdim Results.AddResult(Result(Builder.TakeString())); 1797202379Srdivacky 1798210299Sed // goto identifier ; 1799218893Sdim Builder.AddTypedTextChunk("goto"); 1800218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1801218893Sdim Builder.AddPlaceholderChunk("label"); 1802218893Sdim Results.AddResult(Result(Builder.TakeString())); 1803202379Srdivacky 1804210299Sed // Using directives 1805218893Sdim Builder.AddTypedTextChunk("using"); 1806218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1807218893Sdim Builder.AddTextChunk("namespace"); 1808218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1809218893Sdim Builder.AddPlaceholderChunk("identifier"); 1810218893Sdim Results.AddResult(Result(Builder.TakeString())); 1811202379Srdivacky } 1812202379Srdivacky 1813202379Srdivacky // Fall through (for statement expressions). 1814212904Sdim case Sema::PCC_ForInit: 1815212904Sdim case Sema::PCC_Condition: 1816234353Sdim AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); 1817202379Srdivacky // Fall through: conditions and statements can have expressions. 1818202379Srdivacky 1819218893Sdim case Sema::PCC_ParenthesizedExpression: 1820234353Sdim if (SemaRef.getLangOpts().ObjCAutoRefCount && 1821224145Sdim CCC == Sema::PCC_ParenthesizedExpression) { 1822224145Sdim // (__bridge <type>)<expression> 1823224145Sdim Builder.AddTypedTextChunk("__bridge"); 1824224145Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1825224145Sdim Builder.AddPlaceholderChunk("type"); 1826224145Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1827224145Sdim Builder.AddPlaceholderChunk("expression"); 1828224145Sdim Results.AddResult(Result(Builder.TakeString())); 1829224145Sdim 1830224145Sdim // (__bridge_transfer <Objective-C type>)<expression> 1831224145Sdim Builder.AddTypedTextChunk("__bridge_transfer"); 1832224145Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1833224145Sdim Builder.AddPlaceholderChunk("Objective-C type"); 1834224145Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1835224145Sdim Builder.AddPlaceholderChunk("expression"); 1836224145Sdim Results.AddResult(Result(Builder.TakeString())); 1837224145Sdim 1838224145Sdim // (__bridge_retained <CF type>)<expression> 1839224145Sdim Builder.AddTypedTextChunk("__bridge_retained"); 1840224145Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1841224145Sdim Builder.AddPlaceholderChunk("CF type"); 1842224145Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1843224145Sdim Builder.AddPlaceholderChunk("expression"); 1844224145Sdim Results.AddResult(Result(Builder.TakeString())); 1845224145Sdim } 1846224145Sdim // Fall through 1847224145Sdim 1848212904Sdim case Sema::PCC_Expression: { 1849234353Sdim if (SemaRef.getLangOpts().CPlusPlus) { 1850202379Srdivacky // 'this', if we're in a non-static member function. 1851234353Sdim addThisCompletion(SemaRef, Results); 1852202379Srdivacky 1853234353Sdim // true 1854234353Sdim Builder.AddResultTypeChunk("bool"); 1855234353Sdim Builder.AddTypedTextChunk("true"); 1856234353Sdim Results.AddResult(Result(Builder.TakeString())); 1857234353Sdim 1858234353Sdim // false 1859234353Sdim Builder.AddResultTypeChunk("bool"); 1860234353Sdim Builder.AddTypedTextChunk("false"); 1861234353Sdim Results.AddResult(Result(Builder.TakeString())); 1862202379Srdivacky 1863234353Sdim if (SemaRef.getLangOpts().RTTI) { 1864221345Sdim // dynamic_cast < type-id > ( expression ) 1865221345Sdim Builder.AddTypedTextChunk("dynamic_cast"); 1866221345Sdim Builder.AddChunk(CodeCompletionString::CK_LeftAngle); 1867221345Sdim Builder.AddPlaceholderChunk("type"); 1868221345Sdim Builder.AddChunk(CodeCompletionString::CK_RightAngle); 1869221345Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1870221345Sdim Builder.AddPlaceholderChunk("expression"); 1871221345Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1872221345Sdim Results.AddResult(Result(Builder.TakeString())); 1873221345Sdim } 1874210299Sed 1875210299Sed // static_cast < type-id > ( expression ) 1876218893Sdim Builder.AddTypedTextChunk("static_cast"); 1877218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftAngle); 1878218893Sdim Builder.AddPlaceholderChunk("type"); 1879218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightAngle); 1880218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1881218893Sdim Builder.AddPlaceholderChunk("expression"); 1882218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1883218893Sdim Results.AddResult(Result(Builder.TakeString())); 1884202379Srdivacky 1885210299Sed // reinterpret_cast < type-id > ( expression ) 1886218893Sdim Builder.AddTypedTextChunk("reinterpret_cast"); 1887218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftAngle); 1888218893Sdim Builder.AddPlaceholderChunk("type"); 1889218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightAngle); 1890218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1891218893Sdim Builder.AddPlaceholderChunk("expression"); 1892218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1893218893Sdim Results.AddResult(Result(Builder.TakeString())); 1894202379Srdivacky 1895210299Sed // const_cast < type-id > ( expression ) 1896218893Sdim Builder.AddTypedTextChunk("const_cast"); 1897218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftAngle); 1898218893Sdim Builder.AddPlaceholderChunk("type"); 1899218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightAngle); 1900218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1901218893Sdim Builder.AddPlaceholderChunk("expression"); 1902218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1903218893Sdim Results.AddResult(Result(Builder.TakeString())); 1904202379Srdivacky 1905234353Sdim if (SemaRef.getLangOpts().RTTI) { 1906221345Sdim // typeid ( expression-or-type ) 1907234353Sdim Builder.AddResultTypeChunk("std::type_info"); 1908221345Sdim Builder.AddTypedTextChunk("typeid"); 1909221345Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1910221345Sdim Builder.AddPlaceholderChunk("expression-or-type"); 1911221345Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1912221345Sdim Results.AddResult(Result(Builder.TakeString())); 1913221345Sdim } 1914221345Sdim 1915210299Sed // new T ( ... ) 1916218893Sdim Builder.AddTypedTextChunk("new"); 1917218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1918218893Sdim Builder.AddPlaceholderChunk("type"); 1919218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1920218893Sdim Builder.AddPlaceholderChunk("expressions"); 1921218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1922218893Sdim Results.AddResult(Result(Builder.TakeString())); 1923202379Srdivacky 1924210299Sed // new T [ ] ( ... ) 1925218893Sdim Builder.AddTypedTextChunk("new"); 1926218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1927218893Sdim Builder.AddPlaceholderChunk("type"); 1928218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBracket); 1929218893Sdim Builder.AddPlaceholderChunk("size"); 1930218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBracket); 1931218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1932218893Sdim Builder.AddPlaceholderChunk("expressions"); 1933218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1934218893Sdim Results.AddResult(Result(Builder.TakeString())); 1935202379Srdivacky 1936210299Sed // delete expression 1937234353Sdim Builder.AddResultTypeChunk("void"); 1938218893Sdim Builder.AddTypedTextChunk("delete"); 1939218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1940218893Sdim Builder.AddPlaceholderChunk("expression"); 1941218893Sdim Results.AddResult(Result(Builder.TakeString())); 1942202379Srdivacky 1943210299Sed // delete [] expression 1944234353Sdim Builder.AddResultTypeChunk("void"); 1945218893Sdim Builder.AddTypedTextChunk("delete"); 1946218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1947218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBracket); 1948218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBracket); 1949218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1950218893Sdim Builder.AddPlaceholderChunk("expression"); 1951218893Sdim Results.AddResult(Result(Builder.TakeString())); 1952202379Srdivacky 1953234353Sdim if (SemaRef.getLangOpts().CXXExceptions) { 1954221345Sdim // throw expression 1955234353Sdim Builder.AddResultTypeChunk("void"); 1956221345Sdim Builder.AddTypedTextChunk("throw"); 1957221345Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 1958221345Sdim Builder.AddPlaceholderChunk("expression"); 1959221345Sdim Results.AddResult(Result(Builder.TakeString())); 1960221345Sdim } 1961234353Sdim 1962208600Srdivacky // FIXME: Rethrow? 1963234353Sdim 1964249423Sdim if (SemaRef.getLangOpts().CPlusPlus11) { 1965234353Sdim // nullptr 1966234353Sdim Builder.AddResultTypeChunk("std::nullptr_t"); 1967234353Sdim Builder.AddTypedTextChunk("nullptr"); 1968234353Sdim Results.AddResult(Result(Builder.TakeString())); 1969234353Sdim 1970234353Sdim // alignof 1971234353Sdim Builder.AddResultTypeChunk("size_t"); 1972234353Sdim Builder.AddTypedTextChunk("alignof"); 1973234353Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1974234353Sdim Builder.AddPlaceholderChunk("type"); 1975234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1976234353Sdim Results.AddResult(Result(Builder.TakeString())); 1977234353Sdim 1978234353Sdim // noexcept 1979234353Sdim Builder.AddResultTypeChunk("bool"); 1980234353Sdim Builder.AddTypedTextChunk("noexcept"); 1981234353Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1982234353Sdim Builder.AddPlaceholderChunk("expression"); 1983234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1984234353Sdim Results.AddResult(Result(Builder.TakeString())); 1985234353Sdim 1986234353Sdim // sizeof... expression 1987234353Sdim Builder.AddResultTypeChunk("size_t"); 1988234353Sdim Builder.AddTypedTextChunk("sizeof..."); 1989234353Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 1990234353Sdim Builder.AddPlaceholderChunk("parameter-pack"); 1991234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 1992234353Sdim Results.AddResult(Result(Builder.TakeString())); 1993234353Sdim } 1994202379Srdivacky } 1995202379Srdivacky 1996234353Sdim if (SemaRef.getLangOpts().ObjC1) { 1997202379Srdivacky // Add "super", if we're in an Objective-C class with a superclass. 1998210299Sed if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { 1999210299Sed // The interface can be NULL. 2000210299Sed if (ObjCInterfaceDecl *ID = Method->getClassInterface()) 2001234353Sdim if (ID->getSuperClass()) { 2002234353Sdim std::string SuperType; 2003234353Sdim SuperType = ID->getSuperClass()->getNameAsString(); 2004234353Sdim if (Method->isInstanceMethod()) 2005234353Sdim SuperType += " *"; 2006234353Sdim 2007234353Sdim Builder.AddResultTypeChunk(Allocator.CopyString(SuperType)); 2008234353Sdim Builder.AddTypedTextChunk("super"); 2009234353Sdim Results.AddResult(Result(Builder.TakeString())); 2010234353Sdim } 2011210299Sed } 2012210299Sed 2013202379Srdivacky AddObjCExpressionResults(Results, true); 2014202379Srdivacky } 2015202379Srdivacky 2016239462Sdim if (SemaRef.getLangOpts().C11) { 2017239462Sdim // _Alignof 2018239462Sdim Builder.AddResultTypeChunk("size_t"); 2019239462Sdim if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition()) 2020239462Sdim Builder.AddTypedTextChunk("alignof"); 2021239462Sdim else 2022239462Sdim Builder.AddTypedTextChunk("_Alignof"); 2023239462Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 2024239462Sdim Builder.AddPlaceholderChunk("type"); 2025239462Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 2026239462Sdim Results.AddResult(Result(Builder.TakeString())); 2027239462Sdim } 2028239462Sdim 2029210299Sed // sizeof expression 2030234353Sdim Builder.AddResultTypeChunk("size_t"); 2031218893Sdim Builder.AddTypedTextChunk("sizeof"); 2032218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 2033218893Sdim Builder.AddPlaceholderChunk("expression-or-type"); 2034218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 2035218893Sdim Results.AddResult(Result(Builder.TakeString())); 2036202379Srdivacky break; 2037202379Srdivacky } 2038212904Sdim 2039212904Sdim case Sema::PCC_Type: 2040218893Sdim case Sema::PCC_LocalDeclarationSpecifiers: 2041212904Sdim break; 2042202379Srdivacky } 2043202379Srdivacky 2044234353Sdim if (WantTypesInContext(CCC, SemaRef.getLangOpts())) 2045234353Sdim AddTypeSpecifierResults(SemaRef.getLangOpts(), Results); 2046202379Srdivacky 2047234353Sdim if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type) 2048202379Srdivacky Results.AddResult(Result("operator")); 2049202379Srdivacky} 2050202379Srdivacky 2051201361Srdivacky/// \brief If the given declaration has an associated type, add it as a result 2052201361Srdivacky/// type chunk. 2053201361Srdivackystatic void AddResultTypeChunk(ASTContext &Context, 2054226633Sdim const PrintingPolicy &Policy, 2055249423Sdim const NamedDecl *ND, 2056218893Sdim CodeCompletionBuilder &Result) { 2057201361Srdivacky if (!ND) 2058201361Srdivacky return; 2059218893Sdim 2060218893Sdim // Skip constructors and conversion functions, which have their return types 2061218893Sdim // built into their names. 2062218893Sdim if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND)) 2063218893Sdim return; 2064218893Sdim 2065201361Srdivacky // Determine the type of the declaration (if it has a type). 2066218893Sdim QualType T; 2067249423Sdim if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) 2068201361Srdivacky T = Function->getResultType(); 2069249423Sdim else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) 2070201361Srdivacky T = Method->getResultType(); 2071249423Sdim else if (const FunctionTemplateDecl *FunTmpl = 2072249423Sdim dyn_cast<FunctionTemplateDecl>(ND)) 2073201361Srdivacky T = FunTmpl->getTemplatedDecl()->getResultType(); 2074249423Sdim else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) 2075201361Srdivacky T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext())); 2076201361Srdivacky else if (isa<UnresolvedUsingValueDecl>(ND)) { 2077201361Srdivacky /* Do nothing: ignore unresolved using declarations*/ 2078249423Sdim } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) { 2079201361Srdivacky T = Value->getType(); 2080249423Sdim } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) 2081201361Srdivacky T = Property->getType(); 2082201361Srdivacky 2083201361Srdivacky if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) 2084201361Srdivacky return; 2085201361Srdivacky 2086226633Sdim Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy, 2087218893Sdim Result.getAllocator())); 2088201361Srdivacky} 2089201361Srdivacky 2090249423Sdimstatic void MaybeAddSentinel(ASTContext &Context, 2091249423Sdim const NamedDecl *FunctionOrMethod, 2092218893Sdim CodeCompletionBuilder &Result) { 2093212904Sdim if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) 2094212904Sdim if (Sentinel->getSentinel() == 0) { 2095234353Sdim if (Context.getLangOpts().ObjC1 && 2096212904Sdim Context.Idents.get("nil").hasMacroDefinition()) 2097218893Sdim Result.AddTextChunk(", nil"); 2098212904Sdim else if (Context.Idents.get("NULL").hasMacroDefinition()) 2099218893Sdim Result.AddTextChunk(", NULL"); 2100212904Sdim else 2101218893Sdim Result.AddTextChunk(", (void*)0"); 2102212904Sdim } 2103212904Sdim} 2104212904Sdim 2105226633Sdimstatic std::string formatObjCParamQualifiers(unsigned ObjCQuals) { 2106226633Sdim std::string Result; 2107226633Sdim if (ObjCQuals & Decl::OBJC_TQ_In) 2108234353Sdim Result += "in "; 2109226633Sdim else if (ObjCQuals & Decl::OBJC_TQ_Inout) 2110234353Sdim Result += "inout "; 2111226633Sdim else if (ObjCQuals & Decl::OBJC_TQ_Out) 2112234353Sdim Result += "out "; 2113226633Sdim if (ObjCQuals & Decl::OBJC_TQ_Bycopy) 2114234353Sdim Result += "bycopy "; 2115226633Sdim else if (ObjCQuals & Decl::OBJC_TQ_Byref) 2116234353Sdim Result += "byref "; 2117226633Sdim if (ObjCQuals & Decl::OBJC_TQ_Oneway) 2118234353Sdim Result += "oneway "; 2119226633Sdim return Result; 2120226633Sdim} 2121226633Sdim 2122212904Sdimstatic std::string FormatFunctionParameter(ASTContext &Context, 2123226633Sdim const PrintingPolicy &Policy, 2124249423Sdim const ParmVarDecl *Param, 2125234353Sdim bool SuppressName = false, 2126234353Sdim bool SuppressBlock = false) { 2127212904Sdim bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext()); 2128212904Sdim if (Param->getType()->isDependentType() || 2129212904Sdim !Param->getType()->isBlockPointerType()) { 2130212904Sdim // The argument for a dependent or non-block parameter is a placeholder 2131212904Sdim // containing that parameter's type. 2132212904Sdim std::string Result; 2133212904Sdim 2134212904Sdim if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName) 2135212904Sdim Result = Param->getIdentifier()->getName(); 2136212904Sdim 2137224145Sdim Param->getType().getAsStringInternal(Result, Policy); 2138212904Sdim 2139212904Sdim if (ObjCMethodParam) { 2140226633Sdim Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier()) 2141226633Sdim + Result + ")"; 2142212904Sdim if (Param->getIdentifier() && !SuppressName) 2143212904Sdim Result += Param->getIdentifier()->getName(); 2144212904Sdim } 2145212904Sdim return Result; 2146212904Sdim } 2147212904Sdim 2148212904Sdim // The argument for a block pointer parameter is a block literal with 2149212904Sdim // the appropriate type. 2150249423Sdim FunctionTypeLoc Block; 2151249423Sdim FunctionProtoTypeLoc BlockProto; 2152212904Sdim TypeLoc TL; 2153212904Sdim if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) { 2154212904Sdim TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); 2155212904Sdim while (true) { 2156212904Sdim // Look through typedefs. 2157234353Sdim if (!SuppressBlock) { 2158249423Sdim if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) { 2159249423Sdim if (TypeSourceInfo *InnerTSInfo = 2160249423Sdim TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) { 2161234353Sdim TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); 2162234353Sdim continue; 2163234353Sdim } 2164234353Sdim } 2165234353Sdim 2166234353Sdim // Look through qualified types 2167249423Sdim if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { 2168249423Sdim TL = QualifiedTL.getUnqualifiedLoc(); 2169212904Sdim continue; 2170212904Sdim } 2171212904Sdim } 2172212904Sdim 2173212904Sdim // Try to get the function prototype behind the block pointer type, 2174212904Sdim // then we're done. 2175249423Sdim if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) { 2176249423Sdim TL = BlockPtr.getPointeeLoc().IgnoreParens(); 2177249423Sdim Block = TL.getAs<FunctionTypeLoc>(); 2178249423Sdim BlockProto = TL.getAs<FunctionProtoTypeLoc>(); 2179212904Sdim } 2180212904Sdim break; 2181212904Sdim } 2182212904Sdim } 2183212904Sdim 2184212904Sdim if (!Block) { 2185212904Sdim // We were unable to find a FunctionProtoTypeLoc with parameter names 2186212904Sdim // for the block; just use the parameter type as a placeholder. 2187212904Sdim std::string Result; 2188234353Sdim if (!ObjCMethodParam && Param->getIdentifier()) 2189234353Sdim Result = Param->getIdentifier()->getName(); 2190234353Sdim 2191224145Sdim Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy); 2192212904Sdim 2193212904Sdim if (ObjCMethodParam) { 2194226633Sdim Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier()) 2195226633Sdim + Result + ")"; 2196212904Sdim if (Param->getIdentifier()) 2197212904Sdim Result += Param->getIdentifier()->getName(); 2198212904Sdim } 2199212904Sdim 2200212904Sdim return Result; 2201212904Sdim } 2202234353Sdim 2203212904Sdim // We have the function prototype behind the block pointer type, as it was 2204212904Sdim // written in the source. 2205218893Sdim std::string Result; 2206249423Sdim QualType ResultType = Block.getTypePtr()->getResultType(); 2207234353Sdim if (!ResultType->isVoidType() || SuppressBlock) 2208224145Sdim ResultType.getAsStringInternal(Result, Policy); 2209234353Sdim 2210234353Sdim // Format the parameter list. 2211234353Sdim std::string Params; 2212249423Sdim if (!BlockProto || Block.getNumArgs() == 0) { 2213249423Sdim if (BlockProto && BlockProto.getTypePtr()->isVariadic()) 2214234353Sdim Params = "(...)"; 2215218893Sdim else 2216234353Sdim Params = "(void)"; 2217218893Sdim } else { 2218234353Sdim Params += "("; 2219249423Sdim for (unsigned I = 0, N = Block.getNumArgs(); I != N; ++I) { 2220218893Sdim if (I) 2221234353Sdim Params += ", "; 2222249423Sdim Params += FormatFunctionParameter(Context, Policy, Block.getArg(I), 2223234353Sdim /*SuppressName=*/false, 2224234353Sdim /*SuppressBlock=*/true); 2225218893Sdim 2226249423Sdim if (I == N - 1 && BlockProto.getTypePtr()->isVariadic()) 2227234353Sdim Params += ", ..."; 2228218893Sdim } 2229234353Sdim Params += ")"; 2230234353Sdim } 2231234353Sdim 2232234353Sdim if (SuppressBlock) { 2233234353Sdim // Format as a parameter. 2234234353Sdim Result = Result + " (^"; 2235234353Sdim if (Param->getIdentifier()) 2236234353Sdim Result += Param->getIdentifier()->getName(); 2237218893Sdim Result += ")"; 2238234353Sdim Result += Params; 2239234353Sdim } else { 2240234353Sdim // Format as a block literal argument. 2241234353Sdim Result = '^' + Result; 2242234353Sdim Result += Params; 2243234353Sdim 2244234353Sdim if (Param->getIdentifier()) 2245234353Sdim Result += Param->getIdentifier()->getName(); 2246212904Sdim } 2247218893Sdim 2248212904Sdim return Result; 2249212904Sdim} 2250212904Sdim 2251198092Srdivacky/// \brief Add function parameter chunks to the given code completion string. 2252198092Srdivackystatic void AddFunctionParameterChunks(ASTContext &Context, 2253226633Sdim const PrintingPolicy &Policy, 2254249423Sdim const FunctionDecl *Function, 2255218893Sdim CodeCompletionBuilder &Result, 2256218893Sdim unsigned Start = 0, 2257218893Sdim bool InOptional = false) { 2258218893Sdim bool FirstParameter = true; 2259199482Srdivacky 2260218893Sdim for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { 2261249423Sdim const ParmVarDecl *Param = Function->getParamDecl(P); 2262198092Srdivacky 2263218893Sdim if (Param->hasDefaultArg() && !InOptional) { 2264198092Srdivacky // When we see an optional default argument, put that argument and 2265198092Srdivacky // the remaining default arguments into a new, optional string. 2266234353Sdim CodeCompletionBuilder Opt(Result.getAllocator(), 2267234353Sdim Result.getCodeCompletionTUInfo()); 2268218893Sdim if (!FirstParameter) 2269234353Sdim Opt.AddChunk(CodeCompletionString::CK_Comma); 2270226633Sdim AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true); 2271218893Sdim Result.AddOptionalChunk(Opt.TakeString()); 2272218893Sdim break; 2273198092Srdivacky } 2274198092Srdivacky 2275218893Sdim if (FirstParameter) 2276218893Sdim FirstParameter = false; 2277218893Sdim else 2278234353Sdim Result.AddChunk(CodeCompletionString::CK_Comma); 2279198092Srdivacky 2280218893Sdim InOptional = false; 2281218893Sdim 2282198092Srdivacky // Format the placeholder string. 2283226633Sdim std::string PlaceholderStr = FormatFunctionParameter(Context, Policy, 2284226633Sdim Param); 2285212904Sdim 2286212904Sdim if (Function->isVariadic() && P == N - 1) 2287212904Sdim PlaceholderStr += ", ..."; 2288212904Sdim 2289198092Srdivacky // Add the placeholder string. 2290218893Sdim Result.AddPlaceholderChunk( 2291218893Sdim Result.getAllocator().CopyString(PlaceholderStr)); 2292198092Srdivacky } 2293198092Srdivacky 2294198092Srdivacky if (const FunctionProtoType *Proto 2295198092Srdivacky = Function->getType()->getAs<FunctionProtoType>()) 2296212904Sdim if (Proto->isVariadic()) { 2297212904Sdim if (Proto->getNumArgs() == 0) 2298218893Sdim Result.AddPlaceholderChunk("..."); 2299212904Sdim 2300218893Sdim MaybeAddSentinel(Context, Function, Result); 2301212904Sdim } 2302198092Srdivacky} 2303198092Srdivacky 2304198092Srdivacky/// \brief Add template parameter chunks to the given code completion string. 2305198092Srdivackystatic void AddTemplateParameterChunks(ASTContext &Context, 2306226633Sdim const PrintingPolicy &Policy, 2307249423Sdim const TemplateDecl *Template, 2308218893Sdim CodeCompletionBuilder &Result, 2309218893Sdim unsigned MaxParameters = 0, 2310218893Sdim unsigned Start = 0, 2311218893Sdim bool InDefaultArg = false) { 2312198092Srdivacky bool FirstParameter = true; 2313198092Srdivacky 2314198092Srdivacky TemplateParameterList *Params = Template->getTemplateParameters(); 2315198092Srdivacky TemplateParameterList::iterator PEnd = Params->end(); 2316198092Srdivacky if (MaxParameters) 2317198092Srdivacky PEnd = Params->begin() + MaxParameters; 2318218893Sdim for (TemplateParameterList::iterator P = Params->begin() + Start; 2319218893Sdim P != PEnd; ++P) { 2320198092Srdivacky bool HasDefaultArg = false; 2321198092Srdivacky std::string PlaceholderStr; 2322198092Srdivacky if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { 2323198092Srdivacky if (TTP->wasDeclaredWithTypename()) 2324198092Srdivacky PlaceholderStr = "typename"; 2325198092Srdivacky else 2326198092Srdivacky PlaceholderStr = "class"; 2327198092Srdivacky 2328198092Srdivacky if (TTP->getIdentifier()) { 2329198092Srdivacky PlaceholderStr += ' '; 2330198092Srdivacky PlaceholderStr += TTP->getIdentifier()->getName(); 2331198092Srdivacky } 2332198092Srdivacky 2333198092Srdivacky HasDefaultArg = TTP->hasDefaultArgument(); 2334198092Srdivacky } else if (NonTypeTemplateParmDecl *NTTP 2335218893Sdim = dyn_cast<NonTypeTemplateParmDecl>(*P)) { 2336198092Srdivacky if (NTTP->getIdentifier()) 2337198092Srdivacky PlaceholderStr = NTTP->getIdentifier()->getName(); 2338224145Sdim NTTP->getType().getAsStringInternal(PlaceholderStr, Policy); 2339198092Srdivacky HasDefaultArg = NTTP->hasDefaultArgument(); 2340198092Srdivacky } else { 2341198092Srdivacky assert(isa<TemplateTemplateParmDecl>(*P)); 2342198092Srdivacky TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); 2343198092Srdivacky 2344198092Srdivacky // Since putting the template argument list into the placeholder would 2345198092Srdivacky // be very, very long, we just use an abbreviation. 2346198092Srdivacky PlaceholderStr = "template<...> class"; 2347198092Srdivacky if (TTP->getIdentifier()) { 2348198092Srdivacky PlaceholderStr += ' '; 2349198092Srdivacky PlaceholderStr += TTP->getIdentifier()->getName(); 2350198092Srdivacky } 2351198092Srdivacky 2352198092Srdivacky HasDefaultArg = TTP->hasDefaultArgument(); 2353198092Srdivacky } 2354198092Srdivacky 2355218893Sdim if (HasDefaultArg && !InDefaultArg) { 2356198092Srdivacky // When we see an optional default argument, put that argument and 2357198092Srdivacky // the remaining default arguments into a new, optional string. 2358234353Sdim CodeCompletionBuilder Opt(Result.getAllocator(), 2359234353Sdim Result.getCodeCompletionTUInfo()); 2360218893Sdim if (!FirstParameter) 2361234353Sdim Opt.AddChunk(CodeCompletionString::CK_Comma); 2362226633Sdim AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters, 2363218893Sdim P - Params->begin(), true); 2364218893Sdim Result.AddOptionalChunk(Opt.TakeString()); 2365218893Sdim break; 2366198092Srdivacky } 2367198092Srdivacky 2368218893Sdim InDefaultArg = false; 2369218893Sdim 2370198092Srdivacky if (FirstParameter) 2371198092Srdivacky FirstParameter = false; 2372198092Srdivacky else 2373234353Sdim Result.AddChunk(CodeCompletionString::CK_Comma); 2374198092Srdivacky 2375198092Srdivacky // Add the placeholder string. 2376218893Sdim Result.AddPlaceholderChunk( 2377218893Sdim Result.getAllocator().CopyString(PlaceholderStr)); 2378198092Srdivacky } 2379198092Srdivacky} 2380198092Srdivacky 2381198092Srdivacky/// \brief Add a qualifier to the given code-completion string, if the 2382198092Srdivacky/// provided nested-name-specifier is non-NULL. 2383200583Srdivackystatic void 2384218893SdimAddQualifierToCompletionString(CodeCompletionBuilder &Result, 2385200583Srdivacky NestedNameSpecifier *Qualifier, 2386200583Srdivacky bool QualifierIsInformative, 2387226633Sdim ASTContext &Context, 2388226633Sdim const PrintingPolicy &Policy) { 2389198092Srdivacky if (!Qualifier) 2390198092Srdivacky return; 2391198092Srdivacky 2392198092Srdivacky std::string PrintedNNS; 2393198092Srdivacky { 2394198092Srdivacky llvm::raw_string_ostream OS(PrintedNNS); 2395226633Sdim Qualifier->print(OS, Policy); 2396198092Srdivacky } 2397198092Srdivacky if (QualifierIsInformative) 2398218893Sdim Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS)); 2399198092Srdivacky else 2400218893Sdim Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS)); 2401198092Srdivacky} 2402198092Srdivacky 2403218893Sdimstatic void 2404218893SdimAddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, 2405249423Sdim const FunctionDecl *Function) { 2406200583Srdivacky const FunctionProtoType *Proto 2407200583Srdivacky = Function->getType()->getAs<FunctionProtoType>(); 2408200583Srdivacky if (!Proto || !Proto->getTypeQuals()) 2409200583Srdivacky return; 2410200583Srdivacky 2411218893Sdim // FIXME: Add ref-qualifier! 2412218893Sdim 2413218893Sdim // Handle single qualifiers without copying 2414218893Sdim if (Proto->getTypeQuals() == Qualifiers::Const) { 2415218893Sdim Result.AddInformativeChunk(" const"); 2416218893Sdim return; 2417218893Sdim } 2418218893Sdim 2419218893Sdim if (Proto->getTypeQuals() == Qualifiers::Volatile) { 2420218893Sdim Result.AddInformativeChunk(" volatile"); 2421218893Sdim return; 2422218893Sdim } 2423218893Sdim 2424218893Sdim if (Proto->getTypeQuals() == Qualifiers::Restrict) { 2425218893Sdim Result.AddInformativeChunk(" restrict"); 2426218893Sdim return; 2427218893Sdim } 2428218893Sdim 2429218893Sdim // Handle multiple qualifiers. 2430200583Srdivacky std::string QualsStr; 2431239462Sdim if (Proto->isConst()) 2432200583Srdivacky QualsStr += " const"; 2433239462Sdim if (Proto->isVolatile()) 2434200583Srdivacky QualsStr += " volatile"; 2435239462Sdim if (Proto->isRestrict()) 2436200583Srdivacky QualsStr += " restrict"; 2437218893Sdim Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); 2438200583Srdivacky} 2439200583Srdivacky 2440218893Sdim/// \brief Add the name of the given declaration 2441226633Sdimstatic void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, 2442249423Sdim const NamedDecl *ND, 2443249423Sdim CodeCompletionBuilder &Result) { 2444218893Sdim DeclarationName Name = ND->getDeclName(); 2445218893Sdim if (!Name) 2446218893Sdim return; 2447218893Sdim 2448218893Sdim switch (Name.getNameKind()) { 2449218893Sdim case DeclarationName::CXXOperatorName: { 2450218893Sdim const char *OperatorName = 0; 2451218893Sdim switch (Name.getCXXOverloadedOperator()) { 2452218893Sdim case OO_None: 2453218893Sdim case OO_Conditional: 2454218893Sdim case NUM_OVERLOADED_OPERATORS: 2455218893Sdim OperatorName = "operator"; 2456218893Sdim break; 2457218893Sdim 2458218893Sdim#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ 2459218893Sdim case OO_##Name: OperatorName = "operator" Spelling; break; 2460218893Sdim#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly) 2461218893Sdim#include "clang/Basic/OperatorKinds.def" 2462218893Sdim 2463218893Sdim case OO_New: OperatorName = "operator new"; break; 2464218893Sdim case OO_Delete: OperatorName = "operator delete"; break; 2465218893Sdim case OO_Array_New: OperatorName = "operator new[]"; break; 2466218893Sdim case OO_Array_Delete: OperatorName = "operator delete[]"; break; 2467218893Sdim case OO_Call: OperatorName = "operator()"; break; 2468218893Sdim case OO_Subscript: OperatorName = "operator[]"; break; 2469218893Sdim } 2470218893Sdim Result.AddTypedTextChunk(OperatorName); 2471218893Sdim break; 2472218893Sdim } 2473218893Sdim 2474218893Sdim case DeclarationName::Identifier: 2475218893Sdim case DeclarationName::CXXConversionFunctionName: 2476218893Sdim case DeclarationName::CXXDestructorName: 2477218893Sdim case DeclarationName::CXXLiteralOperatorName: 2478218893Sdim Result.AddTypedTextChunk( 2479218893Sdim Result.getAllocator().CopyString(ND->getNameAsString())); 2480218893Sdim break; 2481218893Sdim 2482218893Sdim case DeclarationName::CXXUsingDirective: 2483218893Sdim case DeclarationName::ObjCZeroArgSelector: 2484218893Sdim case DeclarationName::ObjCOneArgSelector: 2485218893Sdim case DeclarationName::ObjCMultiArgSelector: 2486218893Sdim break; 2487218893Sdim 2488218893Sdim case DeclarationName::CXXConstructorName: { 2489218893Sdim CXXRecordDecl *Record = 0; 2490218893Sdim QualType Ty = Name.getCXXNameType(); 2491218893Sdim if (const RecordType *RecordTy = Ty->getAs<RecordType>()) 2492218893Sdim Record = cast<CXXRecordDecl>(RecordTy->getDecl()); 2493218893Sdim else if (const InjectedClassNameType *InjectedTy 2494218893Sdim = Ty->getAs<InjectedClassNameType>()) 2495218893Sdim Record = InjectedTy->getDecl(); 2496218893Sdim else { 2497218893Sdim Result.AddTypedTextChunk( 2498218893Sdim Result.getAllocator().CopyString(ND->getNameAsString())); 2499218893Sdim break; 2500218893Sdim } 2501218893Sdim 2502218893Sdim Result.AddTypedTextChunk( 2503218893Sdim Result.getAllocator().CopyString(Record->getNameAsString())); 2504218893Sdim if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { 2505234353Sdim Result.AddChunk(CodeCompletionString::CK_LeftAngle); 2506226633Sdim AddTemplateParameterChunks(Context, Policy, Template, Result); 2507234353Sdim Result.AddChunk(CodeCompletionString::CK_RightAngle); 2508218893Sdim } 2509218893Sdim break; 2510218893Sdim } 2511218893Sdim } 2512218893Sdim} 2513218893Sdim 2514234353SdimCodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S, 2515234353Sdim CodeCompletionAllocator &Allocator, 2516239462Sdim CodeCompletionTUInfo &CCTUInfo, 2517239462Sdim bool IncludeBriefComments) { 2518239462Sdim return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo, 2519239462Sdim IncludeBriefComments); 2520234353Sdim} 2521234353Sdim 2522198092Srdivacky/// \brief If possible, create a new code completion string for the given 2523198092Srdivacky/// result. 2524198092Srdivacky/// 2525198092Srdivacky/// \returns Either a new, heap-allocated code completion string describing 2526198092Srdivacky/// how to use this result, or NULL to indicate that the string or name of the 2527198092Srdivacky/// result is all that is needed. 2528198092SrdivackyCodeCompletionString * 2529234353SdimCodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx, 2530234353Sdim Preprocessor &PP, 2531234353Sdim CodeCompletionAllocator &Allocator, 2532239462Sdim CodeCompletionTUInfo &CCTUInfo, 2533239462Sdim bool IncludeBriefComments) { 2534234353Sdim CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); 2535199482Srdivacky 2536234353Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP); 2537218893Sdim if (Kind == RK_Pattern) { 2538218893Sdim Pattern->Priority = Priority; 2539218893Sdim Pattern->Availability = Availability; 2540234353Sdim 2541234353Sdim if (Declaration) { 2542234353Sdim Result.addParentContext(Declaration->getDeclContext()); 2543234353Sdim Pattern->ParentName = Result.getParentName(); 2544249423Sdim // Provide code completion comment for self.GetterName where 2545249423Sdim // GetterName is the getter method for a property with name 2546249423Sdim // different from the property name (declared via a property 2547249423Sdim // getter attribute. 2548249423Sdim const NamedDecl *ND = Declaration; 2549249423Sdim if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND)) 2550249423Sdim if (M->isPropertyAccessor()) 2551249423Sdim if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl()) 2552249423Sdim if (PDecl->getGetterName() == M->getSelector() && 2553249423Sdim PDecl->getIdentifier() != M->getIdentifier()) { 2554249423Sdim if (const RawComment *RC = 2555249423Sdim Ctx.getRawCommentForAnyRedecl(M)) { 2556249423Sdim Result.addBriefComment(RC->getBriefText(Ctx)); 2557249423Sdim Pattern->BriefComment = Result.getBriefComment(); 2558249423Sdim } 2559249423Sdim else if (const RawComment *RC = 2560249423Sdim Ctx.getRawCommentForAnyRedecl(PDecl)) { 2561249423Sdim Result.addBriefComment(RC->getBriefText(Ctx)); 2562249423Sdim Pattern->BriefComment = Result.getBriefComment(); 2563249423Sdim } 2564249423Sdim } 2565234353Sdim } 2566234353Sdim 2567218893Sdim return Pattern; 2568218893Sdim } 2569198092Srdivacky 2570199990Srdivacky if (Kind == RK_Keyword) { 2571218893Sdim Result.AddTypedTextChunk(Keyword); 2572218893Sdim return Result.TakeString(); 2573199990Srdivacky } 2574199990Srdivacky 2575198893Srdivacky if (Kind == RK_Macro) { 2576249423Sdim const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro); 2577249423Sdim assert(MD && "Not a macro?"); 2578249423Sdim const MacroInfo *MI = MD->getMacroInfo(); 2579199990Srdivacky 2580218893Sdim Result.AddTypedTextChunk( 2581218893Sdim Result.getAllocator().CopyString(Macro->getName())); 2582199990Srdivacky 2583199990Srdivacky if (!MI->isFunctionLike()) 2584218893Sdim return Result.TakeString(); 2585198893Srdivacky 2586198893Srdivacky // Format a function-like macro with placeholders for the arguments. 2587234353Sdim Result.AddChunk(CodeCompletionString::CK_LeftParen); 2588226633Sdim MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end(); 2589234353Sdim 2590234353Sdim // C99 variadic macros add __VA_ARGS__ at the end. Skip it. 2591234353Sdim if (MI->isC99Varargs()) { 2592234353Sdim --AEnd; 2593234353Sdim 2594234353Sdim if (A == AEnd) { 2595234353Sdim Result.AddPlaceholderChunk("..."); 2596234353Sdim } 2597226633Sdim } 2598234353Sdim 2599226633Sdim for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) { 2600198893Srdivacky if (A != MI->arg_begin()) 2601234353Sdim Result.AddChunk(CodeCompletionString::CK_Comma); 2602234353Sdim 2603234353Sdim if (MI->isVariadic() && (A+1) == AEnd) { 2604234353Sdim SmallString<32> Arg = (*A)->getName(); 2605234353Sdim if (MI->isC99Varargs()) 2606234353Sdim Arg += ", ..."; 2607234353Sdim else 2608234353Sdim Arg += "..."; 2609218893Sdim Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); 2610234353Sdim break; 2611198893Srdivacky } 2612234353Sdim 2613234353Sdim // Non-variadic macros are simple. 2614234353Sdim Result.AddPlaceholderChunk( 2615234353Sdim Result.getAllocator().CopyString((*A)->getName())); 2616198893Srdivacky } 2617234353Sdim Result.AddChunk(CodeCompletionString::CK_RightParen); 2618218893Sdim return Result.TakeString(); 2619198893Srdivacky } 2620198893Srdivacky 2621208600Srdivacky assert(Kind == RK_Declaration && "Missed a result kind?"); 2622249423Sdim const NamedDecl *ND = Declaration; 2623234353Sdim Result.addParentContext(ND->getDeclContext()); 2624239462Sdim 2625239462Sdim if (IncludeBriefComments) { 2626239462Sdim // Add documentation comment, if it exists. 2627239462Sdim if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) { 2628239462Sdim Result.addBriefComment(RC->getBriefText(Ctx)); 2629249423Sdim } 2630249423Sdim else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) 2631249423Sdim if (OMD->isPropertyAccessor()) 2632249423Sdim if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl()) 2633249423Sdim if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl)) 2634249423Sdim Result.addBriefComment(RC->getBriefText(Ctx)); 2635239462Sdim } 2636239462Sdim 2637199482Srdivacky if (StartsNestedNameSpecifier) { 2638218893Sdim Result.AddTypedTextChunk( 2639218893Sdim Result.getAllocator().CopyString(ND->getNameAsString())); 2640218893Sdim Result.AddTextChunk("::"); 2641218893Sdim return Result.TakeString(); 2642199482Srdivacky } 2643226633Sdim 2644226633Sdim for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) { 2645226633Sdim if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) { 2646226633Sdim Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation())); 2647226633Sdim } 2648226633Sdim } 2649199482Srdivacky 2650234353Sdim AddResultTypeChunk(Ctx, Policy, ND, Result); 2651201361Srdivacky 2652249423Sdim if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { 2653198092Srdivacky AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 2654234353Sdim Ctx, Policy); 2655234353Sdim AddTypedNameChunk(Ctx, Policy, ND, Result); 2656234353Sdim Result.AddChunk(CodeCompletionString::CK_LeftParen); 2657234353Sdim AddFunctionParameterChunks(Ctx, Policy, Function, Result); 2658234353Sdim Result.AddChunk(CodeCompletionString::CK_RightParen); 2659200583Srdivacky AddFunctionTypeQualsToCompletionString(Result, Function); 2660218893Sdim return Result.TakeString(); 2661198092Srdivacky } 2662198092Srdivacky 2663249423Sdim if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) { 2664198092Srdivacky AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 2665234353Sdim Ctx, Policy); 2666198092Srdivacky FunctionDecl *Function = FunTmpl->getTemplatedDecl(); 2667234353Sdim AddTypedNameChunk(Ctx, Policy, Function, Result); 2668218893Sdim 2669198092Srdivacky // Figure out which template parameters are deduced (or have default 2670198092Srdivacky // arguments). 2671234353Sdim llvm::SmallBitVector Deduced; 2672234353Sdim Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced); 2673198092Srdivacky unsigned LastDeducibleArgument; 2674198092Srdivacky for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0; 2675198092Srdivacky --LastDeducibleArgument) { 2676198092Srdivacky if (!Deduced[LastDeducibleArgument - 1]) { 2677198092Srdivacky // C++0x: Figure out if the template argument has a default. If so, 2678198092Srdivacky // the user doesn't need to type this argument. 2679198092Srdivacky // FIXME: We need to abstract template parameters better! 2680198092Srdivacky bool HasDefaultArg = false; 2681198092Srdivacky NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam( 2682218893Sdim LastDeducibleArgument - 1); 2683198092Srdivacky if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) 2684198092Srdivacky HasDefaultArg = TTP->hasDefaultArgument(); 2685198092Srdivacky else if (NonTypeTemplateParmDecl *NTTP 2686198092Srdivacky = dyn_cast<NonTypeTemplateParmDecl>(Param)) 2687198092Srdivacky HasDefaultArg = NTTP->hasDefaultArgument(); 2688198092Srdivacky else { 2689198092Srdivacky assert(isa<TemplateTemplateParmDecl>(Param)); 2690198092Srdivacky HasDefaultArg 2691199482Srdivacky = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); 2692198092Srdivacky } 2693198092Srdivacky 2694198092Srdivacky if (!HasDefaultArg) 2695198092Srdivacky break; 2696198092Srdivacky } 2697198092Srdivacky } 2698198092Srdivacky 2699198092Srdivacky if (LastDeducibleArgument) { 2700198092Srdivacky // Some of the function template arguments cannot be deduced from a 2701198092Srdivacky // function call, so we introduce an explicit template argument list 2702198092Srdivacky // containing all of the arguments up to the first deducible argument. 2703234353Sdim Result.AddChunk(CodeCompletionString::CK_LeftAngle); 2704234353Sdim AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, 2705198092Srdivacky LastDeducibleArgument); 2706234353Sdim Result.AddChunk(CodeCompletionString::CK_RightAngle); 2707198092Srdivacky } 2708198092Srdivacky 2709198092Srdivacky // Add the function parameters 2710234353Sdim Result.AddChunk(CodeCompletionString::CK_LeftParen); 2711234353Sdim AddFunctionParameterChunks(Ctx, Policy, Function, Result); 2712234353Sdim Result.AddChunk(CodeCompletionString::CK_RightParen); 2713200583Srdivacky AddFunctionTypeQualsToCompletionString(Result, Function); 2714218893Sdim return Result.TakeString(); 2715198092Srdivacky } 2716198092Srdivacky 2717249423Sdim if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) { 2718198092Srdivacky AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 2719234353Sdim Ctx, Policy); 2720218893Sdim Result.AddTypedTextChunk( 2721218893Sdim Result.getAllocator().CopyString(Template->getNameAsString())); 2722234353Sdim Result.AddChunk(CodeCompletionString::CK_LeftAngle); 2723234353Sdim AddTemplateParameterChunks(Ctx, Policy, Template, Result); 2724234353Sdim Result.AddChunk(CodeCompletionString::CK_RightAngle); 2725218893Sdim return Result.TakeString(); 2726198092Srdivacky } 2727198092Srdivacky 2728249423Sdim if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) { 2729199482Srdivacky Selector Sel = Method->getSelector(); 2730199482Srdivacky if (Sel.isUnarySelector()) { 2731218893Sdim Result.AddTypedTextChunk(Result.getAllocator().CopyString( 2732218893Sdim Sel.getNameForSlot(0))); 2733218893Sdim return Result.TakeString(); 2734199482Srdivacky } 2735199482Srdivacky 2736218893Sdim std::string SelName = Sel.getNameForSlot(0).str(); 2737199512Srdivacky SelName += ':'; 2738199512Srdivacky if (StartParameter == 0) 2739218893Sdim Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName)); 2740199512Srdivacky else { 2741218893Sdim Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName)); 2742199512Srdivacky 2743199512Srdivacky // If there is only one parameter, and we're past it, add an empty 2744199512Srdivacky // typed-text chunk since there is nothing to type. 2745199512Srdivacky if (Method->param_size() == 1) 2746218893Sdim Result.AddTypedTextChunk(""); 2747199512Srdivacky } 2748199482Srdivacky unsigned Idx = 0; 2749249423Sdim for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(), 2750249423Sdim PEnd = Method->param_end(); 2751199482Srdivacky P != PEnd; (void)++P, ++Idx) { 2752199482Srdivacky if (Idx > 0) { 2753199512Srdivacky std::string Keyword; 2754199512Srdivacky if (Idx > StartParameter) 2755218893Sdim Result.AddChunk(CodeCompletionString::CK_HorizontalSpace); 2756199482Srdivacky if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx)) 2757226633Sdim Keyword += II->getName(); 2758199482Srdivacky Keyword += ":"; 2759210299Sed if (Idx < StartParameter || AllParametersAreInformative) 2760218893Sdim Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword)); 2761218893Sdim else 2762218893Sdim Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword)); 2763199482Srdivacky } 2764199512Srdivacky 2765199512Srdivacky // If we're before the starting parameter, skip the placeholder. 2766199512Srdivacky if (Idx < StartParameter) 2767199512Srdivacky continue; 2768199482Srdivacky 2769199482Srdivacky std::string Arg; 2770212904Sdim 2771212904Sdim if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity) 2772234353Sdim Arg = FormatFunctionParameter(Ctx, Policy, *P, true); 2773212904Sdim else { 2774224145Sdim (*P)->getType().getAsStringInternal(Arg, Policy); 2775226633Sdim Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier()) 2776226633Sdim + Arg + ")"; 2777212904Sdim if (IdentifierInfo *II = (*P)->getIdentifier()) 2778212904Sdim if (DeclaringEntity || AllParametersAreInformative) 2779226633Sdim Arg += II->getName(); 2780212904Sdim } 2781212904Sdim 2782212904Sdim if (Method->isVariadic() && (P + 1) == PEnd) 2783212904Sdim Arg += ", ..."; 2784212904Sdim 2785210299Sed if (DeclaringEntity) 2786218893Sdim Result.AddTextChunk(Result.getAllocator().CopyString(Arg)); 2787210299Sed else if (AllParametersAreInformative) 2788218893Sdim Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg)); 2789199512Srdivacky else 2790218893Sdim Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); 2791199482Srdivacky } 2792199482Srdivacky 2793201361Srdivacky if (Method->isVariadic()) { 2794212904Sdim if (Method->param_size() == 0) { 2795212904Sdim if (DeclaringEntity) 2796218893Sdim Result.AddTextChunk(", ..."); 2797212904Sdim else if (AllParametersAreInformative) 2798218893Sdim Result.AddInformativeChunk(", ..."); 2799212904Sdim else 2800218893Sdim Result.AddPlaceholderChunk(", ..."); 2801212904Sdim } 2802212904Sdim 2803234353Sdim MaybeAddSentinel(Ctx, Method, Result); 2804201361Srdivacky } 2805201361Srdivacky 2806218893Sdim return Result.TakeString(); 2807199482Srdivacky } 2808199482Srdivacky 2809199990Srdivacky if (Qualifier) 2810198092Srdivacky AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, 2811234353Sdim Ctx, Policy); 2812199990Srdivacky 2813218893Sdim Result.AddTypedTextChunk( 2814218893Sdim Result.getAllocator().CopyString(ND->getNameAsString())); 2815218893Sdim return Result.TakeString(); 2816198092Srdivacky} 2817198092Srdivacky 2818198092SrdivackyCodeCompletionString * 2819198092SrdivackyCodeCompleteConsumer::OverloadCandidate::CreateSignatureString( 2820198092Srdivacky unsigned CurrentArg, 2821218893Sdim Sema &S, 2822234353Sdim CodeCompletionAllocator &Allocator, 2823234353Sdim CodeCompletionTUInfo &CCTUInfo) const { 2824226633Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(S); 2825224145Sdim 2826218893Sdim // FIXME: Set priority, availability appropriately. 2827234353Sdim CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available); 2828198092Srdivacky FunctionDecl *FDecl = getFunction(); 2829226633Sdim AddResultTypeChunk(S.Context, Policy, FDecl, Result); 2830198092Srdivacky const FunctionProtoType *Proto 2831198092Srdivacky = dyn_cast<FunctionProtoType>(getFunctionType()); 2832198092Srdivacky if (!FDecl && !Proto) { 2833198092Srdivacky // Function without a prototype. Just give the return type and a 2834198092Srdivacky // highlighted ellipsis. 2835198092Srdivacky const FunctionType *FT = getFunctionType(); 2836218893Sdim Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(), 2837226633Sdim S.Context, Policy, 2838218893Sdim Result.getAllocator())); 2839234353Sdim Result.AddChunk(CodeCompletionString::CK_LeftParen); 2840234353Sdim Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); 2841234353Sdim Result.AddChunk(CodeCompletionString::CK_RightParen); 2842218893Sdim return Result.TakeString(); 2843198092Srdivacky } 2844198092Srdivacky 2845198092Srdivacky if (FDecl) 2846218893Sdim Result.AddTextChunk( 2847218893Sdim Result.getAllocator().CopyString(FDecl->getNameAsString())); 2848198092Srdivacky else 2849218893Sdim Result.AddTextChunk( 2850218893Sdim Result.getAllocator().CopyString( 2851224145Sdim Proto->getResultType().getAsString(Policy))); 2852198092Srdivacky 2853234353Sdim Result.AddChunk(CodeCompletionString::CK_LeftParen); 2854198092Srdivacky unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs(); 2855198092Srdivacky for (unsigned I = 0; I != NumParams; ++I) { 2856198092Srdivacky if (I) 2857234353Sdim Result.AddChunk(CodeCompletionString::CK_Comma); 2858198092Srdivacky 2859198092Srdivacky std::string ArgString; 2860198092Srdivacky QualType ArgType; 2861198092Srdivacky 2862198092Srdivacky if (FDecl) { 2863198092Srdivacky ArgString = FDecl->getParamDecl(I)->getNameAsString(); 2864198092Srdivacky ArgType = FDecl->getParamDecl(I)->getOriginalType(); 2865198092Srdivacky } else { 2866198092Srdivacky ArgType = Proto->getArgType(I); 2867198092Srdivacky } 2868198092Srdivacky 2869224145Sdim ArgType.getAsStringInternal(ArgString, Policy); 2870198092Srdivacky 2871198092Srdivacky if (I == CurrentArg) 2872234353Sdim Result.AddChunk(CodeCompletionString::CK_CurrentParameter, 2873234353Sdim Result.getAllocator().CopyString(ArgString)); 2874198092Srdivacky else 2875218893Sdim Result.AddTextChunk(Result.getAllocator().CopyString(ArgString)); 2876198092Srdivacky } 2877198092Srdivacky 2878198092Srdivacky if (Proto && Proto->isVariadic()) { 2879234353Sdim Result.AddChunk(CodeCompletionString::CK_Comma); 2880198092Srdivacky if (CurrentArg < NumParams) 2881218893Sdim Result.AddTextChunk("..."); 2882198092Srdivacky else 2883234353Sdim Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); 2884198092Srdivacky } 2885234353Sdim Result.AddChunk(CodeCompletionString::CK_RightParen); 2886198092Srdivacky 2887218893Sdim return Result.TakeString(); 2888198092Srdivacky} 2889198092Srdivacky 2890226633Sdimunsigned clang::getMacroUsagePriority(StringRef MacroName, 2891218893Sdim const LangOptions &LangOpts, 2892212904Sdim bool PreferredTypeIsPointer) { 2893212904Sdim unsigned Priority = CCP_Macro; 2894212904Sdim 2895218893Sdim // Treat the "nil", "Nil" and "NULL" macros as null pointer constants. 2896218893Sdim if (MacroName.equals("nil") || MacroName.equals("NULL") || 2897218893Sdim MacroName.equals("Nil")) { 2898212904Sdim Priority = CCP_Constant; 2899212904Sdim if (PreferredTypeIsPointer) 2900212904Sdim Priority = Priority / CCF_SimilarTypeMatch; 2901218893Sdim } 2902218893Sdim // Treat "YES", "NO", "true", and "false" as constants. 2903218893Sdim else if (MacroName.equals("YES") || MacroName.equals("NO") || 2904218893Sdim MacroName.equals("true") || MacroName.equals("false")) 2905218893Sdim Priority = CCP_Constant; 2906218893Sdim // Treat "bool" as a type. 2907218893Sdim else if (MacroName.equals("bool")) 2908218893Sdim Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0); 2909218893Sdim 2910212904Sdim 2911212904Sdim return Priority; 2912212904Sdim} 2913200583Srdivacky 2914249423SdimCXCursorKind clang::getCursorKindForDecl(const Decl *D) { 2915212904Sdim if (!D) 2916212904Sdim return CXCursor_UnexposedDecl; 2917212904Sdim 2918212904Sdim switch (D->getKind()) { 2919212904Sdim case Decl::Enum: return CXCursor_EnumDecl; 2920212904Sdim case Decl::EnumConstant: return CXCursor_EnumConstantDecl; 2921212904Sdim case Decl::Field: return CXCursor_FieldDecl; 2922212904Sdim case Decl::Function: 2923212904Sdim return CXCursor_FunctionDecl; 2924212904Sdim case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl; 2925212904Sdim case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl; 2926212904Sdim case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl; 2927234353Sdim 2928212904Sdim case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl; 2929212904Sdim case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl; 2930212904Sdim case Decl::ObjCMethod: 2931212904Sdim return cast<ObjCMethodDecl>(D)->isInstanceMethod() 2932212904Sdim ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl; 2933212904Sdim case Decl::CXXMethod: return CXCursor_CXXMethod; 2934212904Sdim case Decl::CXXConstructor: return CXCursor_Constructor; 2935212904Sdim case Decl::CXXDestructor: return CXCursor_Destructor; 2936212904Sdim case Decl::CXXConversion: return CXCursor_ConversionFunction; 2937212904Sdim case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl; 2938212904Sdim case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl; 2939212904Sdim case Decl::ParmVar: return CXCursor_ParmDecl; 2940212904Sdim case Decl::Typedef: return CXCursor_TypedefDecl; 2941221345Sdim case Decl::TypeAlias: return CXCursor_TypeAliasDecl; 2942212904Sdim case Decl::Var: return CXCursor_VarDecl; 2943212904Sdim case Decl::Namespace: return CXCursor_Namespace; 2944212904Sdim case Decl::NamespaceAlias: return CXCursor_NamespaceAlias; 2945212904Sdim case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter; 2946212904Sdim case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter; 2947212904Sdim case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter; 2948212904Sdim case Decl::FunctionTemplate: return CXCursor_FunctionTemplate; 2949212904Sdim case Decl::ClassTemplate: return CXCursor_ClassTemplate; 2950226633Sdim case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier; 2951212904Sdim case Decl::ClassTemplatePartialSpecialization: 2952212904Sdim return CXCursor_ClassTemplatePartialSpecialization; 2953212904Sdim case Decl::UsingDirective: return CXCursor_UsingDirective; 2954239462Sdim case Decl::TranslationUnit: return CXCursor_TranslationUnit; 2955198092Srdivacky 2956212904Sdim case Decl::Using: 2957212904Sdim case Decl::UnresolvedUsingValue: 2958212904Sdim case Decl::UnresolvedUsingTypename: 2959212904Sdim return CXCursor_UsingDeclaration; 2960212904Sdim 2961223017Sdim case Decl::ObjCPropertyImpl: 2962223017Sdim switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { 2963223017Sdim case ObjCPropertyImplDecl::Dynamic: 2964223017Sdim return CXCursor_ObjCDynamicDecl; 2965223017Sdim 2966223017Sdim case ObjCPropertyImplDecl::Synthesize: 2967223017Sdim return CXCursor_ObjCSynthesizeDecl; 2968223017Sdim } 2969243830Sdim 2970243830Sdim case Decl::Import: 2971243830Sdim return CXCursor_ModuleImportDecl; 2972223017Sdim 2973212904Sdim default: 2974249423Sdim if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { 2975212904Sdim switch (TD->getTagKind()) { 2976243830Sdim case TTK_Interface: // fall through 2977212904Sdim case TTK_Struct: return CXCursor_StructDecl; 2978212904Sdim case TTK_Class: return CXCursor_ClassDecl; 2979212904Sdim case TTK_Union: return CXCursor_UnionDecl; 2980212904Sdim case TTK_Enum: return CXCursor_EnumDecl; 2981212904Sdim } 2982199512Srdivacky } 2983212904Sdim } 2984212904Sdim 2985212904Sdim return CXCursor_UnexposedDecl; 2986198092Srdivacky} 2987198092Srdivacky 2988210299Sedstatic void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, 2989243830Sdim bool IncludeUndefined, 2990210299Sed bool TargetTypeIsPointer = false) { 2991212904Sdim typedef CodeCompletionResult Result; 2992210299Sed 2993198893Srdivacky Results.EnterNewScope(); 2994218893Sdim 2995199482Srdivacky for (Preprocessor::macro_iterator M = PP.macro_begin(), 2996199482Srdivacky MEnd = PP.macro_end(); 2997210299Sed M != MEnd; ++M) { 2998243830Sdim if (IncludeUndefined || M->first->hasMacroDefinition()) 2999243830Sdim Results.AddResult(Result(M->first, 3000212904Sdim getMacroUsagePriority(M->first->getName(), 3001234353Sdim PP.getLangOpts(), 3002212904Sdim TargetTypeIsPointer))); 3003210299Sed } 3004218893Sdim 3005198893Srdivacky Results.ExitScope(); 3006218893Sdim 3007198893Srdivacky} 3008198893Srdivacky 3009212904Sdimstatic void AddPrettyFunctionResults(const LangOptions &LangOpts, 3010212904Sdim ResultBuilder &Results) { 3011212904Sdim typedef CodeCompletionResult Result; 3012212904Sdim 3013212904Sdim Results.EnterNewScope(); 3014218893Sdim 3015212904Sdim Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant)); 3016212904Sdim Results.AddResult(Result("__FUNCTION__", CCP_Constant)); 3017249423Sdim if (LangOpts.C99 || LangOpts.CPlusPlus11) 3018212904Sdim Results.AddResult(Result("__func__", CCP_Constant)); 3019212904Sdim Results.ExitScope(); 3020212904Sdim} 3021212904Sdim 3022199482Srdivackystatic void HandleCodeCompleteResults(Sema *S, 3023199482Srdivacky CodeCompleteConsumer *CodeCompleter, 3024212904Sdim CodeCompletionContext Context, 3025212904Sdim CodeCompletionResult *Results, 3026212904Sdim unsigned NumResults) { 3027198092Srdivacky if (CodeCompleter) 3028212904Sdim CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); 3029198092Srdivacky} 3030198092Srdivacky 3031212904Sdimstatic enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S, 3032212904Sdim Sema::ParserCompletionContext PCC) { 3033212904Sdim switch (PCC) { 3034212904Sdim case Sema::PCC_Namespace: 3035212904Sdim return CodeCompletionContext::CCC_TopLevel; 3036212904Sdim 3037212904Sdim case Sema::PCC_Class: 3038212904Sdim return CodeCompletionContext::CCC_ClassStructUnion; 3039212904Sdim 3040212904Sdim case Sema::PCC_ObjCInterface: 3041212904Sdim return CodeCompletionContext::CCC_ObjCInterface; 3042212904Sdim 3043212904Sdim case Sema::PCC_ObjCImplementation: 3044212904Sdim return CodeCompletionContext::CCC_ObjCImplementation; 3045212904Sdim 3046212904Sdim case Sema::PCC_ObjCInstanceVariableList: 3047212904Sdim return CodeCompletionContext::CCC_ObjCIvarList; 3048212904Sdim 3049212904Sdim case Sema::PCC_Template: 3050212904Sdim case Sema::PCC_MemberTemplate: 3051218893Sdim if (S.CurContext->isFileContext()) 3052218893Sdim return CodeCompletionContext::CCC_TopLevel; 3053234353Sdim if (S.CurContext->isRecord()) 3054218893Sdim return CodeCompletionContext::CCC_ClassStructUnion; 3055234353Sdim return CodeCompletionContext::CCC_Other; 3056218893Sdim 3057212904Sdim case Sema::PCC_RecoveryInFunction: 3058218893Sdim return CodeCompletionContext::CCC_Recovery; 3059218893Sdim 3060218893Sdim case Sema::PCC_ForInit: 3061234353Sdim if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 || 3062234353Sdim S.getLangOpts().ObjC1) 3063218893Sdim return CodeCompletionContext::CCC_ParenthesizedExpression; 3064218893Sdim else 3065218893Sdim return CodeCompletionContext::CCC_Expression; 3066218893Sdim 3067212904Sdim case Sema::PCC_Expression: 3068212904Sdim case Sema::PCC_Condition: 3069212904Sdim return CodeCompletionContext::CCC_Expression; 3070212904Sdim 3071212904Sdim case Sema::PCC_Statement: 3072212904Sdim return CodeCompletionContext::CCC_Statement; 3073212904Sdim 3074212904Sdim case Sema::PCC_Type: 3075212904Sdim return CodeCompletionContext::CCC_Type; 3076218893Sdim 3077218893Sdim case Sema::PCC_ParenthesizedExpression: 3078218893Sdim return CodeCompletionContext::CCC_ParenthesizedExpression; 3079218893Sdim 3080218893Sdim case Sema::PCC_LocalDeclarationSpecifiers: 3081218893Sdim return CodeCompletionContext::CCC_Type; 3082212904Sdim } 3083234353Sdim 3084234353Sdim llvm_unreachable("Invalid ParserCompletionContext!"); 3085212904Sdim} 3086212904Sdim 3087212904Sdim/// \brief If we're in a C++ virtual member function, add completion results 3088212904Sdim/// that invoke the functions we override, since it's common to invoke the 3089212904Sdim/// overridden function as well as adding new functionality. 3090212904Sdim/// 3091212904Sdim/// \param S The semantic analysis object for which we are generating results. 3092212904Sdim/// 3093212904Sdim/// \param InContext This context in which the nested-name-specifier preceding 3094212904Sdim/// the code-completion point 3095212904Sdimstatic void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, 3096212904Sdim ResultBuilder &Results) { 3097212904Sdim // Look through blocks. 3098212904Sdim DeclContext *CurContext = S.CurContext; 3099212904Sdim while (isa<BlockDecl>(CurContext)) 3100212904Sdim CurContext = CurContext->getParent(); 3101212904Sdim 3102212904Sdim 3103212904Sdim CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext); 3104212904Sdim if (!Method || !Method->isVirtual()) 3105212904Sdim return; 3106212904Sdim 3107212904Sdim // We need to have names for all of the parameters, if we're going to 3108212904Sdim // generate a forwarding call. 3109212904Sdim for (CXXMethodDecl::param_iterator P = Method->param_begin(), 3110212904Sdim PEnd = Method->param_end(); 3111212904Sdim P != PEnd; 3112212904Sdim ++P) { 3113212904Sdim if (!(*P)->getDeclName()) 3114212904Sdim return; 3115212904Sdim } 3116212904Sdim 3117226633Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(S); 3118212904Sdim for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(), 3119212904Sdim MEnd = Method->end_overridden_methods(); 3120212904Sdim M != MEnd; ++M) { 3121234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 3122234353Sdim Results.getCodeCompletionTUInfo()); 3123249423Sdim const CXXMethodDecl *Overridden = *M; 3124212904Sdim if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl()) 3125212904Sdim continue; 3126212904Sdim 3127212904Sdim // If we need a nested-name-specifier, add one now. 3128212904Sdim if (!InContext) { 3129212904Sdim NestedNameSpecifier *NNS 3130212904Sdim = getRequiredQualification(S.Context, CurContext, 3131212904Sdim Overridden->getDeclContext()); 3132212904Sdim if (NNS) { 3133212904Sdim std::string Str; 3134212904Sdim llvm::raw_string_ostream OS(Str); 3135226633Sdim NNS->print(OS, Policy); 3136218893Sdim Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str())); 3137212904Sdim } 3138212904Sdim } else if (!InContext->Equals(Overridden->getDeclContext())) 3139212904Sdim continue; 3140212904Sdim 3141218893Sdim Builder.AddTypedTextChunk(Results.getAllocator().CopyString( 3142218893Sdim Overridden->getNameAsString())); 3143218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 3144212904Sdim bool FirstParam = true; 3145212904Sdim for (CXXMethodDecl::param_iterator P = Method->param_begin(), 3146212904Sdim PEnd = Method->param_end(); 3147212904Sdim P != PEnd; ++P) { 3148212904Sdim if (FirstParam) 3149212904Sdim FirstParam = false; 3150212904Sdim else 3151218893Sdim Builder.AddChunk(CodeCompletionString::CK_Comma); 3152212904Sdim 3153218893Sdim Builder.AddPlaceholderChunk(Results.getAllocator().CopyString( 3154218893Sdim (*P)->getIdentifier()->getName())); 3155212904Sdim } 3156218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 3157218893Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString(), 3158212904Sdim CCP_SuperCompletion, 3159234353Sdim CXCursor_CXXMethod, 3160234353Sdim CXAvailability_Available, 3161234353Sdim Overridden)); 3162212904Sdim Results.Ignore(Overridden); 3163212904Sdim } 3164212904Sdim} 3165212904Sdim 3166234353Sdimvoid Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, 3167234353Sdim ModuleIdPath Path) { 3168234353Sdim typedef CodeCompletionResult Result; 3169234353Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3170234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 3171234353Sdim CodeCompletionContext::CCC_Other); 3172234353Sdim Results.EnterNewScope(); 3173234353Sdim 3174234353Sdim CodeCompletionAllocator &Allocator = Results.getAllocator(); 3175234353Sdim CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); 3176234353Sdim typedef CodeCompletionResult Result; 3177234353Sdim if (Path.empty()) { 3178234353Sdim // Enumerate all top-level modules. 3179249423Sdim SmallVector<Module *, 8> Modules; 3180234353Sdim PP.getHeaderSearchInfo().collectAllModules(Modules); 3181234353Sdim for (unsigned I = 0, N = Modules.size(); I != N; ++I) { 3182234353Sdim Builder.AddTypedTextChunk( 3183234353Sdim Builder.getAllocator().CopyString(Modules[I]->Name)); 3184234353Sdim Results.AddResult(Result(Builder.TakeString(), 3185234353Sdim CCP_Declaration, 3186234353Sdim CXCursor_NotImplemented, 3187234353Sdim Modules[I]->isAvailable() 3188234353Sdim ? CXAvailability_Available 3189234353Sdim : CXAvailability_NotAvailable)); 3190234353Sdim } 3191234353Sdim } else { 3192234353Sdim // Load the named module. 3193234353Sdim Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path, 3194234353Sdim Module::AllVisible, 3195234353Sdim /*IsInclusionDirective=*/false); 3196234353Sdim // Enumerate submodules. 3197234353Sdim if (Mod) { 3198234353Sdim for (Module::submodule_iterator Sub = Mod->submodule_begin(), 3199234353Sdim SubEnd = Mod->submodule_end(); 3200234353Sdim Sub != SubEnd; ++Sub) { 3201234353Sdim 3202234353Sdim Builder.AddTypedTextChunk( 3203234353Sdim Builder.getAllocator().CopyString((*Sub)->Name)); 3204234353Sdim Results.AddResult(Result(Builder.TakeString(), 3205234353Sdim CCP_Declaration, 3206234353Sdim CXCursor_NotImplemented, 3207234353Sdim (*Sub)->isAvailable() 3208234353Sdim ? CXAvailability_Available 3209234353Sdim : CXAvailability_NotAvailable)); 3210234353Sdim } 3211234353Sdim } 3212234353Sdim } 3213234353Sdim Results.ExitScope(); 3214234353Sdim HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), 3215234353Sdim Results.data(),Results.size()); 3216234353Sdim} 3217234353Sdim 3218202379Srdivackyvoid Sema::CodeCompleteOrdinaryName(Scope *S, 3219212904Sdim ParserCompletionContext CompletionContext) { 3220218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3221234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 3222218893Sdim mapCodeCompletionContext(*this, CompletionContext)); 3223212904Sdim Results.EnterNewScope(); 3224218893Sdim 3225202379Srdivacky // Determine how to filter results, e.g., so that the names of 3226202379Srdivacky // values (functions, enumerators, function templates, etc.) are 3227202379Srdivacky // only allowed where we can have an expression. 3228202379Srdivacky switch (CompletionContext) { 3229212904Sdim case PCC_Namespace: 3230212904Sdim case PCC_Class: 3231212904Sdim case PCC_ObjCInterface: 3232212904Sdim case PCC_ObjCImplementation: 3233212904Sdim case PCC_ObjCInstanceVariableList: 3234212904Sdim case PCC_Template: 3235212904Sdim case PCC_MemberTemplate: 3236212904Sdim case PCC_Type: 3237218893Sdim case PCC_LocalDeclarationSpecifiers: 3238202379Srdivacky Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); 3239202379Srdivacky break; 3240202379Srdivacky 3241212904Sdim case PCC_Statement: 3242218893Sdim case PCC_ParenthesizedExpression: 3243212904Sdim case PCC_Expression: 3244212904Sdim case PCC_ForInit: 3245212904Sdim case PCC_Condition: 3246234353Sdim if (WantTypesInContext(CompletionContext, getLangOpts())) 3247210299Sed Results.setFilter(&ResultBuilder::IsOrdinaryName); 3248210299Sed else 3249210299Sed Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); 3250212904Sdim 3251234353Sdim if (getLangOpts().CPlusPlus) 3252212904Sdim MaybeAddOverrideCalls(*this, /*InContext=*/0, Results); 3253202379Srdivacky break; 3254208600Srdivacky 3255212904Sdim case PCC_RecoveryInFunction: 3256208600Srdivacky // Unfiltered 3257208600Srdivacky break; 3258200583Srdivacky } 3259200583Srdivacky 3260212904Sdim // If we are in a C++ non-static member function, check the qualifiers on 3261212904Sdim // the member function to filter/prioritize the results list. 3262212904Sdim if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) 3263212904Sdim if (CurMethod->isInstance()) 3264212904Sdim Results.setObjectTypeQualifiers( 3265212904Sdim Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers())); 3266212904Sdim 3267202379Srdivacky CodeCompletionDeclConsumer Consumer(Results, CurContext); 3268212904Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 3269212904Sdim CodeCompleter->includeGlobals()); 3270202379Srdivacky 3271202379Srdivacky AddOrdinaryNameResults(CompletionContext, S, *this, Results); 3272200583Srdivacky Results.ExitScope(); 3273200583Srdivacky 3274212904Sdim switch (CompletionContext) { 3275218893Sdim case PCC_ParenthesizedExpression: 3276212904Sdim case PCC_Expression: 3277212904Sdim case PCC_Statement: 3278212904Sdim case PCC_RecoveryInFunction: 3279212904Sdim if (S->getFnParent()) 3280234353Sdim AddPrettyFunctionResults(PP.getLangOpts(), Results); 3281212904Sdim break; 3282212904Sdim 3283212904Sdim case PCC_Namespace: 3284212904Sdim case PCC_Class: 3285212904Sdim case PCC_ObjCInterface: 3286212904Sdim case PCC_ObjCImplementation: 3287212904Sdim case PCC_ObjCInstanceVariableList: 3288212904Sdim case PCC_Template: 3289212904Sdim case PCC_MemberTemplate: 3290212904Sdim case PCC_ForInit: 3291212904Sdim case PCC_Condition: 3292212904Sdim case PCC_Type: 3293218893Sdim case PCC_LocalDeclarationSpecifiers: 3294212904Sdim break; 3295212904Sdim } 3296212904Sdim 3297199482Srdivacky if (CodeCompleter->includeMacros()) 3298243830Sdim AddMacroResults(PP, Results, false); 3299212904Sdim 3300218893Sdim HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), 3301212904Sdim Results.data(),Results.size()); 3302198092Srdivacky} 3303198092Srdivacky 3304218893Sdimstatic void AddClassMessageCompletions(Sema &SemaRef, Scope *S, 3305218893Sdim ParsedType Receiver, 3306218893Sdim IdentifierInfo **SelIdents, 3307218893Sdim unsigned NumSelIdents, 3308218893Sdim bool AtArgumentExpression, 3309218893Sdim bool IsSuper, 3310218893Sdim ResultBuilder &Results); 3311218893Sdim 3312218893Sdimvoid Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, 3313218893Sdim bool AllowNonIdentifiers, 3314218893Sdim bool AllowNestedNameSpecifiers) { 3315212904Sdim typedef CodeCompletionResult Result; 3316218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3317234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 3318218893Sdim AllowNestedNameSpecifiers 3319218893Sdim ? CodeCompletionContext::CCC_PotentiallyQualifiedName 3320218893Sdim : CodeCompletionContext::CCC_Name); 3321212904Sdim Results.EnterNewScope(); 3322212904Sdim 3323212904Sdim // Type qualifiers can come after names. 3324212904Sdim Results.AddResult(Result("const")); 3325212904Sdim Results.AddResult(Result("volatile")); 3326234353Sdim if (getLangOpts().C99) 3327212904Sdim Results.AddResult(Result("restrict")); 3328212904Sdim 3329234353Sdim if (getLangOpts().CPlusPlus) { 3330212904Sdim if (AllowNonIdentifiers) { 3331212904Sdim Results.AddResult(Result("operator")); 3332212904Sdim } 3333212904Sdim 3334212904Sdim // Add nested-name-specifiers. 3335212904Sdim if (AllowNestedNameSpecifiers) { 3336212904Sdim Results.allowNestedNameSpecifiers(); 3337218893Sdim Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy); 3338212904Sdim CodeCompletionDeclConsumer Consumer(Results, CurContext); 3339212904Sdim LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, 3340212904Sdim CodeCompleter->includeGlobals()); 3341218893Sdim Results.setFilter(0); 3342212904Sdim } 3343212904Sdim } 3344212904Sdim Results.ExitScope(); 3345212904Sdim 3346218893Sdim // If we're in a context where we might have an expression (rather than a 3347218893Sdim // declaration), and what we've seen so far is an Objective-C type that could 3348218893Sdim // be a receiver of a class message, this may be a class message send with 3349218893Sdim // the initial opening bracket '[' missing. Add appropriate completions. 3350218893Sdim if (AllowNonIdentifiers && !AllowNestedNameSpecifiers && 3351251662Sdim DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier && 3352218893Sdim DS.getTypeSpecType() == DeclSpec::TST_typename && 3353218893Sdim DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && 3354218893Sdim DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && 3355251662Sdim !DS.isTypeAltiVecVector() && 3356251662Sdim S && 3357218893Sdim (S->getFlags() & Scope::DeclScope) != 0 && 3358218893Sdim (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | 3359218893Sdim Scope::FunctionPrototypeScope | 3360218893Sdim Scope::AtCatchScope)) == 0) { 3361218893Sdim ParsedType T = DS.getRepAsType(); 3362218893Sdim if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) 3363218893Sdim AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results); 3364218893Sdim } 3365218893Sdim 3366212904Sdim // Note that we intentionally suppress macro results here, since we do not 3367212904Sdim // encourage using macros to produce the names of entities. 3368212904Sdim 3369218893Sdim HandleCodeCompleteResults(this, CodeCompleter, 3370218893Sdim Results.getCompletionContext(), 3371212904Sdim Results.data(), Results.size()); 3372212904Sdim} 3373212904Sdim 3374212904Sdimstruct Sema::CodeCompleteExpressionData { 3375212904Sdim CodeCompleteExpressionData(QualType PreferredType = QualType()) 3376212904Sdim : PreferredType(PreferredType), IntegralConstantExpression(false), 3377212904Sdim ObjCCollection(false) { } 3378212904Sdim 3379212904Sdim QualType PreferredType; 3380212904Sdim bool IntegralConstantExpression; 3381212904Sdim bool ObjCCollection; 3382226633Sdim SmallVector<Decl *, 4> IgnoreDecls; 3383212904Sdim}; 3384212904Sdim 3385210299Sed/// \brief Perform code-completion in an expression context when we know what 3386210299Sed/// type we're looking for. 3387212904Sdimvoid Sema::CodeCompleteExpression(Scope *S, 3388212904Sdim const CodeCompleteExpressionData &Data) { 3389218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3390234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 3391218893Sdim CodeCompletionContext::CCC_Expression); 3392212904Sdim if (Data.ObjCCollection) 3393212904Sdim Results.setFilter(&ResultBuilder::IsObjCCollection); 3394212904Sdim else if (Data.IntegralConstantExpression) 3395212904Sdim Results.setFilter(&ResultBuilder::IsIntegralConstantValue); 3396234353Sdim else if (WantTypesInContext(PCC_Expression, getLangOpts())) 3397210299Sed Results.setFilter(&ResultBuilder::IsOrdinaryName); 3398210299Sed else 3399210299Sed Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); 3400212904Sdim 3401212904Sdim if (!Data.PreferredType.isNull()) 3402212904Sdim Results.setPreferredType(Data.PreferredType.getNonReferenceType()); 3403210299Sed 3404212904Sdim // Ignore any declarations that we were told that we don't care about. 3405212904Sdim for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I) 3406212904Sdim Results.Ignore(Data.IgnoreDecls[I]); 3407212904Sdim 3408210299Sed CodeCompletionDeclConsumer Consumer(Results, CurContext); 3409212904Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 3410212904Sdim CodeCompleter->includeGlobals()); 3411210299Sed 3412210299Sed Results.EnterNewScope(); 3413212904Sdim AddOrdinaryNameResults(PCC_Expression, S, *this, Results); 3414210299Sed Results.ExitScope(); 3415210299Sed 3416210299Sed bool PreferredTypeIsPointer = false; 3417212904Sdim if (!Data.PreferredType.isNull()) 3418212904Sdim PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() 3419212904Sdim || Data.PreferredType->isMemberPointerType() 3420212904Sdim || Data.PreferredType->isBlockPointerType(); 3421210299Sed 3422212904Sdim if (S->getFnParent() && 3423212904Sdim !Data.ObjCCollection && 3424212904Sdim !Data.IntegralConstantExpression) 3425234353Sdim AddPrettyFunctionResults(PP.getLangOpts(), Results); 3426212904Sdim 3427210299Sed if (CodeCompleter->includeMacros()) 3428243830Sdim AddMacroResults(PP, Results, false, PreferredTypeIsPointer); 3429212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 3430212904Sdim CodeCompletionContext(CodeCompletionContext::CCC_Expression, 3431212904Sdim Data.PreferredType), 3432212904Sdim Results.data(),Results.size()); 3433210299Sed} 3434210299Sed 3435218893Sdimvoid Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) { 3436218893Sdim if (E.isInvalid()) 3437218893Sdim CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction); 3438234353Sdim else if (getLangOpts().ObjC1) 3439218893Sdim CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false); 3440218893Sdim} 3441210299Sed 3442218893Sdim/// \brief The set of properties that have already been added, referenced by 3443218893Sdim/// property name. 3444218893Sdimtypedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet; 3445218893Sdim 3446239462Sdim/// \brief Retrieve the container definition, if any? 3447239462Sdimstatic ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) { 3448239462Sdim if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { 3449239462Sdim if (Interface->hasDefinition()) 3450239462Sdim return Interface->getDefinition(); 3451239462Sdim 3452239462Sdim return Interface; 3453239462Sdim } 3454239462Sdim 3455239462Sdim if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { 3456239462Sdim if (Protocol->hasDefinition()) 3457239462Sdim return Protocol->getDefinition(); 3458239462Sdim 3459239462Sdim return Protocol; 3460239462Sdim } 3461239462Sdim return Container; 3462239462Sdim} 3463239462Sdim 3464239462Sdimstatic void AddObjCProperties(ObjCContainerDecl *Container, 3465199512Srdivacky bool AllowCategories, 3466223017Sdim bool AllowNullaryMethods, 3467199482Srdivacky DeclContext *CurContext, 3468218893Sdim AddedPropertiesSet &AddedProperties, 3469199482Srdivacky ResultBuilder &Results) { 3470212904Sdim typedef CodeCompletionResult Result; 3471199482Srdivacky 3472239462Sdim // Retrieve the definition. 3473239462Sdim Container = getContainerDef(Container); 3474239462Sdim 3475199482Srdivacky // Add properties in this container. 3476199482Srdivacky for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(), 3477199482Srdivacky PEnd = Container->prop_end(); 3478199482Srdivacky P != PEnd; 3479218893Sdim ++P) { 3480218893Sdim if (AddedProperties.insert(P->getIdentifier())) 3481249423Sdim Results.MaybeAddResult(Result(*P, Results.getBasePriority(*P), 0), 3482249423Sdim CurContext); 3483218893Sdim } 3484199482Srdivacky 3485223017Sdim // Add nullary methods 3486223017Sdim if (AllowNullaryMethods) { 3487223017Sdim ASTContext &Context = Container->getASTContext(); 3488226633Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema()); 3489223017Sdim for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), 3490223017Sdim MEnd = Container->meth_end(); 3491223017Sdim M != MEnd; ++M) { 3492223017Sdim if (M->getSelector().isUnarySelector()) 3493223017Sdim if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0)) 3494223017Sdim if (AddedProperties.insert(Name)) { 3495234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 3496234353Sdim Results.getCodeCompletionTUInfo()); 3497226633Sdim AddResultTypeChunk(Context, Policy, *M, Builder); 3498223017Sdim Builder.AddTypedTextChunk( 3499223017Sdim Results.getAllocator().CopyString(Name->getName())); 3500223017Sdim 3501234353Sdim Results.MaybeAddResult(Result(Builder.TakeString(), *M, 3502234353Sdim CCP_MemberDeclaration + CCD_MethodAsProperty), 3503223017Sdim CurContext); 3504223017Sdim } 3505223017Sdim } 3506223017Sdim } 3507223017Sdim 3508223017Sdim 3509199482Srdivacky // Add properties in referenced protocols. 3510199482Srdivacky if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { 3511199482Srdivacky for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), 3512199482Srdivacky PEnd = Protocol->protocol_end(); 3513199482Srdivacky P != PEnd; ++P) 3514223017Sdim AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, 3515223017Sdim AddedProperties, Results); 3516199482Srdivacky } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){ 3517199512Srdivacky if (AllowCategories) { 3518199512Srdivacky // Look through categories. 3519249423Sdim for (ObjCInterfaceDecl::known_categories_iterator 3520249423Sdim Cat = IFace->known_categories_begin(), 3521249423Sdim CatEnd = IFace->known_categories_end(); 3522249423Sdim Cat != CatEnd; ++Cat) 3523249423Sdim AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods, 3524223017Sdim CurContext, AddedProperties, Results); 3525199512Srdivacky } 3526199482Srdivacky 3527199482Srdivacky // Look through protocols. 3528212904Sdim for (ObjCInterfaceDecl::all_protocol_iterator 3529212904Sdim I = IFace->all_referenced_protocol_begin(), 3530212904Sdim E = IFace->all_referenced_protocol_end(); I != E; ++I) 3531223017Sdim AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext, 3532223017Sdim AddedProperties, Results); 3533199482Srdivacky 3534199482Srdivacky // Look in the superclass. 3535199482Srdivacky if (IFace->getSuperClass()) 3536223017Sdim AddObjCProperties(IFace->getSuperClass(), AllowCategories, 3537223017Sdim AllowNullaryMethods, CurContext, 3538218893Sdim AddedProperties, Results); 3539199482Srdivacky } else if (const ObjCCategoryDecl *Category 3540199482Srdivacky = dyn_cast<ObjCCategoryDecl>(Container)) { 3541199482Srdivacky // Look through protocols. 3542212904Sdim for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), 3543212904Sdim PEnd = Category->protocol_end(); 3544199482Srdivacky P != PEnd; ++P) 3545223017Sdim AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext, 3546223017Sdim AddedProperties, Results); 3547199482Srdivacky } 3548199482Srdivacky} 3549199482Srdivacky 3550234353Sdimvoid Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, 3551198092Srdivacky SourceLocation OpLoc, 3552198092Srdivacky bool IsArrow) { 3553234353Sdim if (!Base || !CodeCompleter) 3554198092Srdivacky return; 3555198092Srdivacky 3556234353Sdim ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); 3557234353Sdim if (ConvertedBase.isInvalid()) 3558234353Sdim return; 3559234353Sdim Base = ConvertedBase.get(); 3560234353Sdim 3561212904Sdim typedef CodeCompletionResult Result; 3562198092Srdivacky 3563198092Srdivacky QualType BaseType = Base->getType(); 3564198092Srdivacky 3565198092Srdivacky if (IsArrow) { 3566198092Srdivacky if (const PointerType *Ptr = BaseType->getAs<PointerType>()) 3567198092Srdivacky BaseType = Ptr->getPointeeType(); 3568198092Srdivacky else if (BaseType->isObjCObjectPointerType()) 3569212904Sdim /*Do nothing*/ ; 3570198092Srdivacky else 3571198092Srdivacky return; 3572198092Srdivacky } 3573198092Srdivacky 3574224145Sdim enum CodeCompletionContext::Kind contextKind; 3575224145Sdim 3576224145Sdim if (IsArrow) { 3577224145Sdim contextKind = CodeCompletionContext::CCC_ArrowMemberAccess; 3578224145Sdim } 3579224145Sdim else { 3580224145Sdim if (BaseType->isObjCObjectPointerType() || 3581224145Sdim BaseType->isObjCObjectOrInterfaceType()) { 3582224145Sdim contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess; 3583224145Sdim } 3584224145Sdim else { 3585224145Sdim contextKind = CodeCompletionContext::CCC_DotMemberAccess; 3586224145Sdim } 3587224145Sdim } 3588224145Sdim 3589218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3590234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 3591224145Sdim CodeCompletionContext(contextKind, 3592218893Sdim BaseType), 3593218893Sdim &ResultBuilder::IsMember); 3594199482Srdivacky Results.EnterNewScope(); 3595198092Srdivacky if (const RecordType *Record = BaseType->getAs<RecordType>()) { 3596212904Sdim // Indicate that we are performing a member access, and the cv-qualifiers 3597212904Sdim // for the base object type. 3598212904Sdim Results.setObjectTypeQualifiers(BaseType.getQualifiers()); 3599212904Sdim 3600199482Srdivacky // Access to a C/C++ class, struct, or union. 3601202379Srdivacky Results.allowNestedNameSpecifiers(); 3602202379Srdivacky CodeCompletionDeclConsumer Consumer(Results, CurContext); 3603212904Sdim LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer, 3604212904Sdim CodeCompleter->includeGlobals()); 3605199482Srdivacky 3606234353Sdim if (getLangOpts().CPlusPlus) { 3607198092Srdivacky if (!Results.empty()) { 3608198092Srdivacky // The "template" keyword can follow "->" or "." in the grammar. 3609198092Srdivacky // However, we only want to suggest the template keyword if something 3610198092Srdivacky // is dependent. 3611198092Srdivacky bool IsDependent = BaseType->isDependentType(); 3612198092Srdivacky if (!IsDependent) { 3613198092Srdivacky for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) 3614198092Srdivacky if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) { 3615198092Srdivacky IsDependent = Ctx->isDependentContext(); 3616198092Srdivacky break; 3617198092Srdivacky } 3618198092Srdivacky } 3619199482Srdivacky 3620198092Srdivacky if (IsDependent) 3621202379Srdivacky Results.AddResult(Result("template")); 3622198092Srdivacky } 3623198092Srdivacky } 3624199482Srdivacky } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) { 3625199482Srdivacky // Objective-C property reference. 3626218893Sdim AddedPropertiesSet AddedProperties; 3627198092Srdivacky 3628199482Srdivacky // Add property results based on our interface. 3629199482Srdivacky const ObjCObjectPointerType *ObjCPtr 3630199482Srdivacky = BaseType->getAsObjCInterfacePointerType(); 3631199482Srdivacky assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); 3632223017Sdim AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, 3633223017Sdim /*AllowNullaryMethods=*/true, CurContext, 3634218893Sdim AddedProperties, Results); 3635198893Srdivacky 3636199482Srdivacky // Add properties from the protocols in a qualified interface. 3637199482Srdivacky for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(), 3638199482Srdivacky E = ObjCPtr->qual_end(); 3639199482Srdivacky I != E; ++I) 3640223017Sdim AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext, 3641223017Sdim AddedProperties, Results); 3642199482Srdivacky } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || 3643208600Srdivacky (!IsArrow && BaseType->isObjCObjectType())) { 3644199482Srdivacky // Objective-C instance variable access. 3645199482Srdivacky ObjCInterfaceDecl *Class = 0; 3646199482Srdivacky if (const ObjCObjectPointerType *ObjCPtr 3647199482Srdivacky = BaseType->getAs<ObjCObjectPointerType>()) 3648199482Srdivacky Class = ObjCPtr->getInterfaceDecl(); 3649199482Srdivacky else 3650208600Srdivacky Class = BaseType->getAs<ObjCObjectType>()->getInterface(); 3651199482Srdivacky 3652199482Srdivacky // Add all ivars from this class and its superclasses. 3653202379Srdivacky if (Class) { 3654202379Srdivacky CodeCompletionDeclConsumer Consumer(Results, CurContext); 3655202379Srdivacky Results.setFilter(&ResultBuilder::IsObjCIvar); 3656212904Sdim LookupVisibleDecls(Class, LookupMemberName, Consumer, 3657212904Sdim CodeCompleter->includeGlobals()); 3658199482Srdivacky } 3659198092Srdivacky } 3660199482Srdivacky 3661199482Srdivacky // FIXME: How do we cope with isa? 3662199482Srdivacky 3663199482Srdivacky Results.ExitScope(); 3664199482Srdivacky 3665199482Srdivacky // Hand off the results found for code completion. 3666212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 3667218893Sdim Results.getCompletionContext(), 3668212904Sdim Results.data(),Results.size()); 3669198092Srdivacky} 3670198092Srdivacky 3671198092Srdivackyvoid Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { 3672198092Srdivacky if (!CodeCompleter) 3673198092Srdivacky return; 3674198092Srdivacky 3675198092Srdivacky ResultBuilder::LookupFilter Filter = 0; 3676212904Sdim enum CodeCompletionContext::Kind ContextKind 3677212904Sdim = CodeCompletionContext::CCC_Other; 3678198092Srdivacky switch ((DeclSpec::TST)TagSpec) { 3679198092Srdivacky case DeclSpec::TST_enum: 3680198092Srdivacky Filter = &ResultBuilder::IsEnum; 3681212904Sdim ContextKind = CodeCompletionContext::CCC_EnumTag; 3682198092Srdivacky break; 3683198092Srdivacky 3684198092Srdivacky case DeclSpec::TST_union: 3685198092Srdivacky Filter = &ResultBuilder::IsUnion; 3686212904Sdim ContextKind = CodeCompletionContext::CCC_UnionTag; 3687198092Srdivacky break; 3688198092Srdivacky 3689198092Srdivacky case DeclSpec::TST_struct: 3690198092Srdivacky case DeclSpec::TST_class: 3691243830Sdim case DeclSpec::TST_interface: 3692198092Srdivacky Filter = &ResultBuilder::IsClassOrStruct; 3693212904Sdim ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; 3694198092Srdivacky break; 3695198092Srdivacky 3696198092Srdivacky default: 3697226633Sdim llvm_unreachable("Unknown type specifier kind in CodeCompleteTag"); 3698198092Srdivacky } 3699198092Srdivacky 3700234353Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3701234353Sdim CodeCompleter->getCodeCompletionTUInfo(), ContextKind); 3702202379Srdivacky CodeCompletionDeclConsumer Consumer(Results, CurContext); 3703207619Srdivacky 3704207619Srdivacky // First pass: look for tags. 3705207619Srdivacky Results.setFilter(Filter); 3706212904Sdim LookupVisibleDecls(S, LookupTagName, Consumer, 3707212904Sdim CodeCompleter->includeGlobals()); 3708207619Srdivacky 3709212904Sdim if (CodeCompleter->includeGlobals()) { 3710212904Sdim // Second pass: look for nested name specifiers. 3711212904Sdim Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); 3712212904Sdim LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer); 3713212904Sdim } 3714198092Srdivacky 3715218893Sdim HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), 3716212904Sdim Results.data(),Results.size()); 3717198092Srdivacky} 3718198092Srdivacky 3719212904Sdimvoid Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { 3720218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3721234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 3722218893Sdim CodeCompletionContext::CCC_TypeQualifiers); 3723212904Sdim Results.EnterNewScope(); 3724212904Sdim if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const)) 3725212904Sdim Results.AddResult("const"); 3726212904Sdim if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) 3727212904Sdim Results.AddResult("volatile"); 3728234353Sdim if (getLangOpts().C99 && 3729212904Sdim !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) 3730212904Sdim Results.AddResult("restrict"); 3731249423Sdim if (getLangOpts().C11 && 3732249423Sdim !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic)) 3733249423Sdim Results.AddResult("_Atomic"); 3734212904Sdim Results.ExitScope(); 3735212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 3736218893Sdim Results.getCompletionContext(), 3737212904Sdim Results.data(), Results.size()); 3738212904Sdim} 3739212904Sdim 3740198092Srdivackyvoid Sema::CodeCompleteCase(Scope *S) { 3741212904Sdim if (getCurFunction()->SwitchStack.empty() || !CodeCompleter) 3742198092Srdivacky return; 3743226633Sdim 3744212904Sdim SwitchStmt *Switch = getCurFunction()->SwitchStack.back(); 3745226633Sdim QualType type = Switch->getCond()->IgnoreImplicit()->getType(); 3746226633Sdim if (!type->isEnumeralType()) { 3747226633Sdim CodeCompleteExpressionData Data(type); 3748212904Sdim Data.IntegralConstantExpression = true; 3749212904Sdim CodeCompleteExpression(S, Data); 3750198092Srdivacky return; 3751212904Sdim } 3752198092Srdivacky 3753198092Srdivacky // Code-complete the cases of a switch statement over an enumeration type 3754198092Srdivacky // by providing the list of 3755226633Sdim EnumDecl *Enum = type->castAs<EnumType>()->getDecl(); 3756239462Sdim if (EnumDecl *Def = Enum->getDefinition()) 3757239462Sdim Enum = Def; 3758198092Srdivacky 3759198092Srdivacky // Determine which enumerators we have already seen in the switch statement. 3760198092Srdivacky // FIXME: Ideally, we would also be able to look *past* the code-completion 3761198092Srdivacky // token, in case we are code-completing in the middle of the switch and not 3762198092Srdivacky // at the end. However, we aren't able to do so at the moment. 3763198092Srdivacky llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen; 3764198092Srdivacky NestedNameSpecifier *Qualifier = 0; 3765198092Srdivacky for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; 3766198092Srdivacky SC = SC->getNextSwitchCase()) { 3767198092Srdivacky CaseStmt *Case = dyn_cast<CaseStmt>(SC); 3768198092Srdivacky if (!Case) 3769198092Srdivacky continue; 3770198092Srdivacky 3771198092Srdivacky Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); 3772198092Srdivacky if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal)) 3773198092Srdivacky if (EnumConstantDecl *Enumerator 3774198092Srdivacky = dyn_cast<EnumConstantDecl>(DRE->getDecl())) { 3775198092Srdivacky // We look into the AST of the case statement to determine which 3776198092Srdivacky // enumerator was named. Alternatively, we could compute the value of 3777198092Srdivacky // the integral constant expression, then compare it against the 3778198092Srdivacky // values of each enumerator. However, value-based approach would not 3779198092Srdivacky // work as well with C++ templates where enumerators declared within a 3780198092Srdivacky // template are type- and value-dependent. 3781198092Srdivacky EnumeratorsSeen.insert(Enumerator); 3782198092Srdivacky 3783198092Srdivacky // If this is a qualified-id, keep track of the nested-name-specifier 3784198092Srdivacky // so that we can reproduce it as part of code completion, e.g., 3785198092Srdivacky // 3786198092Srdivacky // switch (TagD.getKind()) { 3787198092Srdivacky // case TagDecl::TK_enum: 3788198092Srdivacky // break; 3789198092Srdivacky // case XXX 3790198092Srdivacky // 3791198092Srdivacky // At the XXX, our completions are TagDecl::TK_union, 3792198092Srdivacky // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union, 3793198092Srdivacky // TK_struct, and TK_class. 3794198893Srdivacky Qualifier = DRE->getQualifier(); 3795198092Srdivacky } 3796198092Srdivacky } 3797198092Srdivacky 3798234353Sdim if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) { 3799198092Srdivacky // If there are no prior enumerators in C++, check whether we have to 3800198092Srdivacky // qualify the names of the enumerators that we suggest, because they 3801198092Srdivacky // may not be visible in this scope. 3802234353Sdim Qualifier = getRequiredQualification(Context, CurContext, Enum); 3803198092Srdivacky } 3804198092Srdivacky 3805198092Srdivacky // Add any enumerators that have not yet been mentioned. 3806218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3807234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 3808218893Sdim CodeCompletionContext::CCC_Expression); 3809198092Srdivacky Results.EnterNewScope(); 3810198092Srdivacky for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(), 3811198092Srdivacky EEnd = Enum->enumerator_end(); 3812198092Srdivacky E != EEnd; ++E) { 3813198092Srdivacky if (EnumeratorsSeen.count(*E)) 3814198092Srdivacky continue; 3815198092Srdivacky 3816249423Sdim CodeCompletionResult R(*E, CCP_EnumInCase, Qualifier); 3817218893Sdim Results.AddResult(R, CurContext, 0, false); 3818198092Srdivacky } 3819198092Srdivacky Results.ExitScope(); 3820207619Srdivacky 3821224145Sdim //We need to make sure we're setting the right context, 3822224145Sdim //so only say we include macros if the code completer says we do 3823224145Sdim enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other; 3824224145Sdim if (CodeCompleter->includeMacros()) { 3825243830Sdim AddMacroResults(PP, Results, false); 3826224145Sdim kind = CodeCompletionContext::CCC_OtherWithMacros; 3827224145Sdim } 3828224145Sdim 3829212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 3830224145Sdim kind, 3831212904Sdim Results.data(),Results.size()); 3832198092Srdivacky} 3833198092Srdivacky 3834198092Srdivackynamespace { 3835198092Srdivacky struct IsBetterOverloadCandidate { 3836198092Srdivacky Sema &S; 3837203955Srdivacky SourceLocation Loc; 3838198092Srdivacky 3839198092Srdivacky public: 3840203955Srdivacky explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc) 3841203955Srdivacky : S(S), Loc(Loc) { } 3842198092Srdivacky 3843198092Srdivacky bool 3844198092Srdivacky operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const { 3845212904Sdim return isBetterOverloadCandidate(S, X, Y, Loc); 3846198092Srdivacky } 3847198092Srdivacky }; 3848198092Srdivacky} 3849198092Srdivacky 3850234353Sdimstatic bool anyNullArguments(llvm::ArrayRef<Expr*> Args) { 3851234353Sdim if (Args.size() && !Args.data()) 3852210299Sed return true; 3853234353Sdim 3854234353Sdim for (unsigned I = 0; I != Args.size(); ++I) 3855210299Sed if (!Args[I]) 3856210299Sed return true; 3857234353Sdim 3858210299Sed return false; 3859210299Sed} 3860210299Sed 3861226633Sdimvoid Sema::CodeCompleteCall(Scope *S, Expr *FnIn, 3862234353Sdim llvm::ArrayRef<Expr *> Args) { 3863198092Srdivacky if (!CodeCompleter) 3864198092Srdivacky return; 3865200583Srdivacky 3866200583Srdivacky // When we're code-completing for a call, we fall back to ordinary 3867200583Srdivacky // name code-completion whenever we can't produce specific 3868200583Srdivacky // results. We may want to revisit this strategy in the future, 3869200583Srdivacky // e.g., by merging the two kinds of results. 3870200583Srdivacky 3871198092Srdivacky Expr *Fn = (Expr *)FnIn; 3872200583Srdivacky 3873198092Srdivacky // Ignore type-dependent call expressions entirely. 3874234353Sdim if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || 3875234353Sdim Expr::hasAnyTypeDependentArguments(Args)) { 3876212904Sdim CodeCompleteOrdinaryName(S, PCC_Expression); 3877198092Srdivacky return; 3878200583Srdivacky } 3879198092Srdivacky 3880201361Srdivacky // Build an overload candidate set based on the functions we find. 3881203955Srdivacky SourceLocation Loc = Fn->getExprLoc(); 3882203955Srdivacky OverloadCandidateSet CandidateSet(Loc); 3883201361Srdivacky 3884198092Srdivacky // FIXME: What if we're calling something that isn't a function declaration? 3885198092Srdivacky // FIXME: What if we're calling a pseudo-destructor? 3886198092Srdivacky // FIXME: What if we're calling a member function? 3887198092Srdivacky 3888202879Srdivacky typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; 3889226633Sdim SmallVector<ResultCandidate, 8> Results; 3890202879Srdivacky 3891201361Srdivacky Expr *NakedFn = Fn->IgnoreParenCasts(); 3892201361Srdivacky if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) 3893234353Sdim AddOverloadedCallCandidates(ULE, Args, CandidateSet, 3894201361Srdivacky /*PartialOverloading=*/ true); 3895201361Srdivacky else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) { 3896201361Srdivacky FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl()); 3897202879Srdivacky if (FDecl) { 3898234353Sdim if (!getLangOpts().CPlusPlus || 3899210299Sed !FDecl->getType()->getAs<FunctionProtoType>()) 3900202879Srdivacky Results.push_back(ResultCandidate(FDecl)); 3901202879Srdivacky else 3902203955Srdivacky // FIXME: access? 3903234353Sdim AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args, 3904234353Sdim CandidateSet, false, /*PartialOverloading*/true); 3905202879Srdivacky } 3906201361Srdivacky } 3907198092Srdivacky 3908210299Sed QualType ParamType; 3909210299Sed 3910202879Srdivacky if (!CandidateSet.empty()) { 3911202879Srdivacky // Sort the overload candidate set by placing the best overloads first. 3912202879Srdivacky std::stable_sort(CandidateSet.begin(), CandidateSet.end(), 3913203955Srdivacky IsBetterOverloadCandidate(*this, Loc)); 3914198092Srdivacky 3915202879Srdivacky // Add the remaining viable overload candidates as code-completion reslults. 3916202879Srdivacky for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), 3917202879Srdivacky CandEnd = CandidateSet.end(); 3918202879Srdivacky Cand != CandEnd; ++Cand) { 3919202879Srdivacky if (Cand->Viable) 3920202879Srdivacky Results.push_back(ResultCandidate(Cand->Function)); 3921202879Srdivacky } 3922210299Sed 3923210299Sed // From the viable candidates, try to determine the type of this parameter. 3924210299Sed for (unsigned I = 0, N = Results.size(); I != N; ++I) { 3925210299Sed if (const FunctionType *FType = Results[I].getFunctionType()) 3926210299Sed if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType)) 3927234353Sdim if (Args.size() < Proto->getNumArgs()) { 3928210299Sed if (ParamType.isNull()) 3929234353Sdim ParamType = Proto->getArgType(Args.size()); 3930210299Sed else if (!Context.hasSameUnqualifiedType( 3931210299Sed ParamType.getNonReferenceType(), 3932234353Sdim Proto->getArgType(Args.size()).getNonReferenceType())) { 3933210299Sed ParamType = QualType(); 3934210299Sed break; 3935210299Sed } 3936210299Sed } 3937210299Sed } 3938210299Sed } else { 3939210299Sed // Try to determine the parameter type from the type of the expression 3940210299Sed // being called. 3941210299Sed QualType FunctionType = Fn->getType(); 3942210299Sed if (const PointerType *Ptr = FunctionType->getAs<PointerType>()) 3943210299Sed FunctionType = Ptr->getPointeeType(); 3944210299Sed else if (const BlockPointerType *BlockPtr 3945210299Sed = FunctionType->getAs<BlockPointerType>()) 3946210299Sed FunctionType = BlockPtr->getPointeeType(); 3947210299Sed else if (const MemberPointerType *MemPtr 3948210299Sed = FunctionType->getAs<MemberPointerType>()) 3949210299Sed FunctionType = MemPtr->getPointeeType(); 3950210299Sed 3951210299Sed if (const FunctionProtoType *Proto 3952210299Sed = FunctionType->getAs<FunctionProtoType>()) { 3953234353Sdim if (Args.size() < Proto->getNumArgs()) 3954234353Sdim ParamType = Proto->getArgType(Args.size()); 3955210299Sed } 3956198092Srdivacky } 3957200583Srdivacky 3958210299Sed if (ParamType.isNull()) 3959212904Sdim CodeCompleteOrdinaryName(S, PCC_Expression); 3960210299Sed else 3961210299Sed CodeCompleteExpression(S, ParamType); 3962210299Sed 3963207619Srdivacky if (!Results.empty()) 3964234353Sdim CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(), 3965200583Srdivacky Results.size()); 3966198092Srdivacky} 3967198092Srdivacky 3968212904Sdimvoid Sema::CodeCompleteInitializer(Scope *S, Decl *D) { 3969212904Sdim ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D); 3970210299Sed if (!VD) { 3971212904Sdim CodeCompleteOrdinaryName(S, PCC_Expression); 3972210299Sed return; 3973210299Sed } 3974210299Sed 3975210299Sed CodeCompleteExpression(S, VD->getType()); 3976210299Sed} 3977210299Sed 3978210299Sedvoid Sema::CodeCompleteReturn(Scope *S) { 3979210299Sed QualType ResultType; 3980210299Sed if (isa<BlockDecl>(CurContext)) { 3981210299Sed if (BlockScopeInfo *BSI = getCurBlock()) 3982210299Sed ResultType = BSI->ReturnType; 3983210299Sed } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext)) 3984210299Sed ResultType = Function->getResultType(); 3985210299Sed else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext)) 3986210299Sed ResultType = Method->getResultType(); 3987210299Sed 3988210299Sed if (ResultType.isNull()) 3989212904Sdim CodeCompleteOrdinaryName(S, PCC_Expression); 3990210299Sed else 3991210299Sed CodeCompleteExpression(S, ResultType); 3992210299Sed} 3993210299Sed 3994226633Sdimvoid Sema::CodeCompleteAfterIf(Scope *S) { 3995226633Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 3996234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 3997226633Sdim mapCodeCompletionContext(*this, PCC_Statement)); 3998226633Sdim Results.setFilter(&ResultBuilder::IsOrdinaryName); 3999226633Sdim Results.EnterNewScope(); 4000226633Sdim 4001226633Sdim CodeCompletionDeclConsumer Consumer(Results, CurContext); 4002226633Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 4003226633Sdim CodeCompleter->includeGlobals()); 4004226633Sdim 4005226633Sdim AddOrdinaryNameResults(PCC_Statement, S, *this, Results); 4006226633Sdim 4007226633Sdim // "else" block 4008234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 4009234353Sdim Results.getCodeCompletionTUInfo()); 4010226633Sdim Builder.AddTypedTextChunk("else"); 4011234353Sdim if (Results.includeCodePatterns()) { 4012234353Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4013234353Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 4014234353Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 4015234353Sdim Builder.AddPlaceholderChunk("statements"); 4016234353Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 4017234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 4018234353Sdim } 4019226633Sdim Results.AddResult(Builder.TakeString()); 4020226633Sdim 4021226633Sdim // "else if" block 4022226633Sdim Builder.AddTypedTextChunk("else"); 4023226633Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4024226633Sdim Builder.AddTextChunk("if"); 4025226633Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4026226633Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4027234353Sdim if (getLangOpts().CPlusPlus) 4028226633Sdim Builder.AddPlaceholderChunk("condition"); 4029226633Sdim else 4030226633Sdim Builder.AddPlaceholderChunk("expression"); 4031226633Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4032234353Sdim if (Results.includeCodePatterns()) { 4033234353Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4034234353Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 4035234353Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 4036234353Sdim Builder.AddPlaceholderChunk("statements"); 4037234353Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 4038234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 4039234353Sdim } 4040226633Sdim Results.AddResult(Builder.TakeString()); 4041226633Sdim 4042226633Sdim Results.ExitScope(); 4043226633Sdim 4044226633Sdim if (S->getFnParent()) 4045234353Sdim AddPrettyFunctionResults(PP.getLangOpts(), Results); 4046226633Sdim 4047226633Sdim if (CodeCompleter->includeMacros()) 4048243830Sdim AddMacroResults(PP, Results, false); 4049226633Sdim 4050226633Sdim HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), 4051226633Sdim Results.data(),Results.size()); 4052226633Sdim} 4053226633Sdim 4054226633Sdimvoid Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) { 4055210299Sed if (LHS) 4056210299Sed CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType()); 4057210299Sed else 4058212904Sdim CodeCompleteOrdinaryName(S, PCC_Expression); 4059210299Sed} 4060210299Sed 4061207619Srdivackyvoid Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, 4062198092Srdivacky bool EnteringContext) { 4063198092Srdivacky if (!SS.getScopeRep() || !CodeCompleter) 4064198092Srdivacky return; 4065198092Srdivacky 4066198092Srdivacky DeclContext *Ctx = computeDeclContext(SS, EnteringContext); 4067198092Srdivacky if (!Ctx) 4068198092Srdivacky return; 4069200583Srdivacky 4070200583Srdivacky // Try to instantiate any non-dependent declaration contexts before 4071200583Srdivacky // we look in them. 4072207619Srdivacky if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx)) 4073200583Srdivacky return; 4074200583Srdivacky 4075218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4076234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4077218893Sdim CodeCompletionContext::CCC_Name); 4078218893Sdim Results.EnterNewScope(); 4079198092Srdivacky 4080198092Srdivacky // The "template" keyword can follow "::" in the grammar, but only 4081198092Srdivacky // put it into the grammar if the nested-name-specifier is dependent. 4082198092Srdivacky NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); 4083198092Srdivacky if (!Results.empty() && NNS->isDependent()) 4084202379Srdivacky Results.AddResult("template"); 4085212904Sdim 4086212904Sdim // Add calls to overridden virtual functions, if there are any. 4087212904Sdim // 4088212904Sdim // FIXME: This isn't wonderful, because we don't know whether we're actually 4089212904Sdim // in a context that permits expressions. This is a general issue with 4090212904Sdim // qualified-id completions. 4091212904Sdim if (!EnteringContext) 4092212904Sdim MaybeAddOverrideCalls(*this, Ctx, Results); 4093212904Sdim Results.ExitScope(); 4094198092Srdivacky 4095212904Sdim CodeCompletionDeclConsumer Consumer(Results, CurContext); 4096212904Sdim LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer); 4097212904Sdim 4098212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4099226633Sdim Results.getCompletionContext(), 4100212904Sdim Results.data(),Results.size()); 4101198092Srdivacky} 4102198092Srdivacky 4103198092Srdivackyvoid Sema::CodeCompleteUsing(Scope *S) { 4104198092Srdivacky if (!CodeCompleter) 4105198092Srdivacky return; 4106198092Srdivacky 4107218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4108234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4109218893Sdim CodeCompletionContext::CCC_PotentiallyQualifiedName, 4110218893Sdim &ResultBuilder::IsNestedNameSpecifier); 4111198092Srdivacky Results.EnterNewScope(); 4112198092Srdivacky 4113198092Srdivacky // If we aren't in class scope, we could see the "namespace" keyword. 4114198092Srdivacky if (!S->isClassScope()) 4115212904Sdim Results.AddResult(CodeCompletionResult("namespace")); 4116198092Srdivacky 4117198092Srdivacky // After "using", we can see anything that would start a 4118198092Srdivacky // nested-name-specifier. 4119202379Srdivacky CodeCompletionDeclConsumer Consumer(Results, CurContext); 4120212904Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 4121212904Sdim CodeCompleter->includeGlobals()); 4122198092Srdivacky Results.ExitScope(); 4123198092Srdivacky 4124212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4125218893Sdim CodeCompletionContext::CCC_PotentiallyQualifiedName, 4126212904Sdim Results.data(),Results.size()); 4127198092Srdivacky} 4128198092Srdivacky 4129198092Srdivackyvoid Sema::CodeCompleteUsingDirective(Scope *S) { 4130198092Srdivacky if (!CodeCompleter) 4131198092Srdivacky return; 4132198092Srdivacky 4133198092Srdivacky // After "using namespace", we expect to see a namespace name or namespace 4134198092Srdivacky // alias. 4135218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4136234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4137218893Sdim CodeCompletionContext::CCC_Namespace, 4138218893Sdim &ResultBuilder::IsNamespaceOrAlias); 4139198092Srdivacky Results.EnterNewScope(); 4140202379Srdivacky CodeCompletionDeclConsumer Consumer(Results, CurContext); 4141212904Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 4142212904Sdim CodeCompleter->includeGlobals()); 4143198092Srdivacky Results.ExitScope(); 4144212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4145212904Sdim CodeCompletionContext::CCC_Namespace, 4146212904Sdim Results.data(),Results.size()); 4147198092Srdivacky} 4148198092Srdivacky 4149198092Srdivackyvoid Sema::CodeCompleteNamespaceDecl(Scope *S) { 4150198092Srdivacky if (!CodeCompleter) 4151198092Srdivacky return; 4152198092Srdivacky 4153198092Srdivacky DeclContext *Ctx = (DeclContext *)S->getEntity(); 4154198092Srdivacky if (!S->getParent()) 4155198092Srdivacky Ctx = Context.getTranslationUnitDecl(); 4156198092Srdivacky 4157218893Sdim bool SuppressedGlobalResults 4158218893Sdim = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); 4159218893Sdim 4160218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4161234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4162218893Sdim SuppressedGlobalResults 4163218893Sdim ? CodeCompletionContext::CCC_Namespace 4164218893Sdim : CodeCompletionContext::CCC_Other, 4165218893Sdim &ResultBuilder::IsNamespace); 4166218893Sdim 4167218893Sdim if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) { 4168198092Srdivacky // We only want to see those namespaces that have already been defined 4169198092Srdivacky // within this scope, because its likely that the user is creating an 4170198092Srdivacky // extended namespace declaration. Keep track of the most recent 4171198092Srdivacky // definition of each namespace. 4172198092Srdivacky std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest; 4173198092Srdivacky for (DeclContext::specific_decl_iterator<NamespaceDecl> 4174198092Srdivacky NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end()); 4175198092Srdivacky NS != NSEnd; ++NS) 4176198092Srdivacky OrigToLatest[NS->getOriginalNamespace()] = *NS; 4177198092Srdivacky 4178198092Srdivacky // Add the most recent definition (or extended definition) of each 4179198092Srdivacky // namespace to the list of results. 4180198092Srdivacky Results.EnterNewScope(); 4181198092Srdivacky for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator 4182234353Sdim NS = OrigToLatest.begin(), 4183234353Sdim NSEnd = OrigToLatest.end(); 4184198092Srdivacky NS != NSEnd; ++NS) 4185249423Sdim Results.AddResult(CodeCompletionResult( 4186249423Sdim NS->second, Results.getBasePriority(NS->second), 0), 4187202379Srdivacky CurContext, 0, false); 4188198092Srdivacky Results.ExitScope(); 4189198092Srdivacky } 4190198092Srdivacky 4191212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4192218893Sdim Results.getCompletionContext(), 4193212904Sdim Results.data(),Results.size()); 4194198092Srdivacky} 4195198092Srdivacky 4196198092Srdivackyvoid Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { 4197198092Srdivacky if (!CodeCompleter) 4198198092Srdivacky return; 4199198092Srdivacky 4200198092Srdivacky // After "namespace", we expect to see a namespace or alias. 4201218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4202234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4203218893Sdim CodeCompletionContext::CCC_Namespace, 4204218893Sdim &ResultBuilder::IsNamespaceOrAlias); 4205202379Srdivacky CodeCompletionDeclConsumer Consumer(Results, CurContext); 4206212904Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 4207212904Sdim CodeCompleter->includeGlobals()); 4208212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4209218893Sdim Results.getCompletionContext(), 4210212904Sdim Results.data(),Results.size()); 4211198092Srdivacky} 4212198092Srdivacky 4213198092Srdivackyvoid Sema::CodeCompleteOperatorName(Scope *S) { 4214198092Srdivacky if (!CodeCompleter) 4215198092Srdivacky return; 4216198092Srdivacky 4217212904Sdim typedef CodeCompletionResult Result; 4218218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4219234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4220218893Sdim CodeCompletionContext::CCC_Type, 4221218893Sdim &ResultBuilder::IsType); 4222198092Srdivacky Results.EnterNewScope(); 4223198092Srdivacky 4224198092Srdivacky // Add the names of overloadable operators. 4225198092Srdivacky#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ 4226198092Srdivacky if (std::strcmp(Spelling, "?")) \ 4227202379Srdivacky Results.AddResult(Result(Spelling)); 4228198092Srdivacky#include "clang/Basic/OperatorKinds.def" 4229198092Srdivacky 4230198092Srdivacky // Add any type names visible from the current scope 4231202379Srdivacky Results.allowNestedNameSpecifiers(); 4232202379Srdivacky CodeCompletionDeclConsumer Consumer(Results, CurContext); 4233212904Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 4234212904Sdim CodeCompleter->includeGlobals()); 4235198092Srdivacky 4236198092Srdivacky // Add any type specifiers 4237234353Sdim AddTypeSpecifierResults(getLangOpts(), Results); 4238198092Srdivacky Results.ExitScope(); 4239198092Srdivacky 4240212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4241212904Sdim CodeCompletionContext::CCC_Type, 4242212904Sdim Results.data(),Results.size()); 4243198092Srdivacky} 4244198092Srdivacky 4245212904Sdimvoid Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, 4246218893Sdim CXXCtorInitializer** Initializers, 4247212904Sdim unsigned NumInitializers) { 4248226633Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(*this); 4249212904Sdim CXXConstructorDecl *Constructor 4250212904Sdim = static_cast<CXXConstructorDecl *>(ConstructorD); 4251212904Sdim if (!Constructor) 4252212904Sdim return; 4253212904Sdim 4254218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4255234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4256218893Sdim CodeCompletionContext::CCC_PotentiallyQualifiedName); 4257212904Sdim Results.EnterNewScope(); 4258212904Sdim 4259212904Sdim // Fill in any already-initialized fields or base classes. 4260212904Sdim llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields; 4261212904Sdim llvm::SmallPtrSet<CanQualType, 4> InitializedBases; 4262212904Sdim for (unsigned I = 0; I != NumInitializers; ++I) { 4263212904Sdim if (Initializers[I]->isBaseInitializer()) 4264212904Sdim InitializedBases.insert( 4265212904Sdim Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0))); 4266212904Sdim else 4267218893Sdim InitializedFields.insert(cast<FieldDecl>( 4268218893Sdim Initializers[I]->getAnyMember())); 4269212904Sdim } 4270212904Sdim 4271212904Sdim // Add completions for base classes. 4272234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 4273234353Sdim Results.getCodeCompletionTUInfo()); 4274212904Sdim bool SawLastInitializer = (NumInitializers == 0); 4275212904Sdim CXXRecordDecl *ClassDecl = Constructor->getParent(); 4276212904Sdim for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), 4277212904Sdim BaseEnd = ClassDecl->bases_end(); 4278212904Sdim Base != BaseEnd; ++Base) { 4279212904Sdim if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { 4280212904Sdim SawLastInitializer 4281212904Sdim = NumInitializers > 0 && 4282212904Sdim Initializers[NumInitializers - 1]->isBaseInitializer() && 4283212904Sdim Context.hasSameUnqualifiedType(Base->getType(), 4284212904Sdim QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); 4285212904Sdim continue; 4286212904Sdim } 4287212904Sdim 4288218893Sdim Builder.AddTypedTextChunk( 4289218893Sdim Results.getAllocator().CopyString( 4290224145Sdim Base->getType().getAsString(Policy))); 4291218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4292218893Sdim Builder.AddPlaceholderChunk("args"); 4293218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4294218893Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString(), 4295212904Sdim SawLastInitializer? CCP_NextInitializer 4296212904Sdim : CCP_MemberDeclaration)); 4297212904Sdim SawLastInitializer = false; 4298212904Sdim } 4299212904Sdim 4300212904Sdim // Add completions for virtual base classes. 4301212904Sdim for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), 4302212904Sdim BaseEnd = ClassDecl->vbases_end(); 4303212904Sdim Base != BaseEnd; ++Base) { 4304212904Sdim if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { 4305212904Sdim SawLastInitializer 4306212904Sdim = NumInitializers > 0 && 4307212904Sdim Initializers[NumInitializers - 1]->isBaseInitializer() && 4308212904Sdim Context.hasSameUnqualifiedType(Base->getType(), 4309212904Sdim QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); 4310212904Sdim continue; 4311212904Sdim } 4312212904Sdim 4313218893Sdim Builder.AddTypedTextChunk( 4314218893Sdim Builder.getAllocator().CopyString( 4315224145Sdim Base->getType().getAsString(Policy))); 4316218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4317218893Sdim Builder.AddPlaceholderChunk("args"); 4318218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4319218893Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString(), 4320212904Sdim SawLastInitializer? CCP_NextInitializer 4321212904Sdim : CCP_MemberDeclaration)); 4322212904Sdim SawLastInitializer = false; 4323212904Sdim } 4324212904Sdim 4325212904Sdim // Add completions for members. 4326212904Sdim for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), 4327212904Sdim FieldEnd = ClassDecl->field_end(); 4328212904Sdim Field != FieldEnd; ++Field) { 4329212904Sdim if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) { 4330212904Sdim SawLastInitializer 4331212904Sdim = NumInitializers > 0 && 4332218893Sdim Initializers[NumInitializers - 1]->isAnyMemberInitializer() && 4333218893Sdim Initializers[NumInitializers - 1]->getAnyMember() == *Field; 4334212904Sdim continue; 4335212904Sdim } 4336212904Sdim 4337212904Sdim if (!Field->getDeclName()) 4338212904Sdim continue; 4339212904Sdim 4340218893Sdim Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( 4341218893Sdim Field->getIdentifier()->getName())); 4342218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4343218893Sdim Builder.AddPlaceholderChunk("args"); 4344218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4345218893Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString(), 4346212904Sdim SawLastInitializer? CCP_NextInitializer 4347218893Sdim : CCP_MemberDeclaration, 4348234353Sdim CXCursor_MemberRef, 4349234353Sdim CXAvailability_Available, 4350234353Sdim *Field)); 4351212904Sdim SawLastInitializer = false; 4352212904Sdim } 4353212904Sdim Results.ExitScope(); 4354212904Sdim 4355218893Sdim HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), 4356212904Sdim Results.data(), Results.size()); 4357212904Sdim} 4358212904Sdim 4359234353Sdim/// \brief Determine whether this scope denotes a namespace. 4360234353Sdimstatic bool isNamespaceScope(Scope *S) { 4361234353Sdim DeclContext *DC = static_cast<DeclContext *>(S->getEntity()); 4362234353Sdim if (!DC) 4363234353Sdim return false; 4364234353Sdim 4365234353Sdim return DC->isFileContext(); 4366234353Sdim} 4367234353Sdim 4368234353Sdimvoid Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, 4369234353Sdim bool AfterAmpersand) { 4370234353Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4371234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4372234353Sdim CodeCompletionContext::CCC_Other); 4373234353Sdim Results.EnterNewScope(); 4374234353Sdim 4375234353Sdim // Note what has already been captured. 4376234353Sdim llvm::SmallPtrSet<IdentifierInfo *, 4> Known; 4377234353Sdim bool IncludedThis = false; 4378234353Sdim for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(), 4379234353Sdim CEnd = Intro.Captures.end(); 4380234353Sdim C != CEnd; ++C) { 4381234353Sdim if (C->Kind == LCK_This) { 4382234353Sdim IncludedThis = true; 4383234353Sdim continue; 4384234353Sdim } 4385234353Sdim 4386234353Sdim Known.insert(C->Id); 4387234353Sdim } 4388234353Sdim 4389234353Sdim // Look for other capturable variables. 4390234353Sdim for (; S && !isNamespaceScope(S); S = S->getParent()) { 4391234353Sdim for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); 4392234353Sdim D != DEnd; ++D) { 4393234353Sdim VarDecl *Var = dyn_cast<VarDecl>(*D); 4394234353Sdim if (!Var || 4395234353Sdim !Var->hasLocalStorage() || 4396234353Sdim Var->hasAttr<BlocksAttr>()) 4397234353Sdim continue; 4398234353Sdim 4399234353Sdim if (Known.insert(Var->getIdentifier())) 4400249423Sdim Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration), 4401249423Sdim CurContext, 0, false); 4402234353Sdim } 4403234353Sdim } 4404234353Sdim 4405234353Sdim // Add 'this', if it would be valid. 4406234353Sdim if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy) 4407234353Sdim addThisCompletion(*this, Results); 4408234353Sdim 4409234353Sdim Results.ExitScope(); 4410234353Sdim 4411234353Sdim HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), 4412234353Sdim Results.data(), Results.size()); 4413234353Sdim} 4414234353Sdim 4415239462Sdim/// Macro that optionally prepends an "@" to the string literal passed in via 4416239462Sdim/// Keyword, depending on whether NeedAt is true or false. 4417239462Sdim#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword) 4418239462Sdim 4419202379Srdivackystatic void AddObjCImplementationResults(const LangOptions &LangOpts, 4420202379Srdivacky ResultBuilder &Results, 4421202379Srdivacky bool NeedAt) { 4422212904Sdim typedef CodeCompletionResult Result; 4423202379Srdivacky // Since we have an implementation, we can end it. 4424239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end"))); 4425202379Srdivacky 4426234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 4427234353Sdim Results.getCodeCompletionTUInfo()); 4428202379Srdivacky if (LangOpts.ObjC2) { 4429202379Srdivacky // @dynamic 4430239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic")); 4431218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4432218893Sdim Builder.AddPlaceholderChunk("property"); 4433218893Sdim Results.AddResult(Result(Builder.TakeString())); 4434202379Srdivacky 4435202379Srdivacky // @synthesize 4436239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize")); 4437218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4438218893Sdim Builder.AddPlaceholderChunk("property"); 4439218893Sdim Results.AddResult(Result(Builder.TakeString())); 4440202379Srdivacky } 4441202379Srdivacky} 4442200583Srdivacky 4443202379Srdivackystatic void AddObjCInterfaceResults(const LangOptions &LangOpts, 4444202379Srdivacky ResultBuilder &Results, 4445202379Srdivacky bool NeedAt) { 4446212904Sdim typedef CodeCompletionResult Result; 4447202379Srdivacky 4448202379Srdivacky // Since we have an interface or protocol, we can end it. 4449239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end"))); 4450202379Srdivacky 4451202379Srdivacky if (LangOpts.ObjC2) { 4452202379Srdivacky // @property 4453239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property"))); 4454202379Srdivacky 4455200583Srdivacky // @required 4456239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required"))); 4457202379Srdivacky 4458200583Srdivacky // @optional 4459239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional"))); 4460202379Srdivacky } 4461202379Srdivacky} 4462200583Srdivacky 4463202379Srdivackystatic void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { 4464212904Sdim typedef CodeCompletionResult Result; 4465234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 4466234353Sdim Results.getCodeCompletionTUInfo()); 4467202379Srdivacky 4468202379Srdivacky // @class name ; 4469239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class")); 4470218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4471218893Sdim Builder.AddPlaceholderChunk("name"); 4472218893Sdim Results.AddResult(Result(Builder.TakeString())); 4473202379Srdivacky 4474210299Sed if (Results.includeCodePatterns()) { 4475210299Sed // @interface name 4476210299Sed // FIXME: Could introduce the whole pattern, including superclasses and 4477210299Sed // such. 4478239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface")); 4479218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4480218893Sdim Builder.AddPlaceholderChunk("class"); 4481218893Sdim Results.AddResult(Result(Builder.TakeString())); 4482202379Srdivacky 4483210299Sed // @protocol name 4484239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol")); 4485218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4486218893Sdim Builder.AddPlaceholderChunk("protocol"); 4487218893Sdim Results.AddResult(Result(Builder.TakeString())); 4488210299Sed 4489210299Sed // @implementation name 4490239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation")); 4491218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4492218893Sdim Builder.AddPlaceholderChunk("class"); 4493218893Sdim Results.AddResult(Result(Builder.TakeString())); 4494210299Sed } 4495202379Srdivacky 4496202379Srdivacky // @compatibility_alias name 4497239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias")); 4498218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4499218893Sdim Builder.AddPlaceholderChunk("alias"); 4500218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4501218893Sdim Builder.AddPlaceholderChunk("class"); 4502218893Sdim Results.AddResult(Result(Builder.TakeString())); 4503249423Sdim 4504249423Sdim if (Results.getSema().getLangOpts().Modules) { 4505249423Sdim // @import name 4506249423Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import")); 4507249423Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4508249423Sdim Builder.AddPlaceholderChunk("module"); 4509249423Sdim Results.AddResult(Result(Builder.TakeString())); 4510249423Sdim } 4511202379Srdivacky} 4512200583Srdivacky 4513226633Sdimvoid Sema::CodeCompleteObjCAtDirective(Scope *S) { 4514218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4515234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4516218893Sdim CodeCompletionContext::CCC_Other); 4517202379Srdivacky Results.EnterNewScope(); 4518226633Sdim if (isa<ObjCImplDecl>(CurContext)) 4519234353Sdim AddObjCImplementationResults(getLangOpts(), Results, false); 4520226633Sdim else if (CurContext->isObjCContainer()) 4521234353Sdim AddObjCInterfaceResults(getLangOpts(), Results, false); 4522202379Srdivacky else 4523202379Srdivacky AddObjCTopLevelResults(Results, false); 4524200583Srdivacky Results.ExitScope(); 4525212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4526212904Sdim CodeCompletionContext::CCC_Other, 4527212904Sdim Results.data(),Results.size()); 4528200583Srdivacky} 4529200583Srdivacky 4530202379Srdivackystatic void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { 4531212904Sdim typedef CodeCompletionResult Result; 4532234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 4533234353Sdim Results.getCodeCompletionTUInfo()); 4534200583Srdivacky 4535200583Srdivacky // @encode ( type-name ) 4536234353Sdim const char *EncodeType = "char[]"; 4537234353Sdim if (Results.getSema().getLangOpts().CPlusPlus || 4538234353Sdim Results.getSema().getLangOpts().ConstStrings) 4539239462Sdim EncodeType = "const char[]"; 4540234353Sdim Builder.AddResultTypeChunk(EncodeType); 4541239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode")); 4542218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4543218893Sdim Builder.AddPlaceholderChunk("type-name"); 4544218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4545218893Sdim Results.AddResult(Result(Builder.TakeString())); 4546200583Srdivacky 4547200583Srdivacky // @protocol ( protocol-name ) 4548234353Sdim Builder.AddResultTypeChunk("Protocol *"); 4549239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol")); 4550218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4551218893Sdim Builder.AddPlaceholderChunk("protocol-name"); 4552218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4553218893Sdim Results.AddResult(Result(Builder.TakeString())); 4554200583Srdivacky 4555200583Srdivacky // @selector ( selector ) 4556234353Sdim Builder.AddResultTypeChunk("SEL"); 4557239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector")); 4558218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4559218893Sdim Builder.AddPlaceholderChunk("selector"); 4560218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4561218893Sdim Results.AddResult(Result(Builder.TakeString())); 4562239462Sdim 4563239462Sdim // @"string" 4564239462Sdim Builder.AddResultTypeChunk("NSString *"); 4565239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\"")); 4566239462Sdim Builder.AddPlaceholderChunk("string"); 4567239462Sdim Builder.AddTextChunk("\""); 4568239462Sdim Results.AddResult(Result(Builder.TakeString())); 4569239462Sdim 4570239462Sdim // @[objects, ...] 4571239462Sdim Builder.AddResultTypeChunk("NSArray *"); 4572239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"[")); 4573234353Sdim Builder.AddPlaceholderChunk("objects, ..."); 4574234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightBracket); 4575234353Sdim Results.AddResult(Result(Builder.TakeString())); 4576234353Sdim 4577239462Sdim // @{key : object, ...} 4578239462Sdim Builder.AddResultTypeChunk("NSDictionary *"); 4579239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{")); 4580234353Sdim Builder.AddPlaceholderChunk("key"); 4581234353Sdim Builder.AddChunk(CodeCompletionString::CK_Colon); 4582234353Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4583234353Sdim Builder.AddPlaceholderChunk("object, ..."); 4584234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 4585234353Sdim Results.AddResult(Result(Builder.TakeString())); 4586239462Sdim 4587239462Sdim // @(expression) 4588239462Sdim Builder.AddResultTypeChunk("id"); 4589239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "(")); 4590239462Sdim Builder.AddPlaceholderChunk("expression"); 4591239462Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4592239462Sdim Results.AddResult(Result(Builder.TakeString())); 4593200583Srdivacky} 4594200583Srdivacky 4595202379Srdivackystatic void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { 4596212904Sdim typedef CodeCompletionResult Result; 4597234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 4598234353Sdim Results.getCodeCompletionTUInfo()); 4599202379Srdivacky 4600210299Sed if (Results.includeCodePatterns()) { 4601210299Sed // @try { statements } @catch ( declaration ) { statements } @finally 4602210299Sed // { statements } 4603239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try")); 4604218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 4605218893Sdim Builder.AddPlaceholderChunk("statements"); 4606218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 4607218893Sdim Builder.AddTextChunk("@catch"); 4608218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4609218893Sdim Builder.AddPlaceholderChunk("parameter"); 4610218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4611218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 4612218893Sdim Builder.AddPlaceholderChunk("statements"); 4613218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 4614218893Sdim Builder.AddTextChunk("@finally"); 4615218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 4616218893Sdim Builder.AddPlaceholderChunk("statements"); 4617218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 4618218893Sdim Results.AddResult(Result(Builder.TakeString())); 4619210299Sed } 4620202379Srdivacky 4621200583Srdivacky // @throw 4622239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw")); 4623218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4624218893Sdim Builder.AddPlaceholderChunk("expression"); 4625218893Sdim Results.AddResult(Result(Builder.TakeString())); 4626202379Srdivacky 4627210299Sed if (Results.includeCodePatterns()) { 4628210299Sed // @synchronized ( expression ) { statements } 4629239462Sdim Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized")); 4630218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 4631218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 4632218893Sdim Builder.AddPlaceholderChunk("expression"); 4633218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 4634218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 4635218893Sdim Builder.AddPlaceholderChunk("statements"); 4636218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 4637218893Sdim Results.AddResult(Result(Builder.TakeString())); 4638210299Sed } 4639202379Srdivacky} 4640200583Srdivacky 4641202379Srdivackystatic void AddObjCVisibilityResults(const LangOptions &LangOpts, 4642202379Srdivacky ResultBuilder &Results, 4643202379Srdivacky bool NeedAt) { 4644212904Sdim typedef CodeCompletionResult Result; 4645239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private"))); 4646239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected"))); 4647239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public"))); 4648202379Srdivacky if (LangOpts.ObjC2) 4649239462Sdim Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package"))); 4650202379Srdivacky} 4651202379Srdivacky 4652202379Srdivackyvoid Sema::CodeCompleteObjCAtVisibility(Scope *S) { 4653218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4654234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4655218893Sdim CodeCompletionContext::CCC_Other); 4656202379Srdivacky Results.EnterNewScope(); 4657234353Sdim AddObjCVisibilityResults(getLangOpts(), Results, false); 4658200583Srdivacky Results.ExitScope(); 4659212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4660212904Sdim CodeCompletionContext::CCC_Other, 4661212904Sdim Results.data(),Results.size()); 4662200583Srdivacky} 4663200583Srdivacky 4664202379Srdivackyvoid Sema::CodeCompleteObjCAtStatement(Scope *S) { 4665218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4666234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4667218893Sdim CodeCompletionContext::CCC_Other); 4668202379Srdivacky Results.EnterNewScope(); 4669202379Srdivacky AddObjCStatementResults(Results, false); 4670202379Srdivacky AddObjCExpressionResults(Results, false); 4671202379Srdivacky Results.ExitScope(); 4672212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4673212904Sdim CodeCompletionContext::CCC_Other, 4674212904Sdim Results.data(),Results.size()); 4675202379Srdivacky} 4676202379Srdivacky 4677200583Srdivackyvoid Sema::CodeCompleteObjCAtExpression(Scope *S) { 4678218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4679234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4680218893Sdim CodeCompletionContext::CCC_Other); 4681200583Srdivacky Results.EnterNewScope(); 4682202379Srdivacky AddObjCExpressionResults(Results, false); 4683200583Srdivacky Results.ExitScope(); 4684212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4685212904Sdim CodeCompletionContext::CCC_Other, 4686212904Sdim Results.data(),Results.size()); 4687200583Srdivacky} 4688200583Srdivacky 4689199512Srdivacky/// \brief Determine whether the addition of the given flag to an Objective-C 4690199512Srdivacky/// property's attributes will cause a conflict. 4691199512Srdivackystatic bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { 4692199512Srdivacky // Check if we've already added this flag. 4693199512Srdivacky if (Attributes & NewFlag) 4694199512Srdivacky return true; 4695199512Srdivacky 4696199512Srdivacky Attributes |= NewFlag; 4697199512Srdivacky 4698199512Srdivacky // Check for collisions with "readonly". 4699199512Srdivacky if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 4700243830Sdim (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) 4701199512Srdivacky return true; 4702199512Srdivacky 4703243830Sdim // Check for more than one of { assign, copy, retain, strong, weak }. 4704199512Srdivacky unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign | 4705224145Sdim ObjCDeclSpec::DQ_PR_unsafe_unretained | 4706199512Srdivacky ObjCDeclSpec::DQ_PR_copy | 4707243830Sdim ObjCDeclSpec::DQ_PR_retain | 4708243830Sdim ObjCDeclSpec::DQ_PR_strong | 4709243830Sdim ObjCDeclSpec::DQ_PR_weak); 4710199512Srdivacky if (AssignCopyRetMask && 4711199512Srdivacky AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && 4712224145Sdim AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained && 4713199512Srdivacky AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && 4714224145Sdim AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain && 4715243830Sdim AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong && 4716243830Sdim AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak) 4717199512Srdivacky return true; 4718199512Srdivacky 4719199512Srdivacky return false; 4720199512Srdivacky} 4721199512Srdivacky 4722199512Srdivackyvoid Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { 4723198092Srdivacky if (!CodeCompleter) 4724198092Srdivacky return; 4725199512Srdivacky 4726198092Srdivacky unsigned Attributes = ODS.getPropertyAttributes(); 4727198092Srdivacky 4728218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4729234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4730218893Sdim CodeCompletionContext::CCC_Other); 4731198092Srdivacky Results.EnterNewScope(); 4732199512Srdivacky if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly)) 4733212904Sdim Results.AddResult(CodeCompletionResult("readonly")); 4734199512Srdivacky if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign)) 4735212904Sdim Results.AddResult(CodeCompletionResult("assign")); 4736224145Sdim if (!ObjCPropertyFlagConflicts(Attributes, 4737224145Sdim ObjCDeclSpec::DQ_PR_unsafe_unretained)) 4738224145Sdim Results.AddResult(CodeCompletionResult("unsafe_unretained")); 4739199512Srdivacky if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite)) 4740212904Sdim Results.AddResult(CodeCompletionResult("readwrite")); 4741199512Srdivacky if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain)) 4742212904Sdim Results.AddResult(CodeCompletionResult("retain")); 4743224145Sdim if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong)) 4744224145Sdim Results.AddResult(CodeCompletionResult("strong")); 4745199512Srdivacky if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy)) 4746212904Sdim Results.AddResult(CodeCompletionResult("copy")); 4747199512Srdivacky if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic)) 4748212904Sdim Results.AddResult(CodeCompletionResult("nonatomic")); 4749223017Sdim if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic)) 4750223017Sdim Results.AddResult(CodeCompletionResult("atomic")); 4751243830Sdim 4752243830Sdim // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC. 4753243830Sdim if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC) 4754243830Sdim if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak)) 4755243830Sdim Results.AddResult(CodeCompletionResult("weak")); 4756243830Sdim 4757199512Srdivacky if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) { 4758234353Sdim CodeCompletionBuilder Setter(Results.getAllocator(), 4759234353Sdim Results.getCodeCompletionTUInfo()); 4760218893Sdim Setter.AddTypedTextChunk("setter"); 4761218893Sdim Setter.AddTextChunk(" = "); 4762218893Sdim Setter.AddPlaceholderChunk("method"); 4763218893Sdim Results.AddResult(CodeCompletionResult(Setter.TakeString())); 4764199512Srdivacky } 4765199512Srdivacky if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) { 4766234353Sdim CodeCompletionBuilder Getter(Results.getAllocator(), 4767234353Sdim Results.getCodeCompletionTUInfo()); 4768218893Sdim Getter.AddTypedTextChunk("getter"); 4769218893Sdim Getter.AddTextChunk(" = "); 4770218893Sdim Getter.AddPlaceholderChunk("method"); 4771218893Sdim Results.AddResult(CodeCompletionResult(Getter.TakeString())); 4772199512Srdivacky } 4773198092Srdivacky Results.ExitScope(); 4774212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4775212904Sdim CodeCompletionContext::CCC_Other, 4776212904Sdim Results.data(),Results.size()); 4777198092Srdivacky} 4778199482Srdivacky 4779239462Sdim/// \brief Describes the kind of Objective-C method that we want to find 4780199512Srdivacky/// via code completion. 4781199512Srdivackyenum ObjCMethodKind { 4782239462Sdim MK_Any, ///< Any kind of method, provided it means other specified criteria. 4783239462Sdim MK_ZeroArgSelector, ///< Zero-argument (unary) selector. 4784239462Sdim MK_OneArgSelector ///< One-argument selector. 4785199512Srdivacky}; 4786199512Srdivacky 4787212904Sdimstatic bool isAcceptableObjCSelector(Selector Sel, 4788212904Sdim ObjCMethodKind WantKind, 4789212904Sdim IdentifierInfo **SelIdents, 4790218893Sdim unsigned NumSelIdents, 4791218893Sdim bool AllowSameLength = true) { 4792199512Srdivacky if (NumSelIdents > Sel.getNumArgs()) 4793199512Srdivacky return false; 4794212904Sdim 4795199512Srdivacky switch (WantKind) { 4796212904Sdim case MK_Any: break; 4797212904Sdim case MK_ZeroArgSelector: return Sel.isUnarySelector(); 4798212904Sdim case MK_OneArgSelector: return Sel.getNumArgs() == 1; 4799199512Srdivacky } 4800212904Sdim 4801218893Sdim if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs()) 4802218893Sdim return false; 4803218893Sdim 4804199512Srdivacky for (unsigned I = 0; I != NumSelIdents; ++I) 4805199512Srdivacky if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I)) 4806199512Srdivacky return false; 4807212904Sdim 4808199512Srdivacky return true; 4809199512Srdivacky} 4810212904Sdim 4811212904Sdimstatic bool isAcceptableObjCMethod(ObjCMethodDecl *Method, 4812212904Sdim ObjCMethodKind WantKind, 4813212904Sdim IdentifierInfo **SelIdents, 4814218893Sdim unsigned NumSelIdents, 4815218893Sdim bool AllowSameLength = true) { 4816212904Sdim return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents, 4817218893Sdim NumSelIdents, AllowSameLength); 4818212904Sdim} 4819218893Sdim 4820218893Sdimnamespace { 4821218893Sdim /// \brief A set of selectors, which is used to avoid introducing multiple 4822218893Sdim /// completions with the same selector into the result set. 4823218893Sdim typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet; 4824218893Sdim} 4825218893Sdim 4826199482Srdivacky/// \brief Add all of the Objective-C methods in the given Objective-C 4827199482Srdivacky/// container to the set of results. 4828199482Srdivacky/// 4829199482Srdivacky/// The container will be a class, protocol, category, or implementation of 4830199482Srdivacky/// any of the above. This mether will recurse to include methods from 4831199482Srdivacky/// the superclasses of classes along with their categories, protocols, and 4832199482Srdivacky/// implementations. 4833199482Srdivacky/// 4834199482Srdivacky/// \param Container the container in which we'll look to find methods. 4835199482Srdivacky/// 4836239462Sdim/// \param WantInstanceMethods Whether to add instance methods (only); if 4837239462Sdim/// false, this routine will add factory methods (only). 4838199482Srdivacky/// 4839199482Srdivacky/// \param CurContext the context in which we're performing the lookup that 4840199482Srdivacky/// finds methods. 4841199482Srdivacky/// 4842218893Sdim/// \param AllowSameLength Whether we allow a method to be added to the list 4843218893Sdim/// when it has the same number of parameters as we have selector identifiers. 4844218893Sdim/// 4845199482Srdivacky/// \param Results the structure into which we'll add results. 4846199482Srdivackystatic void AddObjCMethods(ObjCContainerDecl *Container, 4847199482Srdivacky bool WantInstanceMethods, 4848199512Srdivacky ObjCMethodKind WantKind, 4849199512Srdivacky IdentifierInfo **SelIdents, 4850199512Srdivacky unsigned NumSelIdents, 4851199482Srdivacky DeclContext *CurContext, 4852218893Sdim VisitedSelectorSet &Selectors, 4853218893Sdim bool AllowSameLength, 4854212904Sdim ResultBuilder &Results, 4855212904Sdim bool InOriginalClass = true) { 4856212904Sdim typedef CodeCompletionResult Result; 4857239462Sdim Container = getContainerDef(Container); 4858249423Sdim ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); 4859249423Sdim bool isRootClass = IFace && !IFace->getSuperClass(); 4860199482Srdivacky for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), 4861199482Srdivacky MEnd = Container->meth_end(); 4862199482Srdivacky M != MEnd; ++M) { 4863249423Sdim // The instance methods on the root class can be messaged via the 4864249423Sdim // metaclass. 4865249423Sdim if (M->isInstanceMethod() == WantInstanceMethods || 4866249423Sdim (isRootClass && !WantInstanceMethods)) { 4867199512Srdivacky // Check whether the selector identifiers we've been given are a 4868199512Srdivacky // subset of the identifiers for this particular method. 4869218893Sdim if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents, 4870218893Sdim AllowSameLength)) 4871199512Srdivacky continue; 4872199512Srdivacky 4873239462Sdim if (!Selectors.insert(M->getSelector())) 4874218893Sdim continue; 4875218893Sdim 4876249423Sdim Result R = Result(*M, Results.getBasePriority(*M), 0); 4877199512Srdivacky R.StartParameter = NumSelIdents; 4878199512Srdivacky R.AllParametersAreInformative = (WantKind != MK_Any); 4879212904Sdim if (!InOriginalClass) 4880212904Sdim R.Priority += CCD_InBaseClass; 4881199512Srdivacky Results.MaybeAddResult(R, CurContext); 4882199512Srdivacky } 4883199482Srdivacky } 4884199482Srdivacky 4885218893Sdim // Visit the protocols of protocols. 4886218893Sdim if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { 4887234353Sdim if (Protocol->hasDefinition()) { 4888234353Sdim const ObjCList<ObjCProtocolDecl> &Protocols 4889234353Sdim = Protocol->getReferencedProtocols(); 4890234353Sdim for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 4891234353Sdim E = Protocols.end(); 4892234353Sdim I != E; ++I) 4893234353Sdim AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, 4894234353Sdim NumSelIdents, CurContext, Selectors, AllowSameLength, 4895234353Sdim Results, false); 4896234353Sdim } 4897218893Sdim } 4898218893Sdim 4899234353Sdim if (!IFace || !IFace->hasDefinition()) 4900199482Srdivacky return; 4901199482Srdivacky 4902199482Srdivacky // Add methods in protocols. 4903234353Sdim for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(), 4904234353Sdim E = IFace->protocol_end(); 4905199482Srdivacky I != E; ++I) 4906199512Srdivacky AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents, 4907218893Sdim CurContext, Selectors, AllowSameLength, Results, false); 4908199482Srdivacky 4909199482Srdivacky // Add methods in categories. 4910249423Sdim for (ObjCInterfaceDecl::known_categories_iterator 4911249423Sdim Cat = IFace->known_categories_begin(), 4912249423Sdim CatEnd = IFace->known_categories_end(); 4913249423Sdim Cat != CatEnd; ++Cat) { 4914249423Sdim ObjCCategoryDecl *CatDecl = *Cat; 4915249423Sdim 4916249423Sdim AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, 4917218893Sdim NumSelIdents, CurContext, Selectors, AllowSameLength, 4918218893Sdim Results, InOriginalClass); 4919199482Srdivacky 4920199482Srdivacky // Add a categories protocol methods. 4921199482Srdivacky const ObjCList<ObjCProtocolDecl> &Protocols 4922199482Srdivacky = CatDecl->getReferencedProtocols(); 4923199482Srdivacky for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 4924199482Srdivacky E = Protocols.end(); 4925199482Srdivacky I != E; ++I) 4926199512Srdivacky AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, 4927218893Sdim NumSelIdents, CurContext, Selectors, AllowSameLength, 4928218893Sdim Results, false); 4929199482Srdivacky 4930199482Srdivacky // Add methods in category implementations. 4931199482Srdivacky if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) 4932199512Srdivacky AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, 4933218893Sdim NumSelIdents, CurContext, Selectors, AllowSameLength, 4934218893Sdim Results, InOriginalClass); 4935199482Srdivacky } 4936199482Srdivacky 4937199482Srdivacky // Add methods in superclass. 4938199482Srdivacky if (IFace->getSuperClass()) 4939199512Srdivacky AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, 4940218893Sdim SelIdents, NumSelIdents, CurContext, Selectors, 4941218893Sdim AllowSameLength, Results, false); 4942199482Srdivacky 4943199482Srdivacky // Add methods in our implementation, if any. 4944199482Srdivacky if (ObjCImplementationDecl *Impl = IFace->getImplementation()) 4945199512Srdivacky AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, 4946218893Sdim NumSelIdents, CurContext, Selectors, AllowSameLength, 4947218893Sdim Results, InOriginalClass); 4948199482Srdivacky} 4949199482Srdivacky 4950199512Srdivacky 4951226633Sdimvoid Sema::CodeCompleteObjCPropertyGetter(Scope *S) { 4952199512Srdivacky // Try to find the interface where getters might live. 4953226633Sdim ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); 4954199512Srdivacky if (!Class) { 4955199512Srdivacky if (ObjCCategoryDecl *Category 4956226633Sdim = dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) 4957199512Srdivacky Class = Category->getClassInterface(); 4958199512Srdivacky 4959199512Srdivacky if (!Class) 4960199512Srdivacky return; 4961199512Srdivacky } 4962199512Srdivacky 4963199512Srdivacky // Find all of the potential getters. 4964218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4965234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4966218893Sdim CodeCompletionContext::CCC_Other); 4967199512Srdivacky Results.EnterNewScope(); 4968199512Srdivacky 4969218893Sdim VisitedSelectorSet Selectors; 4970218893Sdim AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors, 4971218893Sdim /*AllowSameLength=*/true, Results); 4972199512Srdivacky Results.ExitScope(); 4973212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 4974212904Sdim CodeCompletionContext::CCC_Other, 4975212904Sdim Results.data(),Results.size()); 4976199512Srdivacky} 4977199512Srdivacky 4978226633Sdimvoid Sema::CodeCompleteObjCPropertySetter(Scope *S) { 4979199512Srdivacky // Try to find the interface where setters might live. 4980199512Srdivacky ObjCInterfaceDecl *Class 4981226633Sdim = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); 4982199512Srdivacky if (!Class) { 4983199512Srdivacky if (ObjCCategoryDecl *Category 4984226633Sdim = dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) 4985199512Srdivacky Class = Category->getClassInterface(); 4986199512Srdivacky 4987199512Srdivacky if (!Class) 4988199512Srdivacky return; 4989199512Srdivacky } 4990199512Srdivacky 4991199512Srdivacky // Find all of the potential getters. 4992218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 4993234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 4994218893Sdim CodeCompletionContext::CCC_Other); 4995199512Srdivacky Results.EnterNewScope(); 4996199512Srdivacky 4997218893Sdim VisitedSelectorSet Selectors; 4998218893Sdim AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext, 4999218893Sdim Selectors, /*AllowSameLength=*/true, Results); 5000199512Srdivacky 5001199512Srdivacky Results.ExitScope(); 5002212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5003212904Sdim CodeCompletionContext::CCC_Other, 5004212904Sdim Results.data(),Results.size()); 5005199512Srdivacky} 5006199512Srdivacky 5007218893Sdimvoid Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, 5008218893Sdim bool IsParameter) { 5009218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5010234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5011218893Sdim CodeCompletionContext::CCC_Type); 5012212904Sdim Results.EnterNewScope(); 5013212904Sdim 5014212904Sdim // Add context-sensitive, Objective-C parameter-passing keywords. 5015212904Sdim bool AddedInOut = false; 5016212904Sdim if ((DS.getObjCDeclQualifier() & 5017212904Sdim (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) { 5018212904Sdim Results.AddResult("in"); 5019212904Sdim Results.AddResult("inout"); 5020212904Sdim AddedInOut = true; 5021212904Sdim } 5022212904Sdim if ((DS.getObjCDeclQualifier() & 5023212904Sdim (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) { 5024212904Sdim Results.AddResult("out"); 5025212904Sdim if (!AddedInOut) 5026212904Sdim Results.AddResult("inout"); 5027212904Sdim } 5028212904Sdim if ((DS.getObjCDeclQualifier() & 5029212904Sdim (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref | 5030212904Sdim ObjCDeclSpec::DQ_Oneway)) == 0) { 5031212904Sdim Results.AddResult("bycopy"); 5032212904Sdim Results.AddResult("byref"); 5033212904Sdim Results.AddResult("oneway"); 5034212904Sdim } 5035212904Sdim 5036218893Sdim // If we're completing the return type of an Objective-C method and the 5037218893Sdim // identifier IBAction refers to a macro, provide a completion item for 5038218893Sdim // an action, e.g., 5039218893Sdim // IBAction)<#selector#>:(id)sender 5040218893Sdim if (DS.getObjCDeclQualifier() == 0 && !IsParameter && 5041218893Sdim Context.Idents.get("IBAction").hasMacroDefinition()) { 5042234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 5043234353Sdim Results.getCodeCompletionTUInfo(), 5044234353Sdim CCP_CodePattern, CXAvailability_Available); 5045218893Sdim Builder.AddTypedTextChunk("IBAction"); 5046234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 5047218893Sdim Builder.AddPlaceholderChunk("selector"); 5048234353Sdim Builder.AddChunk(CodeCompletionString::CK_Colon); 5049234353Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 5050218893Sdim Builder.AddTextChunk("id"); 5051234353Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 5052218893Sdim Builder.AddTextChunk("sender"); 5053218893Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString())); 5054218893Sdim } 5055249423Sdim 5056249423Sdim // If we're completing the return type, provide 'instancetype'. 5057249423Sdim if (!IsParameter) { 5058249423Sdim Results.AddResult(CodeCompletionResult("instancetype")); 5059249423Sdim } 5060218893Sdim 5061212904Sdim // Add various builtin type names and specifiers. 5062212904Sdim AddOrdinaryNameResults(PCC_Type, S, *this, Results); 5063212904Sdim Results.ExitScope(); 5064212904Sdim 5065212904Sdim // Add the various type names 5066212904Sdim Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); 5067212904Sdim CodeCompletionDeclConsumer Consumer(Results, CurContext); 5068212904Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 5069212904Sdim CodeCompleter->includeGlobals()); 5070212904Sdim 5071212904Sdim if (CodeCompleter->includeMacros()) 5072243830Sdim AddMacroResults(PP, Results, false); 5073212904Sdim 5074212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5075212904Sdim CodeCompletionContext::CCC_Type, 5076212904Sdim Results.data(), Results.size()); 5077212904Sdim} 5078212904Sdim 5079207619Srdivacky/// \brief When we have an expression with type "id", we may assume 5080207619Srdivacky/// that it has some more-specific class type based on knowledge of 5081207619Srdivacky/// common uses of Objective-C. This routine returns that class type, 5082207619Srdivacky/// or NULL if no better result could be determined. 5083207619Srdivackystatic ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { 5084218893Sdim ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E); 5085207619Srdivacky if (!Msg) 5086207619Srdivacky return 0; 5087207619Srdivacky 5088207619Srdivacky Selector Sel = Msg->getSelector(); 5089207619Srdivacky if (Sel.isNull()) 5090207619Srdivacky return 0; 5091207619Srdivacky 5092207619Srdivacky IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0); 5093207619Srdivacky if (!Id) 5094207619Srdivacky return 0; 5095207619Srdivacky 5096207619Srdivacky ObjCMethodDecl *Method = Msg->getMethodDecl(); 5097207619Srdivacky if (!Method) 5098207619Srdivacky return 0; 5099207619Srdivacky 5100207619Srdivacky // Determine the class that we're sending the message to. 5101207619Srdivacky ObjCInterfaceDecl *IFace = 0; 5102207619Srdivacky switch (Msg->getReceiverKind()) { 5103207619Srdivacky case ObjCMessageExpr::Class: 5104208600Srdivacky if (const ObjCObjectType *ObjType 5105208600Srdivacky = Msg->getClassReceiver()->getAs<ObjCObjectType>()) 5106208600Srdivacky IFace = ObjType->getInterface(); 5107207619Srdivacky break; 5108207619Srdivacky 5109207619Srdivacky case ObjCMessageExpr::Instance: { 5110207619Srdivacky QualType T = Msg->getInstanceReceiver()->getType(); 5111207619Srdivacky if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) 5112207619Srdivacky IFace = Ptr->getInterfaceDecl(); 5113207619Srdivacky break; 5114207619Srdivacky } 5115207619Srdivacky 5116207619Srdivacky case ObjCMessageExpr::SuperInstance: 5117207619Srdivacky case ObjCMessageExpr::SuperClass: 5118207619Srdivacky break; 5119207619Srdivacky } 5120207619Srdivacky 5121207619Srdivacky if (!IFace) 5122207619Srdivacky return 0; 5123207619Srdivacky 5124207619Srdivacky ObjCInterfaceDecl *Super = IFace->getSuperClass(); 5125207619Srdivacky if (Method->isInstanceMethod()) 5126207619Srdivacky return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) 5127207619Srdivacky .Case("retain", IFace) 5128224145Sdim .Case("strong", IFace) 5129207619Srdivacky .Case("autorelease", IFace) 5130207619Srdivacky .Case("copy", IFace) 5131207619Srdivacky .Case("copyWithZone", IFace) 5132207619Srdivacky .Case("mutableCopy", IFace) 5133207619Srdivacky .Case("mutableCopyWithZone", IFace) 5134207619Srdivacky .Case("awakeFromCoder", IFace) 5135207619Srdivacky .Case("replacementObjectFromCoder", IFace) 5136207619Srdivacky .Case("class", IFace) 5137207619Srdivacky .Case("classForCoder", IFace) 5138207619Srdivacky .Case("superclass", Super) 5139207619Srdivacky .Default(0); 5140207619Srdivacky 5141207619Srdivacky return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) 5142207619Srdivacky .Case("new", IFace) 5143207619Srdivacky .Case("alloc", IFace) 5144207619Srdivacky .Case("allocWithZone", IFace) 5145207619Srdivacky .Case("class", IFace) 5146207619Srdivacky .Case("superclass", Super) 5147207619Srdivacky .Default(0); 5148207619Srdivacky} 5149207619Srdivacky 5150212904Sdim// Add a special completion for a message send to "super", which fills in the 5151212904Sdim// most likely case of forwarding all of our arguments to the superclass 5152212904Sdim// function. 5153212904Sdim/// 5154212904Sdim/// \param S The semantic analysis object. 5155212904Sdim/// 5156243830Sdim/// \param NeedSuperKeyword Whether we need to prefix this completion with 5157212904Sdim/// the "super" keyword. Otherwise, we just need to provide the arguments. 5158212904Sdim/// 5159212904Sdim/// \param SelIdents The identifiers in the selector that have already been 5160212904Sdim/// provided as arguments for a send to "super". 5161212904Sdim/// 5162212904Sdim/// \param NumSelIdents The number of identifiers in \p SelIdents. 5163212904Sdim/// 5164212904Sdim/// \param Results The set of results to augment. 5165212904Sdim/// 5166212904Sdim/// \returns the Objective-C method declaration that would be invoked by 5167212904Sdim/// this "super" completion. If NULL, no completion was added. 5168212904Sdimstatic ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, 5169212904Sdim IdentifierInfo **SelIdents, 5170212904Sdim unsigned NumSelIdents, 5171212904Sdim ResultBuilder &Results) { 5172212904Sdim ObjCMethodDecl *CurMethod = S.getCurMethodDecl(); 5173212904Sdim if (!CurMethod) 5174212904Sdim return 0; 5175212904Sdim 5176212904Sdim ObjCInterfaceDecl *Class = CurMethod->getClassInterface(); 5177212904Sdim if (!Class) 5178212904Sdim return 0; 5179212904Sdim 5180212904Sdim // Try to find a superclass method with the same selector. 5181212904Sdim ObjCMethodDecl *SuperMethod = 0; 5182218893Sdim while ((Class = Class->getSuperClass()) && !SuperMethod) { 5183218893Sdim // Check in the class 5184212904Sdim SuperMethod = Class->getMethod(CurMethod->getSelector(), 5185212904Sdim CurMethod->isInstanceMethod()); 5186212904Sdim 5187218893Sdim // Check in categories or class extensions. 5188218893Sdim if (!SuperMethod) { 5189249423Sdim for (ObjCInterfaceDecl::known_categories_iterator 5190249423Sdim Cat = Class->known_categories_begin(), 5191249423Sdim CatEnd = Class->known_categories_end(); 5192249423Sdim Cat != CatEnd; ++Cat) { 5193249423Sdim if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(), 5194218893Sdim CurMethod->isInstanceMethod()))) 5195218893Sdim break; 5196249423Sdim } 5197218893Sdim } 5198218893Sdim } 5199218893Sdim 5200212904Sdim if (!SuperMethod) 5201212904Sdim return 0; 5202212904Sdim 5203212904Sdim // Check whether the superclass method has the same signature. 5204212904Sdim if (CurMethod->param_size() != SuperMethod->param_size() || 5205212904Sdim CurMethod->isVariadic() != SuperMethod->isVariadic()) 5206212904Sdim return 0; 5207212904Sdim 5208212904Sdim for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(), 5209212904Sdim CurPEnd = CurMethod->param_end(), 5210212904Sdim SuperP = SuperMethod->param_begin(); 5211212904Sdim CurP != CurPEnd; ++CurP, ++SuperP) { 5212212904Sdim // Make sure the parameter types are compatible. 5213212904Sdim if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), 5214212904Sdim (*SuperP)->getType())) 5215212904Sdim return 0; 5216212904Sdim 5217212904Sdim // Make sure we have a parameter name to forward! 5218212904Sdim if (!(*CurP)->getIdentifier()) 5219212904Sdim return 0; 5220212904Sdim } 5221212904Sdim 5222212904Sdim // We have a superclass method. Now, form the send-to-super completion. 5223234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 5224234353Sdim Results.getCodeCompletionTUInfo()); 5225212904Sdim 5226212904Sdim // Give this completion a return type. 5227226633Sdim AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod, 5228226633Sdim Builder); 5229212904Sdim 5230212904Sdim // If we need the "super" keyword, add it (plus some spacing). 5231212904Sdim if (NeedSuperKeyword) { 5232218893Sdim Builder.AddTypedTextChunk("super"); 5233218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 5234212904Sdim } 5235212904Sdim 5236212904Sdim Selector Sel = CurMethod->getSelector(); 5237212904Sdim if (Sel.isUnarySelector()) { 5238212904Sdim if (NeedSuperKeyword) 5239218893Sdim Builder.AddTextChunk(Builder.getAllocator().CopyString( 5240218893Sdim Sel.getNameForSlot(0))); 5241212904Sdim else 5242218893Sdim Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( 5243218893Sdim Sel.getNameForSlot(0))); 5244212904Sdim } else { 5245212904Sdim ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(); 5246212904Sdim for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { 5247212904Sdim if (I > NumSelIdents) 5248218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 5249212904Sdim 5250212904Sdim if (I < NumSelIdents) 5251218893Sdim Builder.AddInformativeChunk( 5252218893Sdim Builder.getAllocator().CopyString( 5253218893Sdim Sel.getNameForSlot(I) + ":")); 5254212904Sdim else if (NeedSuperKeyword || I > NumSelIdents) { 5255218893Sdim Builder.AddTextChunk( 5256218893Sdim Builder.getAllocator().CopyString( 5257218893Sdim Sel.getNameForSlot(I) + ":")); 5258218893Sdim Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( 5259218893Sdim (*CurP)->getIdentifier()->getName())); 5260212904Sdim } else { 5261218893Sdim Builder.AddTypedTextChunk( 5262218893Sdim Builder.getAllocator().CopyString( 5263218893Sdim Sel.getNameForSlot(I) + ":")); 5264218893Sdim Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( 5265218893Sdim (*CurP)->getIdentifier()->getName())); 5266212904Sdim } 5267212904Sdim } 5268212904Sdim } 5269212904Sdim 5270234353Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod, 5271234353Sdim CCP_SuperCompletion)); 5272212904Sdim return SuperMethod; 5273212904Sdim} 5274212904Sdim 5275210299Sedvoid Sema::CodeCompleteObjCMessageReceiver(Scope *S) { 5276212904Sdim typedef CodeCompletionResult Result; 5277218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5278234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5279218893Sdim CodeCompletionContext::CCC_ObjCMessageReceiver, 5280249423Sdim getLangOpts().CPlusPlus11 5281234353Sdim ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture 5282234353Sdim : &ResultBuilder::IsObjCMessageReceiver); 5283210299Sed 5284210299Sed CodeCompletionDeclConsumer Consumer(Results, CurContext); 5285210299Sed Results.EnterNewScope(); 5286212904Sdim LookupVisibleDecls(S, LookupOrdinaryName, Consumer, 5287212904Sdim CodeCompleter->includeGlobals()); 5288210299Sed 5289210299Sed // If we are in an Objective-C method inside a class that has a superclass, 5290210299Sed // add "super" as an option. 5291210299Sed if (ObjCMethodDecl *Method = getCurMethodDecl()) 5292210299Sed if (ObjCInterfaceDecl *Iface = Method->getClassInterface()) 5293212904Sdim if (Iface->getSuperClass()) { 5294210299Sed Results.AddResult(Result("super")); 5295212904Sdim 5296212904Sdim AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results); 5297212904Sdim } 5298210299Sed 5299249423Sdim if (getLangOpts().CPlusPlus11) 5300234353Sdim addThisCompletion(*this, Results); 5301234353Sdim 5302210299Sed Results.ExitScope(); 5303210299Sed 5304210299Sed if (CodeCompleter->includeMacros()) 5305243830Sdim AddMacroResults(PP, Results, false); 5306218893Sdim HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), 5307212904Sdim Results.data(), Results.size()); 5308210299Sed 5309210299Sed} 5310210299Sed 5311207619Srdivackyvoid Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, 5312199512Srdivacky IdentifierInfo **SelIdents, 5313218893Sdim unsigned NumSelIdents, 5314218893Sdim bool AtArgumentExpression) { 5315199482Srdivacky ObjCInterfaceDecl *CDecl = 0; 5316207619Srdivacky if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { 5317207619Srdivacky // Figure out which interface we're in. 5318207619Srdivacky CDecl = CurMethod->getClassInterface(); 5319207619Srdivacky if (!CDecl) 5320207619Srdivacky return; 5321207619Srdivacky 5322207619Srdivacky // Find the superclass of this class. 5323207619Srdivacky CDecl = CDecl->getSuperClass(); 5324207619Srdivacky if (!CDecl) 5325207619Srdivacky return; 5326199482Srdivacky 5327207619Srdivacky if (CurMethod->isInstanceMethod()) { 5328207619Srdivacky // We are inside an instance method, which means that the message 5329207619Srdivacky // send [super ...] is actually calling an instance method on the 5330218893Sdim // current object. 5331218893Sdim return CodeCompleteObjCInstanceMessage(S, 0, 5332212904Sdim SelIdents, NumSelIdents, 5333218893Sdim AtArgumentExpression, 5334218893Sdim CDecl); 5335207619Srdivacky } 5336199482Srdivacky 5337207619Srdivacky // Fall through to send to the superclass in CDecl. 5338207619Srdivacky } else { 5339207619Srdivacky // "super" may be the name of a type or variable. Figure out which 5340207619Srdivacky // it is. 5341249423Sdim IdentifierInfo *Super = getSuperIdentifier(); 5342207619Srdivacky NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, 5343207619Srdivacky LookupOrdinaryName); 5344207619Srdivacky if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) { 5345207619Srdivacky // "super" names an interface. Use it. 5346207619Srdivacky } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) { 5347208600Srdivacky if (const ObjCObjectType *Iface 5348208600Srdivacky = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>()) 5349208600Srdivacky CDecl = Iface->getInterface(); 5350207619Srdivacky } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) { 5351207619Srdivacky // "super" names an unresolved type; we can't be more specific. 5352207619Srdivacky } else { 5353207619Srdivacky // Assume that "super" names some kind of value and parse that way. 5354207619Srdivacky CXXScopeSpec SS; 5355234353Sdim SourceLocation TemplateKWLoc; 5356207619Srdivacky UnqualifiedId id; 5357207619Srdivacky id.setIdentifier(Super, SuperLoc); 5358234353Sdim ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, 5359234353Sdim false, false); 5360207619Srdivacky return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), 5361218893Sdim SelIdents, NumSelIdents, 5362218893Sdim AtArgumentExpression); 5363207619Srdivacky } 5364199482Srdivacky 5365207619Srdivacky // Fall through 5366199482Srdivacky } 5367199482Srdivacky 5368212904Sdim ParsedType Receiver; 5369207619Srdivacky if (CDecl) 5370212904Sdim Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl)); 5371207619Srdivacky return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, 5372218893Sdim NumSelIdents, AtArgumentExpression, 5373218893Sdim /*IsSuper=*/true); 5374207619Srdivacky} 5375207619Srdivacky 5376218893Sdim/// \brief Given a set of code-completion results for the argument of a message 5377218893Sdim/// send, determine the preferred type (if any) for that argument expression. 5378218893Sdimstatic QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, 5379218893Sdim unsigned NumSelIdents) { 5380218893Sdim typedef CodeCompletionResult Result; 5381218893Sdim ASTContext &Context = Results.getSema().Context; 5382218893Sdim 5383218893Sdim QualType PreferredType; 5384218893Sdim unsigned BestPriority = CCP_Unlikely * 2; 5385218893Sdim Result *ResultsData = Results.data(); 5386218893Sdim for (unsigned I = 0, N = Results.size(); I != N; ++I) { 5387218893Sdim Result &R = ResultsData[I]; 5388218893Sdim if (R.Kind == Result::RK_Declaration && 5389218893Sdim isa<ObjCMethodDecl>(R.Declaration)) { 5390218893Sdim if (R.Priority <= BestPriority) { 5391249423Sdim const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration); 5392218893Sdim if (NumSelIdents <= Method->param_size()) { 5393218893Sdim QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1] 5394218893Sdim ->getType(); 5395218893Sdim if (R.Priority < BestPriority || PreferredType.isNull()) { 5396218893Sdim BestPriority = R.Priority; 5397218893Sdim PreferredType = MyPreferredType; 5398218893Sdim } else if (!Context.hasSameUnqualifiedType(PreferredType, 5399218893Sdim MyPreferredType)) { 5400218893Sdim PreferredType = QualType(); 5401218893Sdim } 5402218893Sdim } 5403218893Sdim } 5404218893Sdim } 5405218893Sdim } 5406218893Sdim 5407218893Sdim return PreferredType; 5408212904Sdim} 5409212904Sdim 5410218893Sdimstatic void AddClassMessageCompletions(Sema &SemaRef, Scope *S, 5411218893Sdim ParsedType Receiver, 5412218893Sdim IdentifierInfo **SelIdents, 5413218893Sdim unsigned NumSelIdents, 5414218893Sdim bool AtArgumentExpression, 5415218893Sdim bool IsSuper, 5416218893Sdim ResultBuilder &Results) { 5417212904Sdim typedef CodeCompletionResult Result; 5418207619Srdivacky ObjCInterfaceDecl *CDecl = 0; 5419218893Sdim 5420199482Srdivacky // If the given name refers to an interface type, retrieve the 5421199482Srdivacky // corresponding declaration. 5422207619Srdivacky if (Receiver) { 5423218893Sdim QualType T = SemaRef.GetTypeFromParser(Receiver, 0); 5424207619Srdivacky if (!T.isNull()) 5425208600Srdivacky if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>()) 5426208600Srdivacky CDecl = Interface->getInterface(); 5427199482Srdivacky } 5428218893Sdim 5429199482Srdivacky // Add all of the factory methods in this Objective-C class, its protocols, 5430199482Srdivacky // superclasses, categories, implementation, etc. 5431199482Srdivacky Results.EnterNewScope(); 5432218893Sdim 5433212904Sdim // If this is a send-to-super, try to add the special "super" send 5434212904Sdim // completion. 5435212904Sdim if (IsSuper) { 5436212904Sdim if (ObjCMethodDecl *SuperMethod 5437218893Sdim = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents, 5438218893Sdim Results)) 5439212904Sdim Results.Ignore(SuperMethod); 5440212904Sdim } 5441218893Sdim 5442212904Sdim // If we're inside an Objective-C method definition, prefer its selector to 5443212904Sdim // others. 5444218893Sdim if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) 5445212904Sdim Results.setPreferredSelector(CurMethod->getSelector()); 5446218893Sdim 5447218893Sdim VisitedSelectorSet Selectors; 5448207619Srdivacky if (CDecl) 5449218893Sdim AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents, 5450218893Sdim SemaRef.CurContext, Selectors, AtArgumentExpression, 5451207619Srdivacky Results); 5452207619Srdivacky else { 5453207619Srdivacky // We're messaging "id" as a type; provide all class/factory methods. 5454218893Sdim 5455207619Srdivacky // If we have an external source, load the entire class method 5456212904Sdim // pool from the AST file. 5457243830Sdim if (SemaRef.getExternalSource()) { 5458218893Sdim for (uint32_t I = 0, 5459243830Sdim N = SemaRef.getExternalSource()->GetNumExternalSelectors(); 5460210299Sed I != N; ++I) { 5461243830Sdim Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I); 5462218893Sdim if (Sel.isNull() || SemaRef.MethodPool.count(Sel)) 5463207619Srdivacky continue; 5464218893Sdim 5465218893Sdim SemaRef.ReadMethodPool(Sel); 5466207619Srdivacky } 5467207619Srdivacky } 5468218893Sdim 5469218893Sdim for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(), 5470218893Sdim MEnd = SemaRef.MethodPool.end(); 5471212904Sdim M != MEnd; ++M) { 5472212904Sdim for (ObjCMethodList *MethList = &M->second.second; 5473212904Sdim MethList && MethList->Method; 5474251662Sdim MethList = MethList->getNext()) { 5475207619Srdivacky if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 5476207619Srdivacky NumSelIdents)) 5477207619Srdivacky continue; 5478218893Sdim 5479249423Sdim Result R(MethList->Method, Results.getBasePriority(MethList->Method),0); 5480207619Srdivacky R.StartParameter = NumSelIdents; 5481207619Srdivacky R.AllParametersAreInformative = false; 5482218893Sdim Results.MaybeAddResult(R, SemaRef.CurContext); 5483207619Srdivacky } 5484207619Srdivacky } 5485207619Srdivacky } 5486218893Sdim 5487218893Sdim Results.ExitScope(); 5488218893Sdim} 5489207619Srdivacky 5490218893Sdimvoid Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, 5491218893Sdim IdentifierInfo **SelIdents, 5492218893Sdim unsigned NumSelIdents, 5493218893Sdim bool AtArgumentExpression, 5494218893Sdim bool IsSuper) { 5495226633Sdim 5496226633Sdim QualType T = this->GetTypeFromParser(Receiver); 5497226633Sdim 5498218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5499234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5500226633Sdim CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, 5501226633Sdim T, SelIdents, NumSelIdents)); 5502226633Sdim 5503218893Sdim AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents, 5504218893Sdim AtArgumentExpression, IsSuper, Results); 5505218893Sdim 5506218893Sdim // If we're actually at the argument expression (rather than prior to the 5507218893Sdim // selector), we're actually performing code completion for an expression. 5508218893Sdim // Determine whether we have a single, best method. If so, we can 5509218893Sdim // code-complete the expression using the corresponding parameter type as 5510218893Sdim // our preferred type, improving completion results. 5511218893Sdim if (AtArgumentExpression) { 5512218893Sdim QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, 5513226633Sdim NumSelIdents); 5514218893Sdim if (PreferredType.isNull()) 5515218893Sdim CodeCompleteOrdinaryName(S, PCC_Expression); 5516218893Sdim else 5517218893Sdim CodeCompleteExpression(S, PreferredType); 5518218893Sdim return; 5519218893Sdim } 5520218893Sdim 5521212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5522226633Sdim Results.getCompletionContext(), 5523212904Sdim Results.data(), Results.size()); 5524199482Srdivacky} 5525199482Srdivacky 5526226633Sdimvoid Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, 5527199512Srdivacky IdentifierInfo **SelIdents, 5528212904Sdim unsigned NumSelIdents, 5529218893Sdim bool AtArgumentExpression, 5530218893Sdim ObjCInterfaceDecl *Super) { 5531212904Sdim typedef CodeCompletionResult Result; 5532199482Srdivacky 5533199482Srdivacky Expr *RecExpr = static_cast<Expr *>(Receiver); 5534199482Srdivacky 5535199482Srdivacky // If necessary, apply function/array conversion to the receiver. 5536199482Srdivacky // C99 6.7.5.3p[7,8]. 5537221345Sdim if (RecExpr) { 5538221345Sdim ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr); 5539221345Sdim if (Conv.isInvalid()) // conversion failed. bail. 5540221345Sdim return; 5541221345Sdim RecExpr = Conv.take(); 5542221345Sdim } 5543218893Sdim QualType ReceiverType = RecExpr? RecExpr->getType() 5544218893Sdim : Super? Context.getObjCObjectPointerType( 5545218893Sdim Context.getObjCInterfaceType(Super)) 5546218893Sdim : Context.getObjCIdType(); 5547199482Srdivacky 5548218893Sdim // If we're messaging an expression with type "id" or "Class", check 5549218893Sdim // whether we know something special about the receiver that allows 5550218893Sdim // us to assume a more-specific receiver type. 5551218893Sdim if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) 5552218893Sdim if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) { 5553218893Sdim if (ReceiverType->isObjCClassType()) 5554218893Sdim return CodeCompleteObjCClassMessage(S, 5555218893Sdim ParsedType::make(Context.getObjCInterfaceType(IFace)), 5556218893Sdim SelIdents, NumSelIdents, 5557218893Sdim AtArgumentExpression, Super); 5558218893Sdim 5559218893Sdim ReceiverType = Context.getObjCObjectPointerType( 5560218893Sdim Context.getObjCInterfaceType(IFace)); 5561218893Sdim } 5562218893Sdim 5563199482Srdivacky // Build the set of methods we can see. 5564218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5565234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5566226633Sdim CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, 5567226633Sdim ReceiverType, SelIdents, NumSelIdents)); 5568226633Sdim 5569199482Srdivacky Results.EnterNewScope(); 5570207619Srdivacky 5571212904Sdim // If this is a send-to-super, try to add the special "super" send 5572212904Sdim // completion. 5573218893Sdim if (Super) { 5574212904Sdim if (ObjCMethodDecl *SuperMethod 5575212904Sdim = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents, 5576212904Sdim Results)) 5577212904Sdim Results.Ignore(SuperMethod); 5578212904Sdim } 5579212904Sdim 5580212904Sdim // If we're inside an Objective-C method definition, prefer its selector to 5581212904Sdim // others. 5582212904Sdim if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) 5583212904Sdim Results.setPreferredSelector(CurMethod->getSelector()); 5584199482Srdivacky 5585218893Sdim // Keep track of the selectors we've already added. 5586218893Sdim VisitedSelectorSet Selectors; 5587218893Sdim 5588199482Srdivacky // Handle messages to Class. This really isn't a message to an instance 5589199482Srdivacky // method, so we treat it the same way we would treat a message send to a 5590199482Srdivacky // class method. 5591199482Srdivacky if (ReceiverType->isObjCClassType() || 5592199482Srdivacky ReceiverType->isObjCQualifiedClassType()) { 5593199482Srdivacky if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { 5594199482Srdivacky if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) 5595199512Srdivacky AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents, 5596218893Sdim CurContext, Selectors, AtArgumentExpression, Results); 5597199482Srdivacky } 5598199482Srdivacky } 5599199482Srdivacky // Handle messages to a qualified ID ("id<foo>"). 5600199482Srdivacky else if (const ObjCObjectPointerType *QualID 5601199482Srdivacky = ReceiverType->getAsObjCQualifiedIdType()) { 5602199482Srdivacky // Search protocols for instance methods. 5603199482Srdivacky for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(), 5604199482Srdivacky E = QualID->qual_end(); 5605199482Srdivacky I != E; ++I) 5606199512Srdivacky AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, 5607218893Sdim Selectors, AtArgumentExpression, Results); 5608199482Srdivacky } 5609199482Srdivacky // Handle messages to a pointer to interface type. 5610199482Srdivacky else if (const ObjCObjectPointerType *IFacePtr 5611199482Srdivacky = ReceiverType->getAsObjCInterfacePointerType()) { 5612199482Srdivacky // Search the class, its superclasses, etc., for instance methods. 5613199512Srdivacky AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, 5614218893Sdim NumSelIdents, CurContext, Selectors, AtArgumentExpression, 5615218893Sdim Results); 5616199482Srdivacky 5617199482Srdivacky // Search protocols for instance methods. 5618199482Srdivacky for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(), 5619199482Srdivacky E = IFacePtr->qual_end(); 5620199482Srdivacky I != E; ++I) 5621199512Srdivacky AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext, 5622218893Sdim Selectors, AtArgumentExpression, Results); 5623199482Srdivacky } 5624207619Srdivacky // Handle messages to "id". 5625207619Srdivacky else if (ReceiverType->isObjCIdType()) { 5626207619Srdivacky // We're messaging "id", so provide all instance methods we know 5627207619Srdivacky // about as code-completion results. 5628207619Srdivacky 5629207619Srdivacky // If we have an external source, load the entire class method 5630212904Sdim // pool from the AST file. 5631207619Srdivacky if (ExternalSource) { 5632210299Sed for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); 5633210299Sed I != N; ++I) { 5634210299Sed Selector Sel = ExternalSource->GetExternalSelector(I); 5635212904Sdim if (Sel.isNull() || MethodPool.count(Sel)) 5636207619Srdivacky continue; 5637207619Srdivacky 5638212904Sdim ReadMethodPool(Sel); 5639207619Srdivacky } 5640207619Srdivacky } 5641207619Srdivacky 5642212904Sdim for (GlobalMethodPool::iterator M = MethodPool.begin(), 5643212904Sdim MEnd = MethodPool.end(); 5644212904Sdim M != MEnd; ++M) { 5645212904Sdim for (ObjCMethodList *MethList = &M->second.first; 5646212904Sdim MethList && MethList->Method; 5647251662Sdim MethList = MethList->getNext()) { 5648207619Srdivacky if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 5649207619Srdivacky NumSelIdents)) 5650207619Srdivacky continue; 5651218893Sdim 5652218893Sdim if (!Selectors.insert(MethList->Method->getSelector())) 5653218893Sdim continue; 5654218893Sdim 5655249423Sdim Result R(MethList->Method, Results.getBasePriority(MethList->Method),0); 5656207619Srdivacky R.StartParameter = NumSelIdents; 5657207619Srdivacky R.AllParametersAreInformative = false; 5658207619Srdivacky Results.MaybeAddResult(R, CurContext); 5659207619Srdivacky } 5660207619Srdivacky } 5661207619Srdivacky } 5662199482Srdivacky Results.ExitScope(); 5663218893Sdim 5664218893Sdim 5665218893Sdim // If we're actually at the argument expression (rather than prior to the 5666218893Sdim // selector), we're actually performing code completion for an expression. 5667218893Sdim // Determine whether we have a single, best method. If so, we can 5668218893Sdim // code-complete the expression using the corresponding parameter type as 5669218893Sdim // our preferred type, improving completion results. 5670218893Sdim if (AtArgumentExpression) { 5671218893Sdim QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results, 5672218893Sdim NumSelIdents); 5673218893Sdim if (PreferredType.isNull()) 5674218893Sdim CodeCompleteOrdinaryName(S, PCC_Expression); 5675218893Sdim else 5676218893Sdim CodeCompleteExpression(S, PreferredType); 5677218893Sdim return; 5678218893Sdim } 5679218893Sdim 5680212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5681226633Sdim Results.getCompletionContext(), 5682212904Sdim Results.data(),Results.size()); 5683199482Srdivacky} 5684199482Srdivacky 5685212904Sdimvoid Sema::CodeCompleteObjCForCollection(Scope *S, 5686212904Sdim DeclGroupPtrTy IterationVar) { 5687212904Sdim CodeCompleteExpressionData Data; 5688212904Sdim Data.ObjCCollection = true; 5689212904Sdim 5690212904Sdim if (IterationVar.getAsOpaquePtr()) { 5691212904Sdim DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>(); 5692212904Sdim for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) { 5693212904Sdim if (*I) 5694212904Sdim Data.IgnoreDecls.push_back(*I); 5695212904Sdim } 5696212904Sdim } 5697212904Sdim 5698212904Sdim CodeCompleteExpression(S, Data); 5699212904Sdim} 5700212904Sdim 5701212904Sdimvoid Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents, 5702212904Sdim unsigned NumSelIdents) { 5703212904Sdim // If we have an external source, load the entire class method 5704212904Sdim // pool from the AST file. 5705212904Sdim if (ExternalSource) { 5706212904Sdim for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); 5707212904Sdim I != N; ++I) { 5708212904Sdim Selector Sel = ExternalSource->GetExternalSelector(I); 5709212904Sdim if (Sel.isNull() || MethodPool.count(Sel)) 5710212904Sdim continue; 5711212904Sdim 5712212904Sdim ReadMethodPool(Sel); 5713212904Sdim } 5714212904Sdim } 5715212904Sdim 5716218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5717234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5718218893Sdim CodeCompletionContext::CCC_SelectorName); 5719212904Sdim Results.EnterNewScope(); 5720212904Sdim for (GlobalMethodPool::iterator M = MethodPool.begin(), 5721212904Sdim MEnd = MethodPool.end(); 5722212904Sdim M != MEnd; ++M) { 5723212904Sdim 5724212904Sdim Selector Sel = M->first; 5725212904Sdim if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents)) 5726212904Sdim continue; 5727212904Sdim 5728234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 5729234353Sdim Results.getCodeCompletionTUInfo()); 5730212904Sdim if (Sel.isUnarySelector()) { 5731218893Sdim Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( 5732218893Sdim Sel.getNameForSlot(0))); 5733218893Sdim Results.AddResult(Builder.TakeString()); 5734212904Sdim continue; 5735212904Sdim } 5736212904Sdim 5737212904Sdim std::string Accumulator; 5738212904Sdim for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { 5739212904Sdim if (I == NumSelIdents) { 5740212904Sdim if (!Accumulator.empty()) { 5741218893Sdim Builder.AddInformativeChunk(Builder.getAllocator().CopyString( 5742218893Sdim Accumulator)); 5743212904Sdim Accumulator.clear(); 5744212904Sdim } 5745212904Sdim } 5746212904Sdim 5747226633Sdim Accumulator += Sel.getNameForSlot(I); 5748212904Sdim Accumulator += ':'; 5749212904Sdim } 5750218893Sdim Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator)); 5751218893Sdim Results.AddResult(Builder.TakeString()); 5752212904Sdim } 5753212904Sdim Results.ExitScope(); 5754212904Sdim 5755212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5756212904Sdim CodeCompletionContext::CCC_SelectorName, 5757212904Sdim Results.data(), Results.size()); 5758212904Sdim} 5759212904Sdim 5760199482Srdivacky/// \brief Add all of the protocol declarations that we find in the given 5761199482Srdivacky/// (translation unit) context. 5762199482Srdivackystatic void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, 5763199482Srdivacky bool OnlyForwardDeclarations, 5764199482Srdivacky ResultBuilder &Results) { 5765212904Sdim typedef CodeCompletionResult Result; 5766199482Srdivacky 5767199482Srdivacky for (DeclContext::decl_iterator D = Ctx->decls_begin(), 5768199482Srdivacky DEnd = Ctx->decls_end(); 5769199482Srdivacky D != DEnd; ++D) { 5770199482Srdivacky // Record any protocols we find. 5771199482Srdivacky if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D)) 5772234353Sdim if (!OnlyForwardDeclarations || !Proto->hasDefinition()) 5773249423Sdim Results.AddResult(Result(Proto, Results.getBasePriority(Proto), 0), 5774249423Sdim CurContext, 0, false); 5775199482Srdivacky } 5776199482Srdivacky} 5777199482Srdivacky 5778199482Srdivackyvoid Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, 5779199482Srdivacky unsigned NumProtocols) { 5780218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5781234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5782218893Sdim CodeCompletionContext::CCC_ObjCProtocolName); 5783199482Srdivacky 5784218893Sdim if (CodeCompleter && CodeCompleter->includeGlobals()) { 5785218893Sdim Results.EnterNewScope(); 5786218893Sdim 5787218893Sdim // Tell the result set to ignore all of the protocols we have 5788218893Sdim // already seen. 5789218893Sdim // FIXME: This doesn't work when caching code-completion results. 5790218893Sdim for (unsigned I = 0; I != NumProtocols; ++I) 5791218893Sdim if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first, 5792218893Sdim Protocols[I].second)) 5793218893Sdim Results.Ignore(Protocol); 5794199482Srdivacky 5795218893Sdim // Add all protocols. 5796218893Sdim AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false, 5797218893Sdim Results); 5798199482Srdivacky 5799218893Sdim Results.ExitScope(); 5800218893Sdim } 5801218893Sdim 5802212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5803212904Sdim CodeCompletionContext::CCC_ObjCProtocolName, 5804212904Sdim Results.data(),Results.size()); 5805199482Srdivacky} 5806199482Srdivacky 5807199482Srdivackyvoid Sema::CodeCompleteObjCProtocolDecl(Scope *) { 5808218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5809234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5810218893Sdim CodeCompletionContext::CCC_ObjCProtocolName); 5811199482Srdivacky 5812218893Sdim if (CodeCompleter && CodeCompleter->includeGlobals()) { 5813218893Sdim Results.EnterNewScope(); 5814218893Sdim 5815218893Sdim // Add all protocols. 5816218893Sdim AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, 5817218893Sdim Results); 5818199482Srdivacky 5819218893Sdim Results.ExitScope(); 5820218893Sdim } 5821218893Sdim 5822212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5823212904Sdim CodeCompletionContext::CCC_ObjCProtocolName, 5824212904Sdim Results.data(),Results.size()); 5825199482Srdivacky} 5826199512Srdivacky 5827199512Srdivacky/// \brief Add all of the Objective-C interface declarations that we find in 5828199512Srdivacky/// the given (translation unit) context. 5829199512Srdivackystatic void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, 5830199512Srdivacky bool OnlyForwardDeclarations, 5831199512Srdivacky bool OnlyUnimplemented, 5832199512Srdivacky ResultBuilder &Results) { 5833212904Sdim typedef CodeCompletionResult Result; 5834199512Srdivacky 5835199512Srdivacky for (DeclContext::decl_iterator D = Ctx->decls_begin(), 5836199512Srdivacky DEnd = Ctx->decls_end(); 5837199512Srdivacky D != DEnd; ++D) { 5838199512Srdivacky // Record any interfaces we find. 5839199512Srdivacky if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D)) 5840234353Sdim if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && 5841199512Srdivacky (!OnlyUnimplemented || !Class->getImplementation())) 5842249423Sdim Results.AddResult(Result(Class, Results.getBasePriority(Class), 0), 5843249423Sdim CurContext, 0, false); 5844199512Srdivacky } 5845199512Srdivacky} 5846199512Srdivacky 5847199512Srdivackyvoid Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { 5848218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5849234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5850218893Sdim CodeCompletionContext::CCC_Other); 5851199512Srdivacky Results.EnterNewScope(); 5852199512Srdivacky 5853226633Sdim if (CodeCompleter->includeGlobals()) { 5854226633Sdim // Add all classes. 5855226633Sdim AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, 5856226633Sdim false, Results); 5857226633Sdim } 5858226633Sdim 5859226633Sdim Results.ExitScope(); 5860199512Srdivacky 5861212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5862226633Sdim CodeCompletionContext::CCC_ObjCInterfaceName, 5863212904Sdim Results.data(),Results.size()); 5864199512Srdivacky} 5865199512Srdivacky 5866207619Srdivackyvoid Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, 5867207619Srdivacky SourceLocation ClassNameLoc) { 5868218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5869234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5870226633Sdim CodeCompletionContext::CCC_ObjCInterfaceName); 5871199512Srdivacky Results.EnterNewScope(); 5872199512Srdivacky 5873199512Srdivacky // Make sure that we ignore the class we're currently defining. 5874199512Srdivacky NamedDecl *CurClass 5875207619Srdivacky = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); 5876199512Srdivacky if (CurClass && isa<ObjCInterfaceDecl>(CurClass)) 5877199512Srdivacky Results.Ignore(CurClass); 5878199512Srdivacky 5879226633Sdim if (CodeCompleter->includeGlobals()) { 5880226633Sdim // Add all classes. 5881226633Sdim AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, 5882226633Sdim false, Results); 5883226633Sdim } 5884226633Sdim 5885226633Sdim Results.ExitScope(); 5886199512Srdivacky 5887212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5888226633Sdim CodeCompletionContext::CCC_ObjCInterfaceName, 5889212904Sdim Results.data(),Results.size()); 5890199512Srdivacky} 5891199512Srdivacky 5892199512Srdivackyvoid Sema::CodeCompleteObjCImplementationDecl(Scope *S) { 5893218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5894234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5895218893Sdim CodeCompletionContext::CCC_Other); 5896199512Srdivacky Results.EnterNewScope(); 5897199512Srdivacky 5898226633Sdim if (CodeCompleter->includeGlobals()) { 5899226633Sdim // Add all unimplemented classes. 5900226633Sdim AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, 5901226633Sdim true, Results); 5902226633Sdim } 5903226633Sdim 5904226633Sdim Results.ExitScope(); 5905199512Srdivacky 5906212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5907226633Sdim CodeCompletionContext::CCC_ObjCInterfaceName, 5908212904Sdim Results.data(),Results.size()); 5909199512Srdivacky} 5910199512Srdivacky 5911199512Srdivackyvoid Sema::CodeCompleteObjCInterfaceCategory(Scope *S, 5912207619Srdivacky IdentifierInfo *ClassName, 5913207619Srdivacky SourceLocation ClassNameLoc) { 5914212904Sdim typedef CodeCompletionResult Result; 5915199512Srdivacky 5916218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5917234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5918224145Sdim CodeCompletionContext::CCC_ObjCCategoryName); 5919199512Srdivacky 5920199512Srdivacky // Ignore any categories we find that have already been implemented by this 5921199512Srdivacky // interface. 5922199512Srdivacky llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; 5923199512Srdivacky NamedDecl *CurClass 5924207619Srdivacky = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); 5925249423Sdim if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){ 5926249423Sdim for (ObjCInterfaceDecl::visible_categories_iterator 5927249423Sdim Cat = Class->visible_categories_begin(), 5928249423Sdim CatEnd = Class->visible_categories_end(); 5929249423Sdim Cat != CatEnd; ++Cat) { 5930249423Sdim CategoryNames.insert(Cat->getIdentifier()); 5931249423Sdim } 5932249423Sdim } 5933249423Sdim 5934199512Srdivacky // Add all of the categories we know about. 5935199512Srdivacky Results.EnterNewScope(); 5936199512Srdivacky TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); 5937199512Srdivacky for (DeclContext::decl_iterator D = TU->decls_begin(), 5938199512Srdivacky DEnd = TU->decls_end(); 5939199512Srdivacky D != DEnd; ++D) 5940199512Srdivacky if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D)) 5941199512Srdivacky if (CategoryNames.insert(Category->getIdentifier())) 5942249423Sdim Results.AddResult(Result(Category, Results.getBasePriority(Category),0), 5943249423Sdim CurContext, 0, false); 5944199512Srdivacky Results.ExitScope(); 5945199512Srdivacky 5946212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5947224145Sdim CodeCompletionContext::CCC_ObjCCategoryName, 5948212904Sdim Results.data(),Results.size()); 5949199512Srdivacky} 5950199512Srdivacky 5951199512Srdivackyvoid Sema::CodeCompleteObjCImplementationCategory(Scope *S, 5952207619Srdivacky IdentifierInfo *ClassName, 5953207619Srdivacky SourceLocation ClassNameLoc) { 5954212904Sdim typedef CodeCompletionResult Result; 5955199512Srdivacky 5956199512Srdivacky // Find the corresponding interface. If we couldn't find the interface, the 5957199512Srdivacky // program itself is ill-formed. However, we'll try to be helpful still by 5958199512Srdivacky // providing the list of all of the categories we know about. 5959199512Srdivacky NamedDecl *CurClass 5960207619Srdivacky = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); 5961199512Srdivacky ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass); 5962199512Srdivacky if (!Class) 5963207619Srdivacky return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); 5964199512Srdivacky 5965218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5966234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5967224145Sdim CodeCompletionContext::CCC_ObjCCategoryName); 5968199512Srdivacky 5969199512Srdivacky // Add all of the categories that have have corresponding interface 5970199512Srdivacky // declarations in this class and any of its superclasses, except for 5971199512Srdivacky // already-implemented categories in the class itself. 5972199512Srdivacky llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; 5973199512Srdivacky Results.EnterNewScope(); 5974199512Srdivacky bool IgnoreImplemented = true; 5975199512Srdivacky while (Class) { 5976249423Sdim for (ObjCInterfaceDecl::visible_categories_iterator 5977249423Sdim Cat = Class->visible_categories_begin(), 5978249423Sdim CatEnd = Class->visible_categories_end(); 5979249423Sdim Cat != CatEnd; ++Cat) { 5980249423Sdim if ((!IgnoreImplemented || !Cat->getImplementation()) && 5981249423Sdim CategoryNames.insert(Cat->getIdentifier())) 5982249423Sdim Results.AddResult(Result(*Cat, Results.getBasePriority(*Cat), 0), 5983249423Sdim CurContext, 0, false); 5984249423Sdim } 5985199512Srdivacky 5986199512Srdivacky Class = Class->getSuperClass(); 5987199512Srdivacky IgnoreImplemented = false; 5988199512Srdivacky } 5989199512Srdivacky Results.ExitScope(); 5990199512Srdivacky 5991212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 5992224145Sdim CodeCompletionContext::CCC_ObjCCategoryName, 5993212904Sdim Results.data(),Results.size()); 5994199512Srdivacky} 5995199512Srdivacky 5996226633Sdimvoid Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { 5997218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 5998234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 5999218893Sdim CodeCompletionContext::CCC_Other); 6000199512Srdivacky 6001199512Srdivacky // Figure out where this @synthesize lives. 6002199512Srdivacky ObjCContainerDecl *Container 6003226633Sdim = dyn_cast_or_null<ObjCContainerDecl>(CurContext); 6004199512Srdivacky if (!Container || 6005199512Srdivacky (!isa<ObjCImplementationDecl>(Container) && 6006199512Srdivacky !isa<ObjCCategoryImplDecl>(Container))) 6007199512Srdivacky return; 6008199512Srdivacky 6009199512Srdivacky // Ignore any properties that have already been implemented. 6010239462Sdim Container = getContainerDef(Container); 6011239462Sdim for (DeclContext::decl_iterator D = Container->decls_begin(), 6012199512Srdivacky DEnd = Container->decls_end(); 6013199512Srdivacky D != DEnd; ++D) 6014199512Srdivacky if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D)) 6015199512Srdivacky Results.Ignore(PropertyImpl->getPropertyDecl()); 6016199512Srdivacky 6017199512Srdivacky // Add any properties that we find. 6018218893Sdim AddedPropertiesSet AddedProperties; 6019199512Srdivacky Results.EnterNewScope(); 6020199512Srdivacky if (ObjCImplementationDecl *ClassImpl 6021199512Srdivacky = dyn_cast<ObjCImplementationDecl>(Container)) 6022223017Sdim AddObjCProperties(ClassImpl->getClassInterface(), false, 6023223017Sdim /*AllowNullaryMethods=*/false, CurContext, 6024218893Sdim AddedProperties, Results); 6025199512Srdivacky else 6026199512Srdivacky AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(), 6027223017Sdim false, /*AllowNullaryMethods=*/false, CurContext, 6028223017Sdim AddedProperties, Results); 6029199512Srdivacky Results.ExitScope(); 6030199512Srdivacky 6031212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 6032212904Sdim CodeCompletionContext::CCC_Other, 6033212904Sdim Results.data(),Results.size()); 6034199512Srdivacky} 6035199512Srdivacky 6036199512Srdivackyvoid Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S, 6037226633Sdim IdentifierInfo *PropertyName) { 6038212904Sdim typedef CodeCompletionResult Result; 6039218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 6040234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 6041218893Sdim CodeCompletionContext::CCC_Other); 6042199512Srdivacky 6043199512Srdivacky // Figure out where this @synthesize lives. 6044199512Srdivacky ObjCContainerDecl *Container 6045226633Sdim = dyn_cast_or_null<ObjCContainerDecl>(CurContext); 6046199512Srdivacky if (!Container || 6047199512Srdivacky (!isa<ObjCImplementationDecl>(Container) && 6048199512Srdivacky !isa<ObjCCategoryImplDecl>(Container))) 6049199512Srdivacky return; 6050199512Srdivacky 6051199512Srdivacky // Figure out which interface we're looking into. 6052199512Srdivacky ObjCInterfaceDecl *Class = 0; 6053199512Srdivacky if (ObjCImplementationDecl *ClassImpl 6054199512Srdivacky = dyn_cast<ObjCImplementationDecl>(Container)) 6055199512Srdivacky Class = ClassImpl->getClassInterface(); 6056199512Srdivacky else 6057199512Srdivacky Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl() 6058199512Srdivacky ->getClassInterface(); 6059199512Srdivacky 6060221345Sdim // Determine the type of the property we're synthesizing. 6061221345Sdim QualType PropertyType = Context.getObjCIdType(); 6062221345Sdim if (Class) { 6063221345Sdim if (ObjCPropertyDecl *Property 6064221345Sdim = Class->FindPropertyDeclaration(PropertyName)) { 6065221345Sdim PropertyType 6066221345Sdim = Property->getType().getNonReferenceType().getUnqualifiedType(); 6067221345Sdim 6068221345Sdim // Give preference to ivars 6069221345Sdim Results.setPreferredType(PropertyType); 6070221345Sdim } 6071221345Sdim } 6072221345Sdim 6073199512Srdivacky // Add all of the instance variables in this class and its superclasses. 6074199512Srdivacky Results.EnterNewScope(); 6075221345Sdim bool SawSimilarlyNamedIvar = false; 6076221345Sdim std::string NameWithPrefix; 6077221345Sdim NameWithPrefix += '_'; 6078226633Sdim NameWithPrefix += PropertyName->getName(); 6079221345Sdim std::string NameWithSuffix = PropertyName->getName().str(); 6080221345Sdim NameWithSuffix += '_'; 6081199512Srdivacky for(; Class; Class = Class->getSuperClass()) { 6082221345Sdim for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; 6083221345Sdim Ivar = Ivar->getNextIvar()) { 6084249423Sdim Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), 0), 6085249423Sdim CurContext, 0, false); 6086221345Sdim 6087221345Sdim // Determine whether we've seen an ivar with a name similar to the 6088221345Sdim // property. 6089221345Sdim if ((PropertyName == Ivar->getIdentifier() || 6090221345Sdim NameWithPrefix == Ivar->getName() || 6091221345Sdim NameWithSuffix == Ivar->getName())) { 6092221345Sdim SawSimilarlyNamedIvar = true; 6093221345Sdim 6094221345Sdim // Reduce the priority of this result by one, to give it a slight 6095221345Sdim // advantage over other results whose names don't match so closely. 6096221345Sdim if (Results.size() && 6097221345Sdim Results.data()[Results.size() - 1].Kind 6098221345Sdim == CodeCompletionResult::RK_Declaration && 6099221345Sdim Results.data()[Results.size() - 1].Declaration == Ivar) 6100221345Sdim Results.data()[Results.size() - 1].Priority--; 6101221345Sdim } 6102221345Sdim } 6103199512Srdivacky } 6104221345Sdim 6105221345Sdim if (!SawSimilarlyNamedIvar) { 6106221345Sdim // Create ivar result _propName, that the user can use to synthesize 6107221345Sdim // an ivar of the appropriate type. 6108221345Sdim unsigned Priority = CCP_MemberDeclaration + 1; 6109221345Sdim typedef CodeCompletionResult Result; 6110221345Sdim CodeCompletionAllocator &Allocator = Results.getAllocator(); 6111234353Sdim CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(), 6112234353Sdim Priority,CXAvailability_Available); 6113221345Sdim 6114226633Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(*this); 6115221345Sdim Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context, 6116226633Sdim Policy, Allocator)); 6117221345Sdim Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); 6118221345Sdim Results.AddResult(Result(Builder.TakeString(), Priority, 6119221345Sdim CXCursor_ObjCIvarDecl)); 6120221345Sdim } 6121221345Sdim 6122199512Srdivacky Results.ExitScope(); 6123199512Srdivacky 6124212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 6125212904Sdim CodeCompletionContext::CCC_Other, 6126212904Sdim Results.data(),Results.size()); 6127199512Srdivacky} 6128207619Srdivacky 6129212904Sdim// Mapping from selectors to the methods that implement that selector, along 6130212904Sdim// with the "in original class" flag. 6131212904Sdimtypedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> > 6132212904Sdim KnownMethodsMap; 6133207619Srdivacky 6134207619Srdivacky/// \brief Find all of the methods that reside in the given container 6135207619Srdivacky/// (and its superclasses, protocols, etc.) that meet the given 6136207619Srdivacky/// criteria. Insert those methods into the map of known methods, 6137207619Srdivacky/// indexed by selector so they can be easily found. 6138207619Srdivackystatic void FindImplementableMethods(ASTContext &Context, 6139207619Srdivacky ObjCContainerDecl *Container, 6140207619Srdivacky bool WantInstanceMethods, 6141207619Srdivacky QualType ReturnType, 6142212904Sdim KnownMethodsMap &KnownMethods, 6143212904Sdim bool InOriginalClass = true) { 6144207619Srdivacky if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) { 6145239462Sdim // Make sure we have a definition; that's what we'll walk. 6146234353Sdim if (!IFace->hasDefinition()) 6147234353Sdim return; 6148239462Sdim 6149239462Sdim IFace = IFace->getDefinition(); 6150239462Sdim Container = IFace; 6151234353Sdim 6152207619Srdivacky const ObjCList<ObjCProtocolDecl> &Protocols 6153207619Srdivacky = IFace->getReferencedProtocols(); 6154207619Srdivacky for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 6155218893Sdim E = Protocols.end(); 6156207619Srdivacky I != E; ++I) 6157207619Srdivacky FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, 6158218893Sdim KnownMethods, InOriginalClass); 6159207619Srdivacky 6160218893Sdim // Add methods from any class extensions and categories. 6161249423Sdim for (ObjCInterfaceDecl::visible_categories_iterator 6162249423Sdim Cat = IFace->visible_categories_begin(), 6163249423Sdim CatEnd = IFace->visible_categories_end(); 6164249423Sdim Cat != CatEnd; ++Cat) { 6165249423Sdim FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType, 6166218893Sdim KnownMethods, false); 6167249423Sdim } 6168249423Sdim 6169218893Sdim // Visit the superclass. 6170218893Sdim if (IFace->getSuperClass()) 6171207619Srdivacky FindImplementableMethods(Context, IFace->getSuperClass(), 6172207619Srdivacky WantInstanceMethods, ReturnType, 6173218893Sdim KnownMethods, false); 6174207619Srdivacky } 6175207619Srdivacky 6176207619Srdivacky if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { 6177207619Srdivacky // Recurse into protocols. 6178207619Srdivacky const ObjCList<ObjCProtocolDecl> &Protocols 6179207619Srdivacky = Category->getReferencedProtocols(); 6180207619Srdivacky for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 6181218893Sdim E = Protocols.end(); 6182207619Srdivacky I != E; ++I) 6183207619Srdivacky FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, 6184218893Sdim KnownMethods, InOriginalClass); 6185218893Sdim 6186218893Sdim // If this category is the original class, jump to the interface. 6187218893Sdim if (InOriginalClass && Category->getClassInterface()) 6188218893Sdim FindImplementableMethods(Context, Category->getClassInterface(), 6189218893Sdim WantInstanceMethods, ReturnType, KnownMethods, 6190218893Sdim false); 6191207619Srdivacky } 6192207619Srdivacky 6193207619Srdivacky if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { 6194239462Sdim // Make sure we have a definition; that's what we'll walk. 6195239462Sdim if (!Protocol->hasDefinition()) 6196239462Sdim return; 6197239462Sdim Protocol = Protocol->getDefinition(); 6198239462Sdim Container = Protocol; 6199239462Sdim 6200239462Sdim // Recurse into protocols. 6201239462Sdim const ObjCList<ObjCProtocolDecl> &Protocols 6202239462Sdim = Protocol->getReferencedProtocols(); 6203239462Sdim for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 6204239462Sdim E = Protocols.end(); 6205239462Sdim I != E; ++I) 6206239462Sdim FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, 6207239462Sdim KnownMethods, false); 6208207619Srdivacky } 6209207619Srdivacky 6210207619Srdivacky // Add methods in this container. This operation occurs last because 6211207619Srdivacky // we want the methods from this container to override any methods 6212207619Srdivacky // we've previously seen with the same selector. 6213207619Srdivacky for (ObjCContainerDecl::method_iterator M = Container->meth_begin(), 6214207619Srdivacky MEnd = Container->meth_end(); 6215207619Srdivacky M != MEnd; ++M) { 6216239462Sdim if (M->isInstanceMethod() == WantInstanceMethods) { 6217207619Srdivacky if (!ReturnType.isNull() && 6218239462Sdim !Context.hasSameUnqualifiedType(ReturnType, M->getResultType())) 6219207619Srdivacky continue; 6220207619Srdivacky 6221239462Sdim KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass); 6222207619Srdivacky } 6223207619Srdivacky } 6224207619Srdivacky} 6225207619Srdivacky 6226218893Sdim/// \brief Add the parenthesized return or parameter type chunk to a code 6227218893Sdim/// completion string. 6228218893Sdimstatic void AddObjCPassingTypeChunk(QualType Type, 6229234353Sdim unsigned ObjCDeclQuals, 6230218893Sdim ASTContext &Context, 6231226633Sdim const PrintingPolicy &Policy, 6232218893Sdim CodeCompletionBuilder &Builder) { 6233218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6234234353Sdim std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals); 6235234353Sdim if (!Quals.empty()) 6236234353Sdim Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals)); 6237226633Sdim Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy, 6238218893Sdim Builder.getAllocator())); 6239218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6240218893Sdim} 6241218893Sdim 6242218893Sdim/// \brief Determine whether the given class is or inherits from a class by 6243218893Sdim/// the given name. 6244218893Sdimstatic bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, 6245226633Sdim StringRef Name) { 6246218893Sdim if (!Class) 6247218893Sdim return false; 6248218893Sdim 6249218893Sdim if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name) 6250218893Sdim return true; 6251218893Sdim 6252218893Sdim return InheritsFromClassNamed(Class->getSuperClass(), Name); 6253218893Sdim} 6254218893Sdim 6255218893Sdim/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and 6256218893Sdim/// Key-Value Observing (KVO). 6257218893Sdimstatic void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, 6258218893Sdim bool IsInstanceMethod, 6259218893Sdim QualType ReturnType, 6260218893Sdim ASTContext &Context, 6261223017Sdim VisitedSelectorSet &KnownSelectors, 6262218893Sdim ResultBuilder &Results) { 6263218893Sdim IdentifierInfo *PropName = Property->getIdentifier(); 6264218893Sdim if (!PropName || PropName->getLength() == 0) 6265218893Sdim return; 6266218893Sdim 6267226633Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema()); 6268226633Sdim 6269218893Sdim // Builder that will create each code completion. 6270218893Sdim typedef CodeCompletionResult Result; 6271218893Sdim CodeCompletionAllocator &Allocator = Results.getAllocator(); 6272234353Sdim CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); 6273218893Sdim 6274218893Sdim // The selector table. 6275218893Sdim SelectorTable &Selectors = Context.Selectors; 6276218893Sdim 6277218893Sdim // The property name, copied into the code completion allocation region 6278218893Sdim // on demand. 6279218893Sdim struct KeyHolder { 6280218893Sdim CodeCompletionAllocator &Allocator; 6281226633Sdim StringRef Key; 6282218893Sdim const char *CopiedKey; 6283218893Sdim 6284226633Sdim KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key) 6285218893Sdim : Allocator(Allocator), Key(Key), CopiedKey(0) { } 6286218893Sdim 6287218893Sdim operator const char *() { 6288218893Sdim if (CopiedKey) 6289218893Sdim return CopiedKey; 6290218893Sdim 6291218893Sdim return CopiedKey = Allocator.CopyString(Key); 6292218893Sdim } 6293218893Sdim } Key(Allocator, PropName->getName()); 6294218893Sdim 6295218893Sdim // The uppercased name of the property name. 6296218893Sdim std::string UpperKey = PropName->getName(); 6297218893Sdim if (!UpperKey.empty()) 6298249423Sdim UpperKey[0] = toUppercase(UpperKey[0]); 6299218893Sdim 6300218893Sdim bool ReturnTypeMatchesProperty = ReturnType.isNull() || 6301218893Sdim Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), 6302218893Sdim Property->getType()); 6303218893Sdim bool ReturnTypeMatchesVoid 6304218893Sdim = ReturnType.isNull() || ReturnType->isVoidType(); 6305218893Sdim 6306218893Sdim // Add the normal accessor -(type)key. 6307218893Sdim if (IsInstanceMethod && 6308223017Sdim KnownSelectors.insert(Selectors.getNullarySelector(PropName)) && 6309218893Sdim ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) { 6310218893Sdim if (ReturnType.isNull()) 6311234353Sdim AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, 6312234353Sdim Context, Policy, Builder); 6313218893Sdim 6314218893Sdim Builder.AddTypedTextChunk(Key); 6315218893Sdim Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 6316218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6317218893Sdim } 6318218893Sdim 6319218893Sdim // If we have an integral or boolean property (or the user has provided 6320218893Sdim // an integral or boolean return type), add the accessor -(type)isKey. 6321218893Sdim if (IsInstanceMethod && 6322218893Sdim ((!ReturnType.isNull() && 6323218893Sdim (ReturnType->isIntegerType() || ReturnType->isBooleanType())) || 6324218893Sdim (ReturnType.isNull() && 6325218893Sdim (Property->getType()->isIntegerType() || 6326218893Sdim Property->getType()->isBooleanType())))) { 6327226633Sdim std::string SelectorName = (Twine("is") + UpperKey).str(); 6328218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6329223017Sdim if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { 6330218893Sdim if (ReturnType.isNull()) { 6331218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6332218893Sdim Builder.AddTextChunk("BOOL"); 6333218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6334218893Sdim } 6335218893Sdim 6336218893Sdim Builder.AddTypedTextChunk( 6337218893Sdim Allocator.CopyString(SelectorId->getName())); 6338218893Sdim Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 6339218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6340218893Sdim } 6341218893Sdim } 6342218893Sdim 6343218893Sdim // Add the normal mutator. 6344218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid && 6345218893Sdim !Property->getSetterMethodDecl()) { 6346226633Sdim std::string SelectorName = (Twine("set") + UpperKey).str(); 6347218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6348223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6349218893Sdim if (ReturnType.isNull()) { 6350218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6351218893Sdim Builder.AddTextChunk("void"); 6352218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6353218893Sdim } 6354218893Sdim 6355218893Sdim Builder.AddTypedTextChunk( 6356218893Sdim Allocator.CopyString(SelectorId->getName())); 6357218893Sdim Builder.AddTypedTextChunk(":"); 6358234353Sdim AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, 6359234353Sdim Context, Policy, Builder); 6360218893Sdim Builder.AddTextChunk(Key); 6361218893Sdim Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 6362218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6363218893Sdim } 6364218893Sdim } 6365218893Sdim 6366218893Sdim // Indexed and unordered accessors 6367218893Sdim unsigned IndexedGetterPriority = CCP_CodePattern; 6368218893Sdim unsigned IndexedSetterPriority = CCP_CodePattern; 6369218893Sdim unsigned UnorderedGetterPriority = CCP_CodePattern; 6370218893Sdim unsigned UnorderedSetterPriority = CCP_CodePattern; 6371218893Sdim if (const ObjCObjectPointerType *ObjCPointer 6372218893Sdim = Property->getType()->getAs<ObjCObjectPointerType>()) { 6373218893Sdim if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) { 6374218893Sdim // If this interface type is not provably derived from a known 6375218893Sdim // collection, penalize the corresponding completions. 6376218893Sdim if (!InheritsFromClassNamed(IFace, "NSMutableArray")) { 6377218893Sdim IndexedSetterPriority += CCD_ProbablyNotObjCCollection; 6378218893Sdim if (!InheritsFromClassNamed(IFace, "NSArray")) 6379218893Sdim IndexedGetterPriority += CCD_ProbablyNotObjCCollection; 6380218893Sdim } 6381218893Sdim 6382218893Sdim if (!InheritsFromClassNamed(IFace, "NSMutableSet")) { 6383218893Sdim UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; 6384218893Sdim if (!InheritsFromClassNamed(IFace, "NSSet")) 6385218893Sdim UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; 6386218893Sdim } 6387218893Sdim } 6388218893Sdim } else { 6389218893Sdim IndexedGetterPriority += CCD_ProbablyNotObjCCollection; 6390218893Sdim IndexedSetterPriority += CCD_ProbablyNotObjCCollection; 6391218893Sdim UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; 6392218893Sdim UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; 6393218893Sdim } 6394218893Sdim 6395218893Sdim // Add -(NSUInteger)countOf<key> 6396218893Sdim if (IsInstanceMethod && 6397218893Sdim (ReturnType.isNull() || ReturnType->isIntegerType())) { 6398226633Sdim std::string SelectorName = (Twine("countOf") + UpperKey).str(); 6399218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6400223017Sdim if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { 6401218893Sdim if (ReturnType.isNull()) { 6402218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6403218893Sdim Builder.AddTextChunk("NSUInteger"); 6404218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6405218893Sdim } 6406218893Sdim 6407218893Sdim Builder.AddTypedTextChunk( 6408218893Sdim Allocator.CopyString(SelectorId->getName())); 6409218893Sdim Results.AddResult(Result(Builder.TakeString(), 6410218893Sdim std::min(IndexedGetterPriority, 6411218893Sdim UnorderedGetterPriority), 6412218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6413218893Sdim } 6414218893Sdim } 6415218893Sdim 6416218893Sdim // Indexed getters 6417218893Sdim // Add -(id)objectInKeyAtIndex:(NSUInteger)index 6418218893Sdim if (IsInstanceMethod && 6419218893Sdim (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { 6420218893Sdim std::string SelectorName 6421226633Sdim = (Twine("objectIn") + UpperKey + "AtIndex").str(); 6422218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6423223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6424218893Sdim if (ReturnType.isNull()) { 6425218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6426218893Sdim Builder.AddTextChunk("id"); 6427218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6428218893Sdim } 6429218893Sdim 6430218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6431218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6432218893Sdim Builder.AddTextChunk("NSUInteger"); 6433218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6434218893Sdim Builder.AddTextChunk("index"); 6435218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, 6436218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6437218893Sdim } 6438218893Sdim } 6439218893Sdim 6440218893Sdim // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes 6441218893Sdim if (IsInstanceMethod && 6442218893Sdim (ReturnType.isNull() || 6443218893Sdim (ReturnType->isObjCObjectPointerType() && 6444218893Sdim ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && 6445218893Sdim ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() 6446218893Sdim ->getName() == "NSArray"))) { 6447218893Sdim std::string SelectorName 6448226633Sdim = (Twine(Property->getName()) + "AtIndexes").str(); 6449218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6450223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6451218893Sdim if (ReturnType.isNull()) { 6452218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6453218893Sdim Builder.AddTextChunk("NSArray *"); 6454218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6455218893Sdim } 6456218893Sdim 6457218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6458218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6459218893Sdim Builder.AddTextChunk("NSIndexSet *"); 6460218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6461218893Sdim Builder.AddTextChunk("indexes"); 6462218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, 6463218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6464218893Sdim } 6465218893Sdim } 6466218893Sdim 6467218893Sdim // Add -(void)getKey:(type **)buffer range:(NSRange)inRange 6468218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6469226633Sdim std::string SelectorName = (Twine("get") + UpperKey).str(); 6470218893Sdim IdentifierInfo *SelectorIds[2] = { 6471218893Sdim &Context.Idents.get(SelectorName), 6472218893Sdim &Context.Idents.get("range") 6473218893Sdim }; 6474218893Sdim 6475223017Sdim if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { 6476218893Sdim if (ReturnType.isNull()) { 6477218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6478218893Sdim Builder.AddTextChunk("void"); 6479218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6480218893Sdim } 6481218893Sdim 6482218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6483218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6484218893Sdim Builder.AddPlaceholderChunk("object-type"); 6485218893Sdim Builder.AddTextChunk(" **"); 6486218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6487218893Sdim Builder.AddTextChunk("buffer"); 6488218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 6489218893Sdim Builder.AddTypedTextChunk("range:"); 6490218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6491218893Sdim Builder.AddTextChunk("NSRange"); 6492218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6493218893Sdim Builder.AddTextChunk("inRange"); 6494218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, 6495218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6496218893Sdim } 6497218893Sdim } 6498218893Sdim 6499218893Sdim // Mutable indexed accessors 6500218893Sdim 6501218893Sdim // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index 6502218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6503226633Sdim std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str(); 6504218893Sdim IdentifierInfo *SelectorIds[2] = { 6505218893Sdim &Context.Idents.get("insertObject"), 6506218893Sdim &Context.Idents.get(SelectorName) 6507218893Sdim }; 6508218893Sdim 6509223017Sdim if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { 6510218893Sdim if (ReturnType.isNull()) { 6511218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6512218893Sdim Builder.AddTextChunk("void"); 6513218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6514218893Sdim } 6515218893Sdim 6516218893Sdim Builder.AddTypedTextChunk("insertObject:"); 6517218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6518218893Sdim Builder.AddPlaceholderChunk("object-type"); 6519218893Sdim Builder.AddTextChunk(" *"); 6520218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6521218893Sdim Builder.AddTextChunk("object"); 6522218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 6523218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6524218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6525218893Sdim Builder.AddPlaceholderChunk("NSUInteger"); 6526218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6527218893Sdim Builder.AddTextChunk("index"); 6528218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 6529218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6530218893Sdim } 6531218893Sdim } 6532218893Sdim 6533218893Sdim // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes 6534218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6535226633Sdim std::string SelectorName = (Twine("insert") + UpperKey).str(); 6536218893Sdim IdentifierInfo *SelectorIds[2] = { 6537218893Sdim &Context.Idents.get(SelectorName), 6538218893Sdim &Context.Idents.get("atIndexes") 6539218893Sdim }; 6540218893Sdim 6541223017Sdim if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { 6542218893Sdim if (ReturnType.isNull()) { 6543218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6544218893Sdim Builder.AddTextChunk("void"); 6545218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6546218893Sdim } 6547218893Sdim 6548218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6549218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6550218893Sdim Builder.AddTextChunk("NSArray *"); 6551218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6552218893Sdim Builder.AddTextChunk("array"); 6553218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 6554218893Sdim Builder.AddTypedTextChunk("atIndexes:"); 6555218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6556218893Sdim Builder.AddPlaceholderChunk("NSIndexSet *"); 6557218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6558218893Sdim Builder.AddTextChunk("indexes"); 6559218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 6560218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6561218893Sdim } 6562218893Sdim } 6563218893Sdim 6564218893Sdim // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index 6565218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6566218893Sdim std::string SelectorName 6567226633Sdim = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); 6568218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6569223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6570218893Sdim if (ReturnType.isNull()) { 6571218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6572218893Sdim Builder.AddTextChunk("void"); 6573218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6574218893Sdim } 6575218893Sdim 6576218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6577218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6578218893Sdim Builder.AddTextChunk("NSUInteger"); 6579218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6580218893Sdim Builder.AddTextChunk("index"); 6581218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 6582218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6583218893Sdim } 6584218893Sdim } 6585218893Sdim 6586218893Sdim // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes 6587218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6588218893Sdim std::string SelectorName 6589226633Sdim = (Twine("remove") + UpperKey + "AtIndexes").str(); 6590218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6591223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6592218893Sdim if (ReturnType.isNull()) { 6593218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6594218893Sdim Builder.AddTextChunk("void"); 6595218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6596218893Sdim } 6597218893Sdim 6598218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6599218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6600218893Sdim Builder.AddTextChunk("NSIndexSet *"); 6601218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6602218893Sdim Builder.AddTextChunk("indexes"); 6603218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 6604218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6605218893Sdim } 6606218893Sdim } 6607218893Sdim 6608218893Sdim // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object 6609218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6610218893Sdim std::string SelectorName 6611226633Sdim = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str(); 6612218893Sdim IdentifierInfo *SelectorIds[2] = { 6613218893Sdim &Context.Idents.get(SelectorName), 6614218893Sdim &Context.Idents.get("withObject") 6615218893Sdim }; 6616218893Sdim 6617223017Sdim if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { 6618218893Sdim if (ReturnType.isNull()) { 6619218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6620218893Sdim Builder.AddTextChunk("void"); 6621218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6622218893Sdim } 6623218893Sdim 6624218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6625218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6626218893Sdim Builder.AddPlaceholderChunk("NSUInteger"); 6627218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6628218893Sdim Builder.AddTextChunk("index"); 6629218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 6630218893Sdim Builder.AddTypedTextChunk("withObject:"); 6631218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6632218893Sdim Builder.AddTextChunk("id"); 6633218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6634218893Sdim Builder.AddTextChunk("object"); 6635218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 6636218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6637218893Sdim } 6638218893Sdim } 6639218893Sdim 6640218893Sdim // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array 6641218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6642218893Sdim std::string SelectorName1 6643226633Sdim = (Twine("replace") + UpperKey + "AtIndexes").str(); 6644226633Sdim std::string SelectorName2 = (Twine("with") + UpperKey).str(); 6645218893Sdim IdentifierInfo *SelectorIds[2] = { 6646218893Sdim &Context.Idents.get(SelectorName1), 6647218893Sdim &Context.Idents.get(SelectorName2) 6648218893Sdim }; 6649218893Sdim 6650223017Sdim if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) { 6651218893Sdim if (ReturnType.isNull()) { 6652218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6653218893Sdim Builder.AddTextChunk("void"); 6654218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6655218893Sdim } 6656218893Sdim 6657218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":")); 6658218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6659218893Sdim Builder.AddPlaceholderChunk("NSIndexSet *"); 6660218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6661218893Sdim Builder.AddTextChunk("indexes"); 6662218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 6663218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":")); 6664218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6665218893Sdim Builder.AddTextChunk("NSArray *"); 6666218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6667218893Sdim Builder.AddTextChunk("array"); 6668218893Sdim Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, 6669218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6670218893Sdim } 6671218893Sdim } 6672218893Sdim 6673218893Sdim // Unordered getters 6674218893Sdim // - (NSEnumerator *)enumeratorOfKey 6675218893Sdim if (IsInstanceMethod && 6676218893Sdim (ReturnType.isNull() || 6677218893Sdim (ReturnType->isObjCObjectPointerType() && 6678218893Sdim ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && 6679218893Sdim ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() 6680218893Sdim ->getName() == "NSEnumerator"))) { 6681226633Sdim std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str(); 6682218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6683223017Sdim if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { 6684218893Sdim if (ReturnType.isNull()) { 6685218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6686218893Sdim Builder.AddTextChunk("NSEnumerator *"); 6687218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6688218893Sdim } 6689218893Sdim 6690218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); 6691218893Sdim Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, 6692218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6693218893Sdim } 6694218893Sdim } 6695218893Sdim 6696218893Sdim // - (type *)memberOfKey:(type *)object 6697218893Sdim if (IsInstanceMethod && 6698218893Sdim (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { 6699226633Sdim std::string SelectorName = (Twine("memberOf") + UpperKey).str(); 6700218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6701223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6702218893Sdim if (ReturnType.isNull()) { 6703218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6704218893Sdim Builder.AddPlaceholderChunk("object-type"); 6705218893Sdim Builder.AddTextChunk(" *"); 6706218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6707218893Sdim } 6708218893Sdim 6709218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6710218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6711218893Sdim if (ReturnType.isNull()) { 6712218893Sdim Builder.AddPlaceholderChunk("object-type"); 6713218893Sdim Builder.AddTextChunk(" *"); 6714218893Sdim } else { 6715218893Sdim Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context, 6716226633Sdim Policy, 6717218893Sdim Builder.getAllocator())); 6718218893Sdim } 6719218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6720218893Sdim Builder.AddTextChunk("object"); 6721218893Sdim Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, 6722218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6723218893Sdim } 6724218893Sdim } 6725218893Sdim 6726218893Sdim // Mutable unordered accessors 6727218893Sdim // - (void)addKeyObject:(type *)object 6728218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6729218893Sdim std::string SelectorName 6730226633Sdim = (Twine("add") + UpperKey + Twine("Object")).str(); 6731218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6732223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6733218893Sdim if (ReturnType.isNull()) { 6734218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6735218893Sdim Builder.AddTextChunk("void"); 6736218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6737218893Sdim } 6738218893Sdim 6739218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6740218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6741218893Sdim Builder.AddPlaceholderChunk("object-type"); 6742218893Sdim Builder.AddTextChunk(" *"); 6743218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6744218893Sdim Builder.AddTextChunk("object"); 6745218893Sdim Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 6746218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6747218893Sdim } 6748218893Sdim } 6749218893Sdim 6750218893Sdim // - (void)addKey:(NSSet *)objects 6751218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6752226633Sdim std::string SelectorName = (Twine("add") + UpperKey).str(); 6753218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6754223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6755218893Sdim if (ReturnType.isNull()) { 6756218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6757218893Sdim Builder.AddTextChunk("void"); 6758218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6759218893Sdim } 6760218893Sdim 6761218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6762218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6763218893Sdim Builder.AddTextChunk("NSSet *"); 6764218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6765218893Sdim Builder.AddTextChunk("objects"); 6766218893Sdim Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 6767218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6768218893Sdim } 6769218893Sdim } 6770218893Sdim 6771218893Sdim // - (void)removeKeyObject:(type *)object 6772218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6773218893Sdim std::string SelectorName 6774226633Sdim = (Twine("remove") + UpperKey + Twine("Object")).str(); 6775218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6776223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6777218893Sdim if (ReturnType.isNull()) { 6778218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6779218893Sdim Builder.AddTextChunk("void"); 6780218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6781218893Sdim } 6782218893Sdim 6783218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6784218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6785218893Sdim Builder.AddPlaceholderChunk("object-type"); 6786218893Sdim Builder.AddTextChunk(" *"); 6787218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6788218893Sdim Builder.AddTextChunk("object"); 6789218893Sdim Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 6790218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6791218893Sdim } 6792218893Sdim } 6793218893Sdim 6794218893Sdim // - (void)removeKey:(NSSet *)objects 6795218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6796226633Sdim std::string SelectorName = (Twine("remove") + UpperKey).str(); 6797218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6798223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6799218893Sdim if (ReturnType.isNull()) { 6800218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6801218893Sdim Builder.AddTextChunk("void"); 6802218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6803218893Sdim } 6804218893Sdim 6805218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6806218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6807218893Sdim Builder.AddTextChunk("NSSet *"); 6808218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6809218893Sdim Builder.AddTextChunk("objects"); 6810218893Sdim Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 6811218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6812218893Sdim } 6813218893Sdim } 6814218893Sdim 6815218893Sdim // - (void)intersectKey:(NSSet *)objects 6816218893Sdim if (IsInstanceMethod && ReturnTypeMatchesVoid) { 6817226633Sdim std::string SelectorName = (Twine("intersect") + UpperKey).str(); 6818218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6819223017Sdim if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) { 6820218893Sdim if (ReturnType.isNull()) { 6821218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6822218893Sdim Builder.AddTextChunk("void"); 6823218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6824218893Sdim } 6825218893Sdim 6826218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); 6827218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6828218893Sdim Builder.AddTextChunk("NSSet *"); 6829218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6830218893Sdim Builder.AddTextChunk("objects"); 6831218893Sdim Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, 6832218893Sdim CXCursor_ObjCInstanceMethodDecl)); 6833218893Sdim } 6834218893Sdim } 6835218893Sdim 6836218893Sdim // Key-Value Observing 6837218893Sdim // + (NSSet *)keyPathsForValuesAffectingKey 6838218893Sdim if (!IsInstanceMethod && 6839218893Sdim (ReturnType.isNull() || 6840218893Sdim (ReturnType->isObjCObjectPointerType() && 6841218893Sdim ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && 6842218893Sdim ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() 6843218893Sdim ->getName() == "NSSet"))) { 6844218893Sdim std::string SelectorName 6845226633Sdim = (Twine("keyPathsForValuesAffecting") + UpperKey).str(); 6846218893Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6847223017Sdim if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { 6848218893Sdim if (ReturnType.isNull()) { 6849218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6850218893Sdim Builder.AddTextChunk("NSSet *"); 6851218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6852218893Sdim } 6853218893Sdim 6854218893Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); 6855218893Sdim Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 6856223017Sdim CXCursor_ObjCClassMethodDecl)); 6857218893Sdim } 6858218893Sdim } 6859223017Sdim 6860223017Sdim // + (BOOL)automaticallyNotifiesObserversForKey 6861223017Sdim if (!IsInstanceMethod && 6862223017Sdim (ReturnType.isNull() || 6863223017Sdim ReturnType->isIntegerType() || 6864223017Sdim ReturnType->isBooleanType())) { 6865223017Sdim std::string SelectorName 6866226633Sdim = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); 6867223017Sdim IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); 6868223017Sdim if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) { 6869223017Sdim if (ReturnType.isNull()) { 6870223017Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 6871223017Sdim Builder.AddTextChunk("BOOL"); 6872223017Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 6873223017Sdim } 6874223017Sdim 6875223017Sdim Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); 6876223017Sdim Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, 6877223017Sdim CXCursor_ObjCClassMethodDecl)); 6878223017Sdim } 6879223017Sdim } 6880218893Sdim} 6881218893Sdim 6882207619Srdivackyvoid Sema::CodeCompleteObjCMethodDecl(Scope *S, 6883207619Srdivacky bool IsInstanceMethod, 6884226633Sdim ParsedType ReturnTy) { 6885207619Srdivacky // Determine the return type of the method we're declaring, if 6886207619Srdivacky // provided. 6887207619Srdivacky QualType ReturnType = GetTypeFromParser(ReturnTy); 6888226633Sdim Decl *IDecl = 0; 6889226633Sdim if (CurContext->isObjCContainer()) { 6890226633Sdim ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); 6891226633Sdim IDecl = cast<Decl>(OCD); 6892226633Sdim } 6893218893Sdim // Determine where we should start searching for methods. 6894218893Sdim ObjCContainerDecl *SearchDecl = 0; 6895207619Srdivacky bool IsInImplementation = false; 6896212904Sdim if (Decl *D = IDecl) { 6897207619Srdivacky if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) { 6898207619Srdivacky SearchDecl = Impl->getClassInterface(); 6899207619Srdivacky IsInImplementation = true; 6900207619Srdivacky } else if (ObjCCategoryImplDecl *CatImpl 6901218893Sdim = dyn_cast<ObjCCategoryImplDecl>(D)) { 6902207619Srdivacky SearchDecl = CatImpl->getCategoryDecl(); 6903207619Srdivacky IsInImplementation = true; 6904218893Sdim } else 6905207619Srdivacky SearchDecl = dyn_cast<ObjCContainerDecl>(D); 6906207619Srdivacky } 6907207619Srdivacky 6908207619Srdivacky if (!SearchDecl && S) { 6909218893Sdim if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity())) 6910207619Srdivacky SearchDecl = dyn_cast<ObjCContainerDecl>(DC); 6911207619Srdivacky } 6912207619Srdivacky 6913218893Sdim if (!SearchDecl) { 6914212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 6915212904Sdim CodeCompletionContext::CCC_Other, 6916212904Sdim 0, 0); 6917207619Srdivacky return; 6918207619Srdivacky } 6919207619Srdivacky 6920207619Srdivacky // Find all of the methods that we could declare/implement here. 6921207619Srdivacky KnownMethodsMap KnownMethods; 6922207619Srdivacky FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, 6923218893Sdim ReturnType, KnownMethods); 6924207619Srdivacky 6925207619Srdivacky // Add declarations or definitions for each of the known methods. 6926212904Sdim typedef CodeCompletionResult Result; 6927218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 6928234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 6929218893Sdim CodeCompletionContext::CCC_Other); 6930207619Srdivacky Results.EnterNewScope(); 6931226633Sdim PrintingPolicy Policy = getCompletionPrintingPolicy(*this); 6932207619Srdivacky for (KnownMethodsMap::iterator M = KnownMethods.begin(), 6933207619Srdivacky MEnd = KnownMethods.end(); 6934207619Srdivacky M != MEnd; ++M) { 6935212904Sdim ObjCMethodDecl *Method = M->second.first; 6936234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 6937234353Sdim Results.getCodeCompletionTUInfo()); 6938207619Srdivacky 6939207619Srdivacky // If the result type was not already provided, add it to the 6940207619Srdivacky // pattern as (type). 6941218893Sdim if (ReturnType.isNull()) 6942234353Sdim AddObjCPassingTypeChunk(Method->getResultType(), 6943234353Sdim Method->getObjCDeclQualifier(), 6944234353Sdim Context, Policy, 6945234353Sdim Builder); 6946207619Srdivacky 6947207619Srdivacky Selector Sel = Method->getSelector(); 6948207619Srdivacky 6949207619Srdivacky // Add the first part of the selector to the pattern. 6950218893Sdim Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( 6951218893Sdim Sel.getNameForSlot(0))); 6952207619Srdivacky 6953207619Srdivacky // Add parameters to the pattern. 6954207619Srdivacky unsigned I = 0; 6955207619Srdivacky for (ObjCMethodDecl::param_iterator P = Method->param_begin(), 6956207619Srdivacky PEnd = Method->param_end(); 6957207619Srdivacky P != PEnd; (void)++P, ++I) { 6958207619Srdivacky // Add the part of the selector name. 6959207619Srdivacky if (I == 0) 6960218893Sdim Builder.AddTypedTextChunk(":"); 6961207619Srdivacky else if (I < Sel.getNumArgs()) { 6962218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 6963218893Sdim Builder.AddTypedTextChunk( 6964218893Sdim Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); 6965207619Srdivacky } else 6966207619Srdivacky break; 6967207619Srdivacky 6968207619Srdivacky // Add the parameter type. 6969234353Sdim AddObjCPassingTypeChunk((*P)->getOriginalType(), 6970234353Sdim (*P)->getObjCDeclQualifier(), 6971234353Sdim Context, Policy, 6972226633Sdim Builder); 6973207619Srdivacky 6974207619Srdivacky if (IdentifierInfo *Id = (*P)->getIdentifier()) 6975218893Sdim Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName())); 6976207619Srdivacky } 6977207619Srdivacky 6978207619Srdivacky if (Method->isVariadic()) { 6979207619Srdivacky if (Method->param_size() > 0) 6980218893Sdim Builder.AddChunk(CodeCompletionString::CK_Comma); 6981218893Sdim Builder.AddTextChunk("..."); 6982212904Sdim } 6983207619Srdivacky 6984210299Sed if (IsInImplementation && Results.includeCodePatterns()) { 6985207619Srdivacky // We will be defining the method here, so add a compound statement. 6986218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 6987218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftBrace); 6988218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 6989207619Srdivacky if (!Method->getResultType()->isVoidType()) { 6990207619Srdivacky // If the result type is not void, add a return clause. 6991218893Sdim Builder.AddTextChunk("return"); 6992218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 6993218893Sdim Builder.AddPlaceholderChunk("expression"); 6994218893Sdim Builder.AddChunk(CodeCompletionString::CK_SemiColon); 6995207619Srdivacky } else 6996218893Sdim Builder.AddPlaceholderChunk("statements"); 6997207619Srdivacky 6998218893Sdim Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); 6999218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightBrace); 7000207619Srdivacky } 7001207619Srdivacky 7002212904Sdim unsigned Priority = CCP_CodePattern; 7003212904Sdim if (!M->second.second) 7004212904Sdim Priority += CCD_InBaseClass; 7005212904Sdim 7006234353Sdim Results.AddResult(Result(Builder.TakeString(), Method, Priority)); 7007207619Srdivacky } 7008207619Srdivacky 7009218893Sdim // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of 7010218893Sdim // the properties in this class and its categories. 7011234353Sdim if (Context.getLangOpts().ObjC2) { 7012226633Sdim SmallVector<ObjCContainerDecl *, 4> Containers; 7013218893Sdim Containers.push_back(SearchDecl); 7014218893Sdim 7015223017Sdim VisitedSelectorSet KnownSelectors; 7016223017Sdim for (KnownMethodsMap::iterator M = KnownMethods.begin(), 7017223017Sdim MEnd = KnownMethods.end(); 7018223017Sdim M != MEnd; ++M) 7019223017Sdim KnownSelectors.insert(M->first); 7020223017Sdim 7021223017Sdim 7022218893Sdim ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl); 7023218893Sdim if (!IFace) 7024218893Sdim if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl)) 7025218893Sdim IFace = Category->getClassInterface(); 7026218893Sdim 7027218893Sdim if (IFace) { 7028249423Sdim for (ObjCInterfaceDecl::visible_categories_iterator 7029249423Sdim Cat = IFace->visible_categories_begin(), 7030249423Sdim CatEnd = IFace->visible_categories_end(); 7031249423Sdim Cat != CatEnd; ++Cat) { 7032249423Sdim Containers.push_back(*Cat); 7033249423Sdim } 7034218893Sdim } 7035218893Sdim 7036218893Sdim for (unsigned I = 0, N = Containers.size(); I != N; ++I) { 7037218893Sdim for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(), 7038218893Sdim PEnd = Containers[I]->prop_end(); 7039218893Sdim P != PEnd; ++P) { 7040218893Sdim AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context, 7041223017Sdim KnownSelectors, Results); 7042218893Sdim } 7043218893Sdim } 7044218893Sdim } 7045218893Sdim 7046207619Srdivacky Results.ExitScope(); 7047207619Srdivacky 7048212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 7049212904Sdim CodeCompletionContext::CCC_Other, 7050212904Sdim Results.data(),Results.size()); 7051207619Srdivacky} 7052210299Sed 7053210299Sedvoid Sema::CodeCompleteObjCMethodDeclSelector(Scope *S, 7054210299Sed bool IsInstanceMethod, 7055210299Sed bool AtParameterName, 7056212904Sdim ParsedType ReturnTy, 7057210299Sed IdentifierInfo **SelIdents, 7058210299Sed unsigned NumSelIdents) { 7059210299Sed // If we have an external source, load the entire class method 7060212904Sdim // pool from the AST file. 7061210299Sed if (ExternalSource) { 7062210299Sed for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); 7063210299Sed I != N; ++I) { 7064210299Sed Selector Sel = ExternalSource->GetExternalSelector(I); 7065212904Sdim if (Sel.isNull() || MethodPool.count(Sel)) 7066210299Sed continue; 7067212904Sdim 7068212904Sdim ReadMethodPool(Sel); 7069210299Sed } 7070210299Sed } 7071210299Sed 7072210299Sed // Build the set of methods we can see. 7073212904Sdim typedef CodeCompletionResult Result; 7074218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 7075234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 7076218893Sdim CodeCompletionContext::CCC_Other); 7077210299Sed 7078210299Sed if (ReturnTy) 7079210299Sed Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); 7080212904Sdim 7081210299Sed Results.EnterNewScope(); 7082212904Sdim for (GlobalMethodPool::iterator M = MethodPool.begin(), 7083212904Sdim MEnd = MethodPool.end(); 7084212904Sdim M != MEnd; ++M) { 7085212904Sdim for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first : 7086212904Sdim &M->second.second; 7087212904Sdim MethList && MethList->Method; 7088251662Sdim MethList = MethList->getNext()) { 7089210299Sed if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents, 7090210299Sed NumSelIdents)) 7091210299Sed continue; 7092210299Sed 7093210299Sed if (AtParameterName) { 7094210299Sed // Suggest parameter names we've seen before. 7095210299Sed if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) { 7096210299Sed ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1]; 7097210299Sed if (Param->getIdentifier()) { 7098234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 7099234353Sdim Results.getCodeCompletionTUInfo()); 7100218893Sdim Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( 7101218893Sdim Param->getIdentifier()->getName())); 7102218893Sdim Results.AddResult(Builder.TakeString()); 7103210299Sed } 7104210299Sed } 7105210299Sed 7106210299Sed continue; 7107210299Sed } 7108210299Sed 7109249423Sdim Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0); 7110210299Sed R.StartParameter = NumSelIdents; 7111210299Sed R.AllParametersAreInformative = false; 7112210299Sed R.DeclaringEntity = true; 7113210299Sed Results.MaybeAddResult(R, CurContext); 7114210299Sed } 7115210299Sed } 7116210299Sed 7117210299Sed Results.ExitScope(); 7118212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 7119212904Sdim CodeCompletionContext::CCC_Other, 7120212904Sdim Results.data(),Results.size()); 7121210299Sed} 7122212904Sdim 7123212904Sdimvoid Sema::CodeCompletePreprocessorDirective(bool InConditional) { 7124218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 7125234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 7126218893Sdim CodeCompletionContext::CCC_PreprocessorDirective); 7127212904Sdim Results.EnterNewScope(); 7128212904Sdim 7129212904Sdim // #if <condition> 7130234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 7131234353Sdim Results.getCodeCompletionTUInfo()); 7132218893Sdim Builder.AddTypedTextChunk("if"); 7133218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7134218893Sdim Builder.AddPlaceholderChunk("condition"); 7135218893Sdim Results.AddResult(Builder.TakeString()); 7136212904Sdim 7137212904Sdim // #ifdef <macro> 7138218893Sdim Builder.AddTypedTextChunk("ifdef"); 7139218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7140218893Sdim Builder.AddPlaceholderChunk("macro"); 7141218893Sdim Results.AddResult(Builder.TakeString()); 7142218893Sdim 7143212904Sdim // #ifndef <macro> 7144218893Sdim Builder.AddTypedTextChunk("ifndef"); 7145218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7146218893Sdim Builder.AddPlaceholderChunk("macro"); 7147218893Sdim Results.AddResult(Builder.TakeString()); 7148212904Sdim 7149212904Sdim if (InConditional) { 7150212904Sdim // #elif <condition> 7151218893Sdim Builder.AddTypedTextChunk("elif"); 7152218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7153218893Sdim Builder.AddPlaceholderChunk("condition"); 7154218893Sdim Results.AddResult(Builder.TakeString()); 7155212904Sdim 7156212904Sdim // #else 7157218893Sdim Builder.AddTypedTextChunk("else"); 7158218893Sdim Results.AddResult(Builder.TakeString()); 7159212904Sdim 7160212904Sdim // #endif 7161218893Sdim Builder.AddTypedTextChunk("endif"); 7162218893Sdim Results.AddResult(Builder.TakeString()); 7163212904Sdim } 7164212904Sdim 7165212904Sdim // #include "header" 7166218893Sdim Builder.AddTypedTextChunk("include"); 7167218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7168218893Sdim Builder.AddTextChunk("\""); 7169218893Sdim Builder.AddPlaceholderChunk("header"); 7170218893Sdim Builder.AddTextChunk("\""); 7171218893Sdim Results.AddResult(Builder.TakeString()); 7172212904Sdim 7173212904Sdim // #include <header> 7174218893Sdim Builder.AddTypedTextChunk("include"); 7175218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7176218893Sdim Builder.AddTextChunk("<"); 7177218893Sdim Builder.AddPlaceholderChunk("header"); 7178218893Sdim Builder.AddTextChunk(">"); 7179218893Sdim Results.AddResult(Builder.TakeString()); 7180212904Sdim 7181212904Sdim // #define <macro> 7182218893Sdim Builder.AddTypedTextChunk("define"); 7183218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7184218893Sdim Builder.AddPlaceholderChunk("macro"); 7185218893Sdim Results.AddResult(Builder.TakeString()); 7186212904Sdim 7187212904Sdim // #define <macro>(<args>) 7188218893Sdim Builder.AddTypedTextChunk("define"); 7189218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7190218893Sdim Builder.AddPlaceholderChunk("macro"); 7191218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 7192218893Sdim Builder.AddPlaceholderChunk("args"); 7193218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 7194218893Sdim Results.AddResult(Builder.TakeString()); 7195212904Sdim 7196212904Sdim // #undef <macro> 7197218893Sdim Builder.AddTypedTextChunk("undef"); 7198218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7199218893Sdim Builder.AddPlaceholderChunk("macro"); 7200218893Sdim Results.AddResult(Builder.TakeString()); 7201212904Sdim 7202212904Sdim // #line <number> 7203218893Sdim Builder.AddTypedTextChunk("line"); 7204218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7205218893Sdim Builder.AddPlaceholderChunk("number"); 7206218893Sdim Results.AddResult(Builder.TakeString()); 7207212904Sdim 7208212904Sdim // #line <number> "filename" 7209218893Sdim Builder.AddTypedTextChunk("line"); 7210218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7211218893Sdim Builder.AddPlaceholderChunk("number"); 7212218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7213218893Sdim Builder.AddTextChunk("\""); 7214218893Sdim Builder.AddPlaceholderChunk("filename"); 7215218893Sdim Builder.AddTextChunk("\""); 7216218893Sdim Results.AddResult(Builder.TakeString()); 7217212904Sdim 7218212904Sdim // #error <message> 7219218893Sdim Builder.AddTypedTextChunk("error"); 7220218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7221218893Sdim Builder.AddPlaceholderChunk("message"); 7222218893Sdim Results.AddResult(Builder.TakeString()); 7223212904Sdim 7224212904Sdim // #pragma <arguments> 7225218893Sdim Builder.AddTypedTextChunk("pragma"); 7226218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7227218893Sdim Builder.AddPlaceholderChunk("arguments"); 7228218893Sdim Results.AddResult(Builder.TakeString()); 7229212904Sdim 7230234353Sdim if (getLangOpts().ObjC1) { 7231212904Sdim // #import "header" 7232218893Sdim Builder.AddTypedTextChunk("import"); 7233218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7234218893Sdim Builder.AddTextChunk("\""); 7235218893Sdim Builder.AddPlaceholderChunk("header"); 7236218893Sdim Builder.AddTextChunk("\""); 7237218893Sdim Results.AddResult(Builder.TakeString()); 7238212904Sdim 7239212904Sdim // #import <header> 7240218893Sdim Builder.AddTypedTextChunk("import"); 7241218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7242218893Sdim Builder.AddTextChunk("<"); 7243218893Sdim Builder.AddPlaceholderChunk("header"); 7244218893Sdim Builder.AddTextChunk(">"); 7245218893Sdim Results.AddResult(Builder.TakeString()); 7246212904Sdim } 7247212904Sdim 7248212904Sdim // #include_next "header" 7249218893Sdim Builder.AddTypedTextChunk("include_next"); 7250218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7251218893Sdim Builder.AddTextChunk("\""); 7252218893Sdim Builder.AddPlaceholderChunk("header"); 7253218893Sdim Builder.AddTextChunk("\""); 7254218893Sdim Results.AddResult(Builder.TakeString()); 7255212904Sdim 7256212904Sdim // #include_next <header> 7257218893Sdim Builder.AddTypedTextChunk("include_next"); 7258218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7259218893Sdim Builder.AddTextChunk("<"); 7260218893Sdim Builder.AddPlaceholderChunk("header"); 7261218893Sdim Builder.AddTextChunk(">"); 7262218893Sdim Results.AddResult(Builder.TakeString()); 7263212904Sdim 7264212904Sdim // #warning <message> 7265218893Sdim Builder.AddTypedTextChunk("warning"); 7266218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7267218893Sdim Builder.AddPlaceholderChunk("message"); 7268218893Sdim Results.AddResult(Builder.TakeString()); 7269212904Sdim 7270212904Sdim // Note: #ident and #sccs are such crazy anachronisms that we don't provide 7271212904Sdim // completions for them. And __include_macros is a Clang-internal extension 7272212904Sdim // that we don't want to encourage anyone to use. 7273212904Sdim 7274212904Sdim // FIXME: we don't support #assert or #unassert, so don't suggest them. 7275212904Sdim Results.ExitScope(); 7276212904Sdim 7277212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 7278212904Sdim CodeCompletionContext::CCC_PreprocessorDirective, 7279212904Sdim Results.data(), Results.size()); 7280212904Sdim} 7281212904Sdim 7282212904Sdimvoid Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { 7283212904Sdim CodeCompleteOrdinaryName(S, 7284212904Sdim S->getFnParent()? Sema::PCC_RecoveryInFunction 7285212904Sdim : Sema::PCC_Namespace); 7286212904Sdim} 7287212904Sdim 7288212904Sdimvoid Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { 7289218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 7290234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 7291218893Sdim IsDefinition? CodeCompletionContext::CCC_MacroName 7292218893Sdim : CodeCompletionContext::CCC_MacroNameUse); 7293212904Sdim if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { 7294212904Sdim // Add just the names of macros, not their arguments. 7295234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 7296234353Sdim Results.getCodeCompletionTUInfo()); 7297212904Sdim Results.EnterNewScope(); 7298212904Sdim for (Preprocessor::macro_iterator M = PP.macro_begin(), 7299212904Sdim MEnd = PP.macro_end(); 7300212904Sdim M != MEnd; ++M) { 7301218893Sdim Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( 7302218893Sdim M->first->getName())); 7303243830Sdim Results.AddResult(CodeCompletionResult(Builder.TakeString(), 7304243830Sdim CCP_CodePattern, 7305243830Sdim CXCursor_MacroDefinition)); 7306212904Sdim } 7307212904Sdim Results.ExitScope(); 7308212904Sdim } else if (IsDefinition) { 7309212904Sdim // FIXME: Can we detect when the user just wrote an include guard above? 7310212904Sdim } 7311212904Sdim 7312218893Sdim HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), 7313212904Sdim Results.data(), Results.size()); 7314212904Sdim} 7315212904Sdim 7316212904Sdimvoid Sema::CodeCompletePreprocessorExpression() { 7317218893Sdim ResultBuilder Results(*this, CodeCompleter->getAllocator(), 7318234353Sdim CodeCompleter->getCodeCompletionTUInfo(), 7319218893Sdim CodeCompletionContext::CCC_PreprocessorExpression); 7320212904Sdim 7321212904Sdim if (!CodeCompleter || CodeCompleter->includeMacros()) 7322243830Sdim AddMacroResults(PP, Results, true); 7323212904Sdim 7324212904Sdim // defined (<macro>) 7325212904Sdim Results.EnterNewScope(); 7326234353Sdim CodeCompletionBuilder Builder(Results.getAllocator(), 7327234353Sdim Results.getCodeCompletionTUInfo()); 7328218893Sdim Builder.AddTypedTextChunk("defined"); 7329218893Sdim Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); 7330218893Sdim Builder.AddChunk(CodeCompletionString::CK_LeftParen); 7331218893Sdim Builder.AddPlaceholderChunk("macro"); 7332218893Sdim Builder.AddChunk(CodeCompletionString::CK_RightParen); 7333218893Sdim Results.AddResult(Builder.TakeString()); 7334212904Sdim Results.ExitScope(); 7335212904Sdim 7336212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 7337212904Sdim CodeCompletionContext::CCC_PreprocessorExpression, 7338212904Sdim Results.data(), Results.size()); 7339212904Sdim} 7340212904Sdim 7341212904Sdimvoid Sema::CodeCompletePreprocessorMacroArgument(Scope *S, 7342212904Sdim IdentifierInfo *Macro, 7343212904Sdim MacroInfo *MacroInfo, 7344212904Sdim unsigned Argument) { 7345212904Sdim // FIXME: In the future, we could provide "overload" results, much like we 7346212904Sdim // do for function calls. 7347212904Sdim 7348226633Sdim // Now just ignore this. There will be another code-completion callback 7349226633Sdim // for the expanded tokens. 7350212904Sdim} 7351212904Sdim 7352212904Sdimvoid Sema::CodeCompleteNaturalLanguage() { 7353212904Sdim HandleCodeCompleteResults(this, CodeCompleter, 7354212904Sdim CodeCompletionContext::CCC_NaturalLanguage, 7355212904Sdim 0, 0); 7356212904Sdim} 7357212904Sdim 7358218893Sdimvoid Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator, 7359234353Sdim CodeCompletionTUInfo &CCTUInfo, 7360226633Sdim SmallVectorImpl<CodeCompletionResult> &Results) { 7361234353Sdim ResultBuilder Builder(*this, Allocator, CCTUInfo, 7362234353Sdim CodeCompletionContext::CCC_Recovery); 7363212904Sdim if (!CodeCompleter || CodeCompleter->includeGlobals()) { 7364212904Sdim CodeCompletionDeclConsumer Consumer(Builder, 7365212904Sdim Context.getTranslationUnitDecl()); 7366212904Sdim LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, 7367212904Sdim Consumer); 7368212904Sdim } 7369212904Sdim 7370212904Sdim if (!CodeCompleter || CodeCompleter->includeMacros()) 7371243830Sdim AddMacroResults(PP, Builder, true); 7372212904Sdim 7373212904Sdim Results.clear(); 7374212904Sdim Results.insert(Results.end(), 7375212904Sdim Builder.data(), Builder.data() + Builder.size()); 7376212904Sdim} 7377