blob: ee6fb3bf0e194fe7cb7f29356863de96394ba8a0 [file] [log] [blame]
Douglas Gregor86d9a522009-09-21 16:56:56 +00001//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
Douglas Gregor81b747b2009-09-17 21:32:03 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the CodeCompleteConsumer class.
11//
12//===----------------------------------------------------------------------===//
13#include "clang/Sema/CodeCompleteConsumer.h"
John McCall19510852010-08-20 18:27:03 +000014#include "clang/Sema/Scope.h"
Douglas Gregore737f502010-08-12 20:07:10 +000015#include "clang/Sema/Sema.h"
Douglas Gregor75b71282009-09-18 17:54:00 +000016#include "clang/AST/DeclCXX.h"
John McCall7cd088e2010-08-24 07:21:54 +000017#include "clang/AST/DeclObjC.h"
John McCall2a7fb272010-08-25 05:32:35 +000018#include "clang/AST/DeclTemplate.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000019#include "clang/Lex/Preprocessor.h"
Douglas Gregor2b4074f2009-12-01 05:55:20 +000020#include "clang-c/Index.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000021#include "llvm/ADT/STLExtras.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000022#include "llvm/Support/raw_ostream.h"
23#include <algorithm>
Douglas Gregore6e03612009-09-18 22:15:54 +000024#include <cstring>
25#include <functional>
Douglas Gregor92eff462009-11-17 16:43:05 +000026
Douglas Gregor81b747b2009-09-17 21:32:03 +000027using namespace clang;
Douglas Gregor92eff462009-11-17 16:43:05 +000028using llvm::StringRef;
Douglas Gregor81b747b2009-09-17 21:32:03 +000029
Douglas Gregore6e03612009-09-18 22:15:54 +000030//===----------------------------------------------------------------------===//
Douglas Gregor6f942b22010-09-21 16:06:22 +000031// Code completion context implementation
32//===----------------------------------------------------------------------===//
33
34bool CodeCompletionContext::wantConstructorResults() const {
35 switch (Kind) {
Douglas Gregor52779fb2010-09-23 23:01:17 +000036 case CCC_Recovery:
Douglas Gregor6f942b22010-09-21 16:06:22 +000037 case CCC_Statement:
38 case CCC_Expression:
39 case CCC_ObjCMessageReceiver:
40 case CCC_ParenthesizedExpression:
41 return true;
42
43 case CCC_TopLevel:
44 case CCC_ObjCInterface:
45 case CCC_ObjCImplementation:
46 case CCC_ObjCIvarList:
47 case CCC_ClassStructUnion:
48 case CCC_MemberAccess:
49 case CCC_EnumTag:
50 case CCC_UnionTag:
51 case CCC_ClassOrStructTag:
52 case CCC_ObjCProtocolName:
53 case CCC_Namespace:
54 case CCC_Type:
55 case CCC_Name:
56 case CCC_PotentiallyQualifiedName:
57 case CCC_MacroName:
58 case CCC_MacroNameUse:
59 case CCC_PreprocessorExpression:
60 case CCC_PreprocessorDirective:
61 case CCC_NaturalLanguage:
62 case CCC_SelectorName:
63 case CCC_TypeQualifiers:
Douglas Gregor52779fb2010-09-23 23:01:17 +000064 case CCC_Other:
Douglas Gregor6f942b22010-09-21 16:06:22 +000065 return false;
66 }
67
68 return false;
69}
70
71//===----------------------------------------------------------------------===//
Douglas Gregore6e03612009-09-18 22:15:54 +000072// Code completion string implementation
73//===----------------------------------------------------------------------===//
Douglas Gregor0c8296d2009-11-07 00:00:49 +000074CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
Daniel Dunbarad5757f2009-11-12 18:40:12 +000075 : Kind(Kind), Text("")
Douglas Gregor0563c262009-09-22 23:15:58 +000076{
Douglas Gregor0c8296d2009-11-07 00:00:49 +000077 switch (Kind) {
78 case CK_TypedText:
79 case CK_Text:
80 case CK_Placeholder:
81 case CK_Informative:
Douglas Gregorff5ce6e2009-12-18 18:53:37 +000082 case CK_ResultType:
Douglas Gregor0c8296d2009-11-07 00:00:49 +000083 case CK_CurrentParameter: {
84 char *New = new char [Text.size() + 1];
85 std::memcpy(New, Text.data(), Text.size());
86 New[Text.size()] = '\0';
87 this->Text = New;
88 break;
89 }
90
91 case CK_Optional:
Jeffrey Yasskin9f61aa92009-12-12 05:05:38 +000092 llvm_unreachable("Optional strings cannot be created from text");
Douglas Gregor0c8296d2009-11-07 00:00:49 +000093 break;
94
95 case CK_LeftParen:
96 this->Text = "(";
97 break;
98
99 case CK_RightParen:
100 this->Text = ")";
101 break;
102
103 case CK_LeftBracket:
104 this->Text = "[";
105 break;
106
107 case CK_RightBracket:
108 this->Text = "]";
109 break;
110
111 case CK_LeftBrace:
112 this->Text = "{";
113 break;
114
115 case CK_RightBrace:
116 this->Text = "}";
117 break;
118
119 case CK_LeftAngle:
120 this->Text = "<";
121 break;
122
123 case CK_RightAngle:
124 this->Text = ">";
125 break;
126
127 case CK_Comma:
128 this->Text = ", ";
129 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000130
131 case CK_Colon:
Douglas Gregore8f5a172010-04-07 00:21:17 +0000132 this->Text = ":";
Douglas Gregor01dfea02010-01-10 23:08:15 +0000133 break;
134
135 case CK_SemiColon:
136 this->Text = ";";
137 break;
138
139 case CK_Equal:
140 this->Text = " = ";
141 break;
142
143 case CK_HorizontalSpace:
144 this->Text = " ";
145 break;
146
147 case CK_VerticalSpace:
148 this->Text = "\n";
149 break;
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000150 }
Douglas Gregor0563c262009-09-22 23:15:58 +0000151}
152
153CodeCompletionString::Chunk
Douglas Gregor92eff462009-11-17 16:43:05 +0000154CodeCompletionString::Chunk::CreateText(StringRef Text) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000155 return Chunk(CK_Text, Text);
Douglas Gregore6e03612009-09-18 22:15:54 +0000156}
157
158CodeCompletionString::Chunk
159CodeCompletionString::Chunk::CreateOptional(
160 std::auto_ptr<CodeCompletionString> Optional) {
161 Chunk Result;
162 Result.Kind = CK_Optional;
163 Result.Optional = Optional.release();
164 return Result;
165}
166
167CodeCompletionString::Chunk
Douglas Gregor92eff462009-11-17 16:43:05 +0000168CodeCompletionString::Chunk::CreatePlaceholder(StringRef Placeholder) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000169 return Chunk(CK_Placeholder, Placeholder);
170}
171
172CodeCompletionString::Chunk
Douglas Gregor92eff462009-11-17 16:43:05 +0000173CodeCompletionString::Chunk::CreateInformative(StringRef Informative) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000174 return Chunk(CK_Informative, Informative);
Douglas Gregore6e03612009-09-18 22:15:54 +0000175}
176
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000177CodeCompletionString::Chunk
Douglas Gregorff5ce6e2009-12-18 18:53:37 +0000178CodeCompletionString::Chunk::CreateResultType(StringRef ResultType) {
179 return Chunk(CK_ResultType, ResultType);
180}
181
182CodeCompletionString::Chunk
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000183CodeCompletionString::Chunk::CreateCurrentParameter(
Douglas Gregor92eff462009-11-17 16:43:05 +0000184 StringRef CurrentParameter) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000185 return Chunk(CK_CurrentParameter, CurrentParameter);
186}
187
Douglas Gregor54f01612009-11-19 00:01:57 +0000188CodeCompletionString::Chunk CodeCompletionString::Chunk::Clone() const {
189 switch (Kind) {
190 case CK_TypedText:
191 case CK_Text:
192 case CK_Placeholder:
193 case CK_Informative:
Douglas Gregorff5ce6e2009-12-18 18:53:37 +0000194 case CK_ResultType:
Douglas Gregor54f01612009-11-19 00:01:57 +0000195 case CK_CurrentParameter:
196 case CK_LeftParen:
197 case CK_RightParen:
198 case CK_LeftBracket:
199 case CK_RightBracket:
200 case CK_LeftBrace:
201 case CK_RightBrace:
202 case CK_LeftAngle:
203 case CK_RightAngle:
204 case CK_Comma:
Douglas Gregor01dfea02010-01-10 23:08:15 +0000205 case CK_Colon:
206 case CK_SemiColon:
207 case CK_Equal:
208 case CK_HorizontalSpace:
209 case CK_VerticalSpace:
Douglas Gregor54f01612009-11-19 00:01:57 +0000210 return Chunk(Kind, Text);
211
212 case CK_Optional: {
213 std::auto_ptr<CodeCompletionString> Opt(Optional->Clone());
214 return CreateOptional(Opt);
215 }
216 }
217
218 // Silence GCC warning.
219 return Chunk();
220}
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000221
Douglas Gregore6e03612009-09-18 22:15:54 +0000222void
223CodeCompletionString::Chunk::Destroy() {
224 switch (Kind) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000225 case CK_Optional:
226 delete Optional;
227 break;
228
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000229 case CK_TypedText:
Douglas Gregor0563c262009-09-22 23:15:58 +0000230 case CK_Text:
231 case CK_Placeholder:
232 case CK_Informative:
Douglas Gregorff5ce6e2009-12-18 18:53:37 +0000233 case CK_ResultType:
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000234 case CK_CurrentParameter:
235 delete [] Text;
236 break;
237
238 case CK_LeftParen:
239 case CK_RightParen:
240 case CK_LeftBracket:
241 case CK_RightBracket:
242 case CK_LeftBrace:
243 case CK_RightBrace:
244 case CK_LeftAngle:
245 case CK_RightAngle:
246 case CK_Comma:
Douglas Gregor01dfea02010-01-10 23:08:15 +0000247 case CK_Colon:
248 case CK_SemiColon:
249 case CK_Equal:
250 case CK_HorizontalSpace:
251 case CK_VerticalSpace:
Douglas Gregor0563c262009-09-22 23:15:58 +0000252 break;
Douglas Gregore6e03612009-09-18 22:15:54 +0000253 }
254}
255
Douglas Gregor12e13132010-05-26 22:00:08 +0000256void CodeCompletionString::clear() {
Douglas Gregore6e03612009-09-18 22:15:54 +0000257 std::for_each(Chunks.begin(), Chunks.end(),
258 std::mem_fun_ref(&Chunk::Destroy));
Douglas Gregor12e13132010-05-26 22:00:08 +0000259 Chunks.clear();
Douglas Gregore6e03612009-09-18 22:15:54 +0000260}
261
262std::string CodeCompletionString::getAsString() const {
263 std::string Result;
264 llvm::raw_string_ostream OS(Result);
265
266 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
267 switch (C->Kind) {
Douglas Gregore6e03612009-09-18 22:15:54 +0000268 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
Douglas Gregor0563c262009-09-22 23:15:58 +0000269 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +0000270
271 case CK_Informative:
272 case CK_ResultType:
273 OS << "[#" << C->Text << "#]";
274 break;
275
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000276 case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
277 default: OS << C->Text; break;
Douglas Gregore6e03612009-09-18 22:15:54 +0000278 }
279 }
Dan Gohman6bdeb402010-07-26 21:33:22 +0000280 return OS.str();
Douglas Gregore6e03612009-09-18 22:15:54 +0000281}
282
Douglas Gregor54f01612009-11-19 00:01:57 +0000283const char *CodeCompletionString::getTypedText() const {
284 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
285 if (C->Kind == CK_TypedText)
286 return C->Text;
287
288 return 0;
289}
290
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000291CodeCompletionString *
292CodeCompletionString::Clone(CodeCompletionString *Result) const {
293 if (!Result)
294 Result = new CodeCompletionString;
Douglas Gregor54f01612009-11-19 00:01:57 +0000295 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C)
296 Result->AddChunk(C->Clone());
297 return Result;
298}
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000299
John McCall0a2c5e22010-08-25 06:19:51 +0000300void CodeCompletionResult::Destroy() {
Douglas Gregor54f01612009-11-19 00:01:57 +0000301 if (Kind == RK_Pattern) {
302 delete Pattern;
303 Pattern = 0;
304 }
305}
306
John McCall0a2c5e22010-08-25 06:19:51 +0000307unsigned CodeCompletionResult::getPriorityFromDecl(NamedDecl *ND) {
Douglas Gregor12e13132010-05-26 22:00:08 +0000308 if (!ND)
309 return CCP_Unlikely;
310
311 // Context-based decisions.
Sebastian Redl7a126a42010-08-31 00:36:30 +0000312 DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Douglas Gregor97fe61c2010-09-18 15:16:27 +0000313 if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
314 // _cmd is relatively rare
315 if (ImplicitParamDecl *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
316 if (ImplicitParam->getIdentifier() &&
317 ImplicitParam->getIdentifier()->isStr("_cmd"))
318 return CCP_ObjC_cmd;
319
Douglas Gregor12e13132010-05-26 22:00:08 +0000320 return CCP_LocalDeclaration;
Douglas Gregor97fe61c2010-09-18 15:16:27 +0000321 }
Douglas Gregor12e13132010-05-26 22:00:08 +0000322 if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
323 return CCP_MemberDeclaration;
324
325 // Content-based decisions.
326 if (isa<EnumConstantDecl>(ND))
327 return CCP_Constant;
328 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
329 return CCP_Type;
Douglas Gregor97fe61c2010-09-18 15:16:27 +0000330
Douglas Gregor12e13132010-05-26 22:00:08 +0000331 return CCP_Declaration;
332}
333
Douglas Gregore6e03612009-09-18 22:15:54 +0000334//===----------------------------------------------------------------------===//
Douglas Gregor05944382009-09-23 00:16:58 +0000335// Code completion overload candidate implementation
336//===----------------------------------------------------------------------===//
337FunctionDecl *
338CodeCompleteConsumer::OverloadCandidate::getFunction() const {
339 if (getKind() == CK_Function)
340 return Function;
341 else if (getKind() == CK_FunctionTemplate)
342 return FunctionTemplate->getTemplatedDecl();
343 else
344 return 0;
345}
346
347const FunctionType *
348CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
349 switch (Kind) {
350 case CK_Function:
351 return Function->getType()->getAs<FunctionType>();
352
353 case CK_FunctionTemplate:
354 return FunctionTemplate->getTemplatedDecl()->getType()
355 ->getAs<FunctionType>();
356
357 case CK_FunctionType:
358 return Type;
359 }
360
361 return 0;
362}
363
364//===----------------------------------------------------------------------===//
Douglas Gregore6e03612009-09-18 22:15:54 +0000365// Code completion consumer implementation
366//===----------------------------------------------------------------------===//
367
Douglas Gregor86d9a522009-09-21 16:56:56 +0000368CodeCompleteConsumer::~CodeCompleteConsumer() { }
Douglas Gregore6e03612009-09-18 22:15:54 +0000369
Douglas Gregor81b747b2009-09-17 21:32:03 +0000370void
Daniel Dunbar3a2838d2009-11-13 08:58:20 +0000371PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
Douglas Gregore6b1bb62010-08-11 21:23:17 +0000372 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +0000373 CodeCompletionResult *Results,
Douglas Gregor81b747b2009-09-17 21:32:03 +0000374 unsigned NumResults) {
Douglas Gregor1e5e6682010-08-26 13:48:20 +0000375 std::stable_sort(Results, Results + NumResults);
376
Douglas Gregor81b747b2009-09-17 21:32:03 +0000377 // Print the results.
378 for (unsigned I = 0; I != NumResults; ++I) {
Douglas Gregorf52cede2009-10-09 22:16:47 +0000379 OS << "COMPLETION: ";
Douglas Gregor81b747b2009-09-17 21:32:03 +0000380 switch (Results[I].Kind) {
John McCall0a2c5e22010-08-25 06:19:51 +0000381 case CodeCompletionResult::RK_Declaration:
Benjamin Kramer900fc632010-04-17 09:33:03 +0000382 OS << Results[I].Declaration;
Douglas Gregor81b747b2009-09-17 21:32:03 +0000383 if (Results[I].Hidden)
384 OS << " (Hidden)";
Douglas Gregor86d9a522009-09-21 16:56:56 +0000385 if (CodeCompletionString *CCS
386 = Results[I].CreateCodeCompletionString(SemaRef)) {
Douglas Gregore6e03612009-09-18 22:15:54 +0000387 OS << " : " << CCS->getAsString();
388 delete CCS;
389 }
390
Douglas Gregor81b747b2009-09-17 21:32:03 +0000391 OS << '\n';
392 break;
393
John McCall0a2c5e22010-08-25 06:19:51 +0000394 case CodeCompletionResult::RK_Keyword:
Douglas Gregorab0b4f12010-01-13 23:24:38 +0000395 OS << Results[I].Keyword << '\n';
Douglas Gregor81b747b2009-09-17 21:32:03 +0000396 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +0000397
John McCall0a2c5e22010-08-25 06:19:51 +0000398 case CodeCompletionResult::RK_Macro: {
Douglas Gregorab0b4f12010-01-13 23:24:38 +0000399 OS << Results[I].Macro->getName();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +0000400 if (CodeCompletionString *CCS
Douglas Gregorab0b4f12010-01-13 23:24:38 +0000401 = Results[I].CreateCodeCompletionString(SemaRef)) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +0000402 OS << " : " << CCS->getAsString();
403 delete CCS;
404 }
405 OS << '\n';
406 break;
407 }
Douglas Gregor54f01612009-11-19 00:01:57 +0000408
John McCall0a2c5e22010-08-25 06:19:51 +0000409 case CodeCompletionResult::RK_Pattern: {
Douglas Gregorab0b4f12010-01-13 23:24:38 +0000410 OS << "Pattern : "
Douglas Gregor54f01612009-11-19 00:01:57 +0000411 << Results[I].Pattern->getAsString() << '\n';
412 break;
413 }
Douglas Gregor81b747b2009-09-17 21:32:03 +0000414 }
415 }
Douglas Gregor81b747b2009-09-17 21:32:03 +0000416}
Douglas Gregor05944382009-09-23 00:16:58 +0000417
418void
Daniel Dunbar3a2838d2009-11-13 08:58:20 +0000419PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
420 unsigned CurrentArg,
Douglas Gregor05944382009-09-23 00:16:58 +0000421 OverloadCandidate *Candidates,
422 unsigned NumCandidates) {
423 for (unsigned I = 0; I != NumCandidates; ++I) {
Douglas Gregor86d802e2009-09-23 00:34:09 +0000424 if (CodeCompletionString *CCS
425 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
Douglas Gregorf52cede2009-10-09 22:16:47 +0000426 OS << "OVERLOAD: " << CCS->getAsString() << "\n";
Douglas Gregor86d802e2009-09-23 00:34:09 +0000427 delete CCS;
Douglas Gregor05944382009-09-23 00:16:58 +0000428 }
429 }
Douglas Gregor05944382009-09-23 00:16:58 +0000430}
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000431
John McCall0a2c5e22010-08-25 06:19:51 +0000432void CodeCompletionResult::computeCursorKindAndAvailability() {
Douglas Gregor87c08a52010-08-13 22:48:40 +0000433 switch (Kind) {
434 case RK_Declaration:
Douglas Gregor58ddb602010-08-23 23:00:57 +0000435 // Set the availability based on attributes.
436 Availability = CXAvailability_Available;
437 if (Declaration->getAttr<UnavailableAttr>())
438 Availability = CXAvailability_NotAvailable;
439 else if (Declaration->getAttr<DeprecatedAttr>())
440 Availability = CXAvailability_Deprecated;
441
Douglas Gregore8d7beb2010-09-03 23:30:36 +0000442 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Declaration))
443 if (Function->isDeleted())
Douglas Gregor58ddb602010-08-23 23:00:57 +0000444 Availability = CXAvailability_NotAvailable;
Douglas Gregore8d7beb2010-09-03 23:30:36 +0000445
446 CursorKind = getCursorKindForDecl(Declaration);
447 if (CursorKind == CXCursor_UnexposedDecl)
Douglas Gregor87c08a52010-08-13 22:48:40 +0000448 CursorKind = CXCursor_NotImplemented;
Douglas Gregor87c08a52010-08-13 22:48:40 +0000449 break;
450
John McCall0a2c5e22010-08-25 06:19:51 +0000451 case RK_Macro:
Douglas Gregor58ddb602010-08-23 23:00:57 +0000452 Availability = CXAvailability_Available;
Douglas Gregor87c08a52010-08-13 22:48:40 +0000453 CursorKind = CXCursor_MacroDefinition;
454 break;
455
John McCall0a2c5e22010-08-25 06:19:51 +0000456 case RK_Keyword:
Douglas Gregor58ddb602010-08-23 23:00:57 +0000457 Availability = CXAvailability_Available;
Douglas Gregor87c08a52010-08-13 22:48:40 +0000458 CursorKind = CXCursor_NotImplemented;
459 break;
460
John McCall0a2c5e22010-08-25 06:19:51 +0000461 case RK_Pattern:
Douglas Gregor87c08a52010-08-13 22:48:40 +0000462 // Do nothing: Patterns can come with cursor kinds!
463 break;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000464 }
465}
Douglas Gregor2b4074f2009-12-01 05:55:20 +0000466
Douglas Gregor721f3592010-08-25 18:41:16 +0000467/// \brief Retrieve the name that should be used to order a result.
468///
469/// If the name needs to be constructed as a string, that string will be
470/// saved into Saved and the returned StringRef will refer to it.
471static llvm::StringRef getOrderedName(const CodeCompletionResult &R,
472 std::string &Saved) {
473 switch (R.Kind) {
474 case CodeCompletionResult::RK_Keyword:
475 return R.Keyword;
476
477 case CodeCompletionResult::RK_Pattern:
478 return R.Pattern->getTypedText();
479
480 case CodeCompletionResult::RK_Macro:
481 return R.Macro->getName();
482
483 case CodeCompletionResult::RK_Declaration:
484 // Handle declarations below.
485 break;
486 }
487
488 DeclarationName Name = R.Declaration->getDeclName();
489
490 // If the name is a simple identifier (by far the common case), or a
491 // zero-argument selector, just return a reference to that identifier.
492 if (IdentifierInfo *Id = Name.getAsIdentifierInfo())
493 return Id->getName();
494 if (Name.isObjCZeroArgSelector())
495 if (IdentifierInfo *Id
496 = Name.getObjCSelector().getIdentifierInfoForSlot(0))
497 return Id->getName();
498
499 Saved = Name.getAsString();
500 return Saved;
501}
502
503bool clang::operator<(const CodeCompletionResult &X,
504 const CodeCompletionResult &Y) {
505 std::string XSaved, YSaved;
506 llvm::StringRef XStr = getOrderedName(X, XSaved);
507 llvm::StringRef YStr = getOrderedName(Y, YSaved);
508 int cmp = XStr.compare_lower(YStr);
509 if (cmp)
510 return cmp < 0;
511
Douglas Gregor1e5e6682010-08-26 13:48:20 +0000512 // If case-insensitive comparison fails, try case-sensitive comparison.
513 cmp = XStr.compare(YStr);
514 if (cmp)
515 return cmp < 0;
Douglas Gregor721f3592010-08-25 18:41:16 +0000516
517 return false;
518}