summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/CodeCompleteConsumer.h26
-rw-r--r--clang/lib/Sema/CodeCompleteConsumer.cpp61
-rw-r--r--clang/lib/Sema/SemaCodeComplete.cpp40
-rw-r--r--clang/test/CodeCompletion/property.m29
-rw-r--r--clang/test/Index/complete-property-flags.m29
5 files changed, 147 insertions, 38 deletions
diff --git a/clang/include/clang/Sema/CodeCompleteConsumer.h b/clang/include/clang/Sema/CodeCompleteConsumer.h
index 43ff6869184..f8c4c5281c6 100644
--- a/clang/include/clang/Sema/CodeCompleteConsumer.h
+++ b/clang/include/clang/Sema/CodeCompleteConsumer.h
@@ -123,6 +123,9 @@ public:
/// \brief Create a new current-parameter chunk.
static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter);
+ /// \brief Clone the given chunk.
+ Chunk Clone() const;
+
/// \brief Destroy this chunk, deallocating any memory it owns.
void Destroy();
};
@@ -192,15 +195,21 @@ public:
/// \brief Add a new chunk.
void AddChunk(Chunk C) { Chunks.push_back(C); }
+ /// \brief Returns the text in the TypedText chunk.
+ const char *getTypedText() const;
+
/// \brief Retrieve a string representation of the code completion string,
/// which is mainly useful for debugging.
std::string getAsString() const;
+ /// \brief Clone this code-completion string.
+ CodeCompletionString *Clone() const;
+
/// \brief Serialize this code-completion string to the given stream.
void Serialize(llvm::raw_ostream &OS) const;
/// \brief Deserialize a code-completion string from the given string.
- static CodeCompletionString *Deserialize(llvm::StringRef &Str);
+ static CodeCompletionString *Deserialize(llvm::StringRef &Str);
};
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
@@ -220,7 +229,8 @@ public:
enum ResultKind {
RK_Declaration = 0, //< Refers to a declaration
RK_Keyword, //< Refers to a keyword or symbol.
- RK_Macro //< Refers to a macro
+ RK_Macro, //< Refers to a macro
+ RK_Pattern //< Refers to a precomputed pattern.
};
/// \brief The kind of result stored here.
@@ -235,6 +245,10 @@ public:
/// or symbol's spelling.
const char *Keyword;
+ /// \brief When Kind == RK_Pattern, the code-completion string that
+ /// describes the completion text to insert.
+ CodeCompletionString *Pattern;
+
/// \brief When Kind == RK_Macro, the identifier that refers to a macro.
IdentifierInfo *Macro;
};
@@ -277,6 +291,12 @@ public:
: Kind(RK_Macro), Macro(Macro), Rank(Rank), Hidden(false),
QualifierIsInformative(0), StartsNestedNameSpecifier(false),
Qualifier(0) { }
+
+ /// \brief Build a result that refers to a pattern.
+ Result(CodeCompletionString *Pattern, unsigned Rank)
+ : Kind(RK_Pattern), Pattern(Pattern), Rank(Rank), Hidden(false),
+ QualifierIsInformative(0), StartsNestedNameSpecifier(false),
+ Qualifier(0) { }
/// \brief Retrieve the declaration stored in this result.
NamedDecl *getDeclaration() const {
@@ -293,6 +313,8 @@ public:
/// \brief Create a new code-completion string that describes how to insert
/// this result into a program.
CodeCompletionString *CreateCodeCompletionString(Sema &S);
+
+ void Destroy();
};
class OverloadCandidate {
diff --git a/clang/lib/Sema/CodeCompleteConsumer.cpp b/clang/lib/Sema/CodeCompleteConsumer.cpp
index 88ac4e49cf9..a9d83010576 100644
--- a/clang/lib/Sema/CodeCompleteConsumer.cpp
+++ b/clang/lib/Sema/CodeCompleteConsumer.cpp
@@ -117,6 +117,33 @@ CodeCompletionString::Chunk::CreateCurrentParameter(
return Chunk(CK_CurrentParameter, CurrentParameter);
}
+CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const {
+ switch (Kind) {
+ case CK_TypedText:
+ case CK_Text:
+ case CK_Placeholder:
+ case CK_Informative:
+ case CK_CurrentParameter:
+ case CK_LeftParen:
+ case CK_RightParen:
+ case CK_LeftBracket:
+ case CK_RightBracket:
+ case CK_LeftBrace:
+ case CK_RightBrace:
+ case CK_LeftAngle:
+ case CK_RightAngle:
+ case CK_Comma:
+ return Chunk(Kind, Text);
+
+ case CK_Optional: {
+ std::auto_ptr<CodeCompletionString> Opt(Optional->Clone());
+ return CreateOptional(Opt);
+ }
+ }
+
+ // Silence GCC warning.
+ return Chunk();
+}
void
CodeCompletionString::Chunk::Destroy() {
@@ -168,6 +195,20 @@ std::string CodeCompletionString::getAsString() const {
return Result;
}
+const char *CodeCompletionString::getTypedText() const {
+ for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
+ if (C->Kind == CK_TypedText)
+ return C->Text;
+
+ return 0;
+}
+
+CodeCompletionString *CodeCompletionString::Clone() const {
+ CodeCompletionString *Result = new CodeCompletionString;
+ for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
+ Result->AddChunk(C->Clone());
+ return Result;
+}
namespace {
// Escape a string for XML-like formatting.
@@ -473,6 +514,13 @@ CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
return Result;
}
+void CodeCompleteConsumer::Result::Destroy() {
+ if (Kind == RK_Pattern) {
+ delete Pattern;
+ Pattern = 0;
+ }
+}
+
//===----------------------------------------------------------------------===//
// Code completion overload candidate implementation
//===----------------------------------------------------------------------===//
@@ -545,6 +593,12 @@ PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
OS << '\n';
break;
}
+
+ case Result::RK_Pattern: {
+ OS << "Pattern : " << Results[I].Rank << " : "
+ << Results[I].Pattern->getAsString() << '\n';
+ break;
+ }
}
}
@@ -627,6 +681,13 @@ CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
OS << '\n';
break;
}
+
+ case Result::RK_Pattern: {
+ OS << "Pattern:";
+ Results[I].Pattern->Serialize(OS);
+ OS << '\n';
+ break;
+ }
}
}
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 22d2884ede1..f3f7d3f4055 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -1066,6 +1066,17 @@ namespace {
else if (X.Rank > Y.Rank)
return false;
+ // We use a special ordering for keywords and patterns, based on the
+ // typed text.
+ if ((X.Kind == Result::RK_Keyword || X.Kind == Result::RK_Pattern) &&
+ (Y.Kind == Result::RK_Keyword || Y.Kind == Result::RK_Pattern)) {
+ const char *XStr = (X.Kind == Result::RK_Keyword)? X.Keyword
+ : X.Pattern->getTypedText();
+ const char *YStr = (Y.Kind == Result::RK_Keyword)? Y.Keyword
+ : Y.Pattern->getTypedText();
+ return strcmp(XStr, YStr) < 0;
+ }
+
// Result kinds are ordered by decreasing importance.
if (X.Kind < Y.Kind)
return true;
@@ -1087,12 +1098,14 @@ namespace {
return isEarlierDeclarationName(X.Declaration->getDeclName(),
Y.Declaration->getDeclName());
- case Result::RK_Keyword:
- return strcmp(X.Keyword, Y.Keyword) < 0;
-
case Result::RK_Macro:
return llvm::LowercaseString(X.Macro->getName()) <
llvm::LowercaseString(Y.Macro->getName());
+
+ case Result::RK_Keyword:
+ case Result::RK_Pattern:
+ llvm::llvm_unreachable("Result kinds handled above");
+ break;
}
// Silence GCC warning.
@@ -1120,6 +1133,9 @@ static void HandleCodeCompleteResults(Sema *S,
if (CodeCompleter)
CodeCompleter->ProcessCodeCompleteResults(*S, Results, NumResults);
+
+ for (unsigned I = 0; I != NumResults; ++I)
+ Results[I].Destroy();
}
void Sema::CodeCompleteOrdinaryName(Scope *S) {
@@ -1635,10 +1651,20 @@ void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Results.MaybeAddResult(CodeCompleteConsumer::Result("copy", 0));
if (!(Attributes & ObjCDeclSpec::DQ_PR_nonatomic))
Results.MaybeAddResult(CodeCompleteConsumer::Result("nonatomic", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_setter))
- Results.MaybeAddResult(CodeCompleteConsumer::Result("setter", 0));
- if (!(Attributes & ObjCDeclSpec::DQ_PR_getter))
- Results.MaybeAddResult(CodeCompleteConsumer::Result("getter", 0));
+ if (!(Attributes & ObjCDeclSpec::DQ_PR_setter)) {
+ CodeCompletionString *Setter = new CodeCompletionString;
+ Setter->AddTypedTextChunk("setter");
+ Setter->AddTextChunk(" = ");
+ Setter->AddPlaceholderChunk("method");
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(Setter, 0));
+ }
+ if (!(Attributes & ObjCDeclSpec::DQ_PR_getter)) {
+ CodeCompletionString *Getter = new CodeCompletionString;
+ Getter->AddTypedTextChunk("getter");
+ Getter->AddTextChunk(" = ");
+ Getter->AddPlaceholderChunk("method");
+ Results.MaybeAddResult(CodeCompleteConsumer::Result(Getter, 0));
+ }
Results.ExitScope();
HandleCodeCompleteResults(this, CodeCompleter, Results.data(),Results.size());
}
diff --git a/clang/test/CodeCompletion/property.m b/clang/test/CodeCompletion/property.m
deleted file mode 100644
index 184519b408f..00000000000
--- a/clang/test/CodeCompletion/property.m
+++ /dev/null
@@ -1,29 +0,0 @@
-// Note: the run lines follow their respective tests, since line/column
-// matter in this test.
-
-@interface Foo {
- void *isa;
-}
-@property(copy) Foo *myprop;
-@property(retain, nonatomic) id xx;
-// RUN: clang-cc -fsyntax-only -code-completion-at=%s:7:11 %s -o - | FileCheck -check-prefix=CC1 %s
-// CC1: assign
-// CC1-NEXT: copy
-// CC1-NEXT: getter
-// CC1-NEXT: nonatomic
-// CC1-NEXT: readonly
-// CC1-NEXT: readwrite
-// CC1-NEXT: retain
-// CC1-NEXT: setter
-// RUN: clang-cc -fsyntax-only -code-completion-at=%s:8:18 %s -o - | FileCheck -check-prefix=CC2 %s
-// CC2: assign
-// CC2-NEXT: copy
-// CC2-NEXT: getter
-// CC2-NEXT: nonatomic
-// CC2-NEXT: readonly
-// CC2-NEXT: readwrite
-// CC2-NEXT: setter
-@end
-
-
-
diff --git a/clang/test/Index/complete-property-flags.m b/clang/test/Index/complete-property-flags.m
new file mode 100644
index 00000000000..65204b54f82
--- /dev/null
+++ b/clang/test/Index/complete-property-flags.m
@@ -0,0 +1,29 @@
+// Note: the run lines follow their respective tests, since line/column
+// matter in this test.
+
+@interface Foo {
+ void *isa;
+}
+@property(copy) Foo *myprop;
+@property(retain, nonatomic) id xx;
+// RUN: c-index-test -code-completion-at=%s:7:11 %s | FileCheck -check-prefix=CHECK-CC1 %s
+// CHECK-CC1: {TypedText assign}
+// CHECK-CC1-NEXT: {TypedText copy}
+// CHECK-CC1-NEXT: {TypedText getter}{Text = }{Placeholder method}
+// CHECK-CC1-NEXT: {TypedText nonatomic}
+// CHECK-CC1-NEXT: {TypedText readonly}
+// CHECK-CC1-NEXT: {TypedText readwrite}
+// CHECK-CC1-NEXT: {TypedText retain}
+// CHECK-CC1-NEXT: {TypedText setter}{Text = }{Placeholder method}
+// RUN: c-index-test -code-completion-at=%s:8:18 %s | FileCheck -check-prefix=CHECK-CC2 %s
+// CHECK-CC2: {TypedText assign}
+// CHECK-CC2-NEXT: {TypedText copy}
+// CHECK-CC2-NEXT: {TypedText getter}{Text = }{Placeholder method}
+// CHECK-CC2-NEXT: {TypedText nonatomic}
+// CHECK-CC2-NEXT: {TypedText readonly}
+// CHECK-CC2-NEXT: {TypedText readwrite}
+// CHECK-CC2-NEXT: {TypedText setter}{Text = }{Placeholder method}
+@end
+
+
+
OpenPOWER on IntegriCloud