CodeCompleteConsumer.cpp revision 198893
1//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===// 2// 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" 14#include "clang/AST/DeclCXX.h" 15#include "clang/Parse/Scope.h" 16#include "clang/Lex/Preprocessor.h" 17#include "Sema.h" 18#include "llvm/ADT/STLExtras.h" 19#include "llvm/Support/Compiler.h" 20#include "llvm/Support/raw_ostream.h" 21#include <algorithm> 22#include <cstring> 23#include <functional> 24using namespace clang; 25 26//===----------------------------------------------------------------------===// 27// Code completion string implementation 28//===----------------------------------------------------------------------===// 29CodeCompletionString::Chunk::Chunk(ChunkKind Kind, const char *Text) 30 : Kind(Kind), Text(0) 31{ 32 assert((Kind == CK_Text || Kind == CK_Placeholder || Kind == CK_Informative) 33 && "Invalid text chunk kind"); 34 char *New = new char [std::strlen(Text) + 1]; 35 std::strcpy(New, Text); 36 this->Text = New; 37} 38 39CodeCompletionString::Chunk 40CodeCompletionString::Chunk::CreateText(const char *Text) { 41 return Chunk(CK_Text, Text); 42} 43 44CodeCompletionString::Chunk 45CodeCompletionString::Chunk::CreateOptional( 46 std::auto_ptr<CodeCompletionString> Optional) { 47 Chunk Result; 48 Result.Kind = CK_Optional; 49 Result.Optional = Optional.release(); 50 return Result; 51} 52 53CodeCompletionString::Chunk 54CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) { 55 return Chunk(CK_Placeholder, Placeholder); 56} 57 58CodeCompletionString::Chunk 59CodeCompletionString::Chunk::CreateInformative(const char *Informative) { 60 return Chunk(CK_Informative, Informative); 61} 62 63void 64CodeCompletionString::Chunk::Destroy() { 65 switch (Kind) { 66 case CK_Optional: 67 delete Optional; 68 break; 69 70 case CK_Text: 71 case CK_Placeholder: 72 case CK_Informative: 73 delete [] Text; 74 break; 75 } 76} 77 78CodeCompletionString::~CodeCompletionString() { 79 std::for_each(Chunks.begin(), Chunks.end(), 80 std::mem_fun_ref(&Chunk::Destroy)); 81} 82 83std::string CodeCompletionString::getAsString() const { 84 std::string Result; 85 llvm::raw_string_ostream OS(Result); 86 87 for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) { 88 switch (C->Kind) { 89 case CK_Text: OS << C->Text; break; 90 case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break; 91 case CK_Placeholder: OS << "<#" << C->Text << "#>"; break; 92 case CK_Informative: OS << "[#" << C->Text << "#]"; break; 93 } 94 } 95 OS.flush(); 96 return Result; 97} 98 99//===----------------------------------------------------------------------===// 100// Code completion overload candidate implementation 101//===----------------------------------------------------------------------===// 102FunctionDecl * 103CodeCompleteConsumer::OverloadCandidate::getFunction() const { 104 if (getKind() == CK_Function) 105 return Function; 106 else if (getKind() == CK_FunctionTemplate) 107 return FunctionTemplate->getTemplatedDecl(); 108 else 109 return 0; 110} 111 112const FunctionType * 113CodeCompleteConsumer::OverloadCandidate::getFunctionType() const { 114 switch (Kind) { 115 case CK_Function: 116 return Function->getType()->getAs<FunctionType>(); 117 118 case CK_FunctionTemplate: 119 return FunctionTemplate->getTemplatedDecl()->getType() 120 ->getAs<FunctionType>(); 121 122 case CK_FunctionType: 123 return Type; 124 } 125 126 return 0; 127} 128 129//===----------------------------------------------------------------------===// 130// Code completion consumer implementation 131//===----------------------------------------------------------------------===// 132 133CodeCompleteConsumer::~CodeCompleteConsumer() { } 134 135void 136PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Result *Results, 137 unsigned NumResults) { 138 // Print the results. 139 for (unsigned I = 0; I != NumResults; ++I) { 140 OS << "COMPLETION: "; 141 switch (Results[I].Kind) { 142 case Result::RK_Declaration: 143 OS << Results[I].Declaration->getNameAsString() << " : " 144 << Results[I].Rank; 145 if (Results[I].Hidden) 146 OS << " (Hidden)"; 147 if (CodeCompletionString *CCS 148 = Results[I].CreateCodeCompletionString(SemaRef)) { 149 OS << " : " << CCS->getAsString(); 150 delete CCS; 151 } 152 153 OS << '\n'; 154 break; 155 156 case Result::RK_Keyword: 157 OS << Results[I].Keyword << " : " << Results[I].Rank << '\n'; 158 break; 159 160 case Result::RK_Macro: { 161 OS << Results[I].Macro->getName() << " : " << Results[I].Rank; 162 if (CodeCompletionString *CCS 163 = Results[I].CreateCodeCompletionString(SemaRef)) { 164 OS << " : " << CCS->getAsString(); 165 delete CCS; 166 } 167 OS << '\n'; 168 break; 169 } 170 } 171 } 172 173 // Once we've printed the code-completion results, suppress remaining 174 // diagnostics. 175 // FIXME: Move this somewhere else! 176 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 177} 178 179void 180PrintingCodeCompleteConsumer::ProcessOverloadCandidates(unsigned CurrentArg, 181 OverloadCandidate *Candidates, 182 unsigned NumCandidates) { 183 for (unsigned I = 0; I != NumCandidates; ++I) { 184 if (CodeCompletionString *CCS 185 = Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) { 186 OS << "OVERLOAD: " << CCS->getAsString() << "\n"; 187 delete CCS; 188 } 189 } 190 191 // Once we've printed the code-completion results, suppress remaining 192 // diagnostics. 193 // FIXME: Move this somewhere else! 194 SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics(); 195} 196