diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-08-29 19:27:27 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-08-29 19:27:27 +0000 |
commit | 0c431c8c001e4c1f7488663d98700a8ce1e89e2a (patch) | |
tree | 6e146a551c2390a41009c5c534c9cf8af3ac4427 | |
parent | 97204552708cda46ce4adb27e81f6d295f02fec1 (diff) |
Improve code completion for initializer lists in constructors. Instead
of prioritizing just by initialization order, we bump the priority of
just the *next* initializer in the list, and leave everything else at
the normal priority. That way, if one intentionally skips the
initialization of a base or member (to get default initialization),
we'll still get ordered completion for the rest.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112454 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Sema/CodeCompleteConsumer.h | 3 | ||||
-rw-r--r-- | lib/Sema/SemaCodeComplete.cpp | 40 | ||||
-rw-r--r-- | test/Index/complete-ctor-inits.cpp | 31 |
3 files changed, 55 insertions, 19 deletions
diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index edc6331af0..c8799372ab 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -30,6 +30,9 @@ namespace clang { /// \brief Default priority values for code-completion results based /// on their kind. enum { + /// \brief Priority for the next initialization in a constructor initializer + /// list. + CCP_NextInitializer = 7, /// \brief Priority for a send-to-super completion. CCP_SuperCompletion = 8, /// \brief Priority for a declaration that is in the local scope. diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index d1851813e1..a7ac0f1170 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -3290,13 +3290,19 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, } // Add completions for base classes. - unsigned Priority = 1; + bool SawLastInitializer = (NumInitializers == 0); CXXRecordDecl *ClassDecl = Constructor->getParent(); for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), BaseEnd = ClassDecl->bases_end(); Base != BaseEnd; ++Base) { - if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) + if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isBaseInitializer() && + Context.hasSameUnqualifiedType(Base->getType(), + QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); continue; + } CodeCompletionString *Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk( @@ -3304,15 +3310,24 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, Pattern->AddChunk(CodeCompletionString::CK_LeftParen); Pattern->AddPlaceholderChunk("args"); Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Pattern, Priority++)); + Results.AddResult(CodeCompletionResult(Pattern, + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration)); + SawLastInitializer = false; } // Add completions for virtual base classes. for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(), BaseEnd = ClassDecl->vbases_end(); Base != BaseEnd; ++Base) { - if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) + if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isBaseInitializer() && + Context.hasSameUnqualifiedType(Base->getType(), + QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0)); continue; + } CodeCompletionString *Pattern = new CodeCompletionString; Pattern->AddTypedTextChunk( @@ -3320,15 +3335,23 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, Pattern->AddChunk(CodeCompletionString::CK_LeftParen); Pattern->AddPlaceholderChunk("args"); Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Pattern, Priority++)); + Results.AddResult(CodeCompletionResult(Pattern, + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration)); + SawLastInitializer = false; } // Add completions for members. for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), FieldEnd = ClassDecl->field_end(); Field != FieldEnd; ++Field) { - if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) + if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) { + SawLastInitializer + = NumInitializers > 0 && + Initializers[NumInitializers - 1]->isMemberInitializer() && + Initializers[NumInitializers - 1]->getMember() == *Field; continue; + } if (!Field->getDeclName()) continue; @@ -3338,7 +3361,10 @@ void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD, Pattern->AddChunk(CodeCompletionString::CK_LeftParen); Pattern->AddPlaceholderChunk("args"); Pattern->AddChunk(CodeCompletionString::CK_RightParen); - Results.AddResult(CodeCompletionResult(Pattern, Priority++)); + Results.AddResult(CodeCompletionResult(Pattern, + SawLastInitializer? CCP_NextInitializer + : CCP_MemberDeclaration)); + SawLastInitializer = false; } Results.ExitScope(); diff --git a/test/Index/complete-ctor-inits.cpp b/test/Index/complete-ctor-inits.cpp index d1c517daf9..f9cc7022ea 100644 --- a/test/Index/complete-ctor-inits.cpp +++ b/test/Index/complete-ctor-inits.cpp @@ -15,19 +15,26 @@ struct Z : public X<int>, public Y { int a, b, c; }; -Z::Z() : ::X<int>(0), Virt(), a() { } +Z::Z() : ::X<int>(0), Virt(), b(), c() { } // RUN: c-index-test -code-completion-at=%s:18:10 %s | FileCheck -check-prefix=CHECK-CC1 %s -// CHECK-CC1: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (4) -// CHECK-CC1: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (5) -// CHECK-CC1: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (6) -// CHECK-CC1: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (3) -// CHECK-CC1: NotImplemented:{TypedText X<int>}{LeftParen (}{Placeholder args}{RightParen )} (1) -// CHECK-CC1: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (2) +// CHECK-CC1: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC1: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC1: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC1: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC1: NotImplemented:{TypedText X<int>}{LeftParen (}{Placeholder args}{RightParen )} (7) +// CHECK-CC1: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (20) // RUN: c-index-test -code-completion-at=%s:18:23 %s | FileCheck -check-prefix=CHECK-CC2 %s -// CHECK-CC2: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (3) -// CHECK-CC2: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (4) -// CHECK-CC2: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (5) -// CHECK-CC2: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (2) -// CHECK-CC2: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (1) +// CHECK-CC2: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC2: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC2: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC2: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC2: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (7) + +// RUN: c-index-test -code-completion-at=%s:18:36 %s | FileCheck -check-prefix=CHECK-CC3 %s +// CHECK-CC3: NotImplemented:{TypedText a}{LeftParen (}{Placeholder args}{RightParen )} (20) +// CHECK-CC3-NOT: NotImplemented:{TypedText b}{LeftParen (}{Placeholder args}{RightParen )} +// CHECK-CC3: NotImplemented:{TypedText c}{LeftParen (}{Placeholder args}{RightParen )} (7) +// CHECK-CC3-NOT: NotImplemented:{TypedText Virt}{LeftParen (}{Placeholder args}{RightParen )} +// CHECK-CC3: NotImplemented:{TypedText Y}{LeftParen (}{Placeholder args}{RightParen )} (20) |