2009-09-21 20:56:56 +04:00
|
|
|
//===--- CodeCompleteConsumer.cpp - Code Completion Interface ---*- C++ -*-===//
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the CodeCompleteConsumer class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "clang/Sema/CodeCompleteConsumer.h"
|
2009-09-18 21:54:00 +04:00
|
|
|
#include "clang/AST/DeclCXX.h"
|
2009-09-18 19:37:17 +04:00
|
|
|
#include "clang/Parse/Scope.h"
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
|
|
|
#include "Sema.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2009-11-07 03:00:49 +03:00
|
|
|
#include "llvm/ADT/StringSwitch.h"
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <algorithm>
|
2009-09-19 02:15:54 +04:00
|
|
|
#include <cstring>
|
|
|
|
#include <functional>
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
using namespace clang;
|
|
|
|
|
2009-09-19 02:15:54 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Code completion string implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2009-11-07 03:00:49 +03:00
|
|
|
CodeCompletionString::Chunk::Chunk(ChunkKind Kind, llvm::StringRef Text)
|
2009-11-12 21:40:12 +03:00
|
|
|
: Kind(Kind), Text("")
|
2009-09-23 03:15:58 +04:00
|
|
|
{
|
2009-11-07 03:00:49 +03:00
|
|
|
switch (Kind) {
|
|
|
|
case CK_TypedText:
|
|
|
|
case CK_Text:
|
|
|
|
case CK_Placeholder:
|
|
|
|
case CK_Informative:
|
|
|
|
case CK_CurrentParameter: {
|
|
|
|
char *New = new char [Text.size() + 1];
|
|
|
|
std::memcpy(New, Text.data(), Text.size());
|
|
|
|
New[Text.size()] = '\0';
|
|
|
|
this->Text = New;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case CK_Optional:
|
|
|
|
llvm::llvm_unreachable("Optional strings cannot be created from text");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_LeftParen:
|
|
|
|
this->Text = "(";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_RightParen:
|
|
|
|
this->Text = ")";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_LeftBracket:
|
|
|
|
this->Text = "[";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_RightBracket:
|
|
|
|
this->Text = "]";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_LeftBrace:
|
|
|
|
this->Text = "{";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_RightBrace:
|
|
|
|
this->Text = "}";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_LeftAngle:
|
|
|
|
this->Text = "<";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_RightAngle:
|
|
|
|
this->Text = ">";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_Comma:
|
|
|
|
this->Text = ", ";
|
|
|
|
break;
|
|
|
|
}
|
2009-09-23 03:15:58 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
CodeCompletionString::Chunk
|
|
|
|
CodeCompletionString::Chunk::CreateText(const char *Text) {
|
|
|
|
return Chunk(CK_Text, Text);
|
2009-09-19 02:15:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
CodeCompletionString::Chunk
|
|
|
|
CodeCompletionString::Chunk::CreateOptional(
|
|
|
|
std::auto_ptr<CodeCompletionString> Optional) {
|
|
|
|
Chunk Result;
|
|
|
|
Result.Kind = CK_Optional;
|
|
|
|
Result.Optional = Optional.release();
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
CodeCompletionString::Chunk
|
|
|
|
CodeCompletionString::Chunk::CreatePlaceholder(const char *Placeholder) {
|
2009-09-23 03:15:58 +04:00
|
|
|
return Chunk(CK_Placeholder, Placeholder);
|
|
|
|
}
|
|
|
|
|
|
|
|
CodeCompletionString::Chunk
|
|
|
|
CodeCompletionString::Chunk::CreateInformative(const char *Informative) {
|
|
|
|
return Chunk(CK_Informative, Informative);
|
2009-09-19 02:15:54 +04:00
|
|
|
}
|
|
|
|
|
2009-11-07 03:00:49 +03:00
|
|
|
CodeCompletionString::Chunk
|
|
|
|
CodeCompletionString::Chunk::CreateCurrentParameter(
|
|
|
|
const char *CurrentParameter) {
|
|
|
|
return Chunk(CK_CurrentParameter, CurrentParameter);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-19 02:15:54 +04:00
|
|
|
void
|
|
|
|
CodeCompletionString::Chunk::Destroy() {
|
|
|
|
switch (Kind) {
|
2009-09-23 03:15:58 +04:00
|
|
|
case CK_Optional:
|
|
|
|
delete Optional;
|
|
|
|
break;
|
|
|
|
|
2009-11-07 03:00:49 +03:00
|
|
|
case CK_TypedText:
|
2009-09-23 03:15:58 +04:00
|
|
|
case CK_Text:
|
|
|
|
case CK_Placeholder:
|
|
|
|
case CK_Informative:
|
2009-11-07 03:00:49 +03:00
|
|
|
case CK_CurrentParameter:
|
|
|
|
delete [] Text;
|
|
|
|
break;
|
|
|
|
|
|
|
|
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:
|
2009-09-23 03:15:58 +04:00
|
|
|
break;
|
2009-09-19 02:15:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CodeCompletionString::~CodeCompletionString() {
|
|
|
|
std::for_each(Chunks.begin(), Chunks.end(),
|
|
|
|
std::mem_fun_ref(&Chunk::Destroy));
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string CodeCompletionString::getAsString() const {
|
|
|
|
std::string Result;
|
|
|
|
llvm::raw_string_ostream OS(Result);
|
|
|
|
|
|
|
|
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
|
|
|
|
switch (C->Kind) {
|
|
|
|
case CK_Optional: OS << "{#" << C->Optional->getAsString() << "#}"; break;
|
2009-09-23 03:15:58 +04:00
|
|
|
case CK_Placeholder: OS << "<#" << C->Text << "#>"; break;
|
|
|
|
case CK_Informative: OS << "[#" << C->Text << "#]"; break;
|
2009-11-07 03:00:49 +03:00
|
|
|
case CK_CurrentParameter: OS << "<#" << C->Text << "#>"; break;
|
|
|
|
default: OS << C->Text; break;
|
2009-09-19 02:15:54 +04:00
|
|
|
}
|
|
|
|
}
|
2009-09-29 19:13:39 +04:00
|
|
|
OS.flush();
|
2009-09-19 02:15:54 +04:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-11-07 03:00:49 +03:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
// Escape a string for XML-like formatting.
|
|
|
|
struct EscapedString {
|
|
|
|
EscapedString(llvm::StringRef Str) : Str(Str) { }
|
|
|
|
|
|
|
|
llvm::StringRef Str;
|
|
|
|
};
|
|
|
|
|
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EscapedString EStr) {
|
|
|
|
llvm::StringRef Str = EStr.Str;
|
|
|
|
while (!Str.empty()) {
|
|
|
|
// Find the next escaped character.
|
|
|
|
llvm::StringRef::size_type Pos = Str.find_first_of("<>&\"'");
|
|
|
|
|
|
|
|
// Print everything before that escaped character.
|
|
|
|
OS << Str.substr(0, Pos);
|
|
|
|
|
|
|
|
// If we didn't find any escaped characters, we're done.
|
|
|
|
if (Pos == llvm::StringRef::npos)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Print the appropriate escape sequence.
|
|
|
|
switch (Str[Pos]) {
|
|
|
|
case '<': OS << "<"; break;
|
|
|
|
case '>': OS << ">"; break;
|
|
|
|
case '&': OS << "&"; break;
|
|
|
|
case '"': OS << """; break;
|
|
|
|
case '\'': OS << "'"; break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove everything up to and including that escaped character.
|
|
|
|
Str = Str.substr(Pos + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Remove XML-like escaping from a string.
|
|
|
|
std::string UnescapeString(llvm::StringRef Str) {
|
|
|
|
using llvm::StringRef;
|
|
|
|
|
|
|
|
std::string Result;
|
|
|
|
llvm::raw_string_ostream OS(Result);
|
|
|
|
|
|
|
|
while (!Str.empty()) {
|
|
|
|
StringRef::size_type Amp = Str.find('&');
|
|
|
|
OS << Str.substr(0, Amp);
|
|
|
|
|
|
|
|
if (Amp == StringRef::npos)
|
|
|
|
break;
|
|
|
|
|
|
|
|
StringRef::size_type Semi = Str.substr(Amp).find(';');
|
|
|
|
if (Semi == StringRef::npos) {
|
|
|
|
// Malformed input; do the best we can.
|
|
|
|
OS << '&';
|
|
|
|
Str = Str.substr(Amp + 1);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
char Unescaped = llvm::StringSwitch<char>(Str.substr(Amp + 1, Semi - 1))
|
|
|
|
.Case("lt", '<')
|
|
|
|
.Case("gt", '>')
|
|
|
|
.Case("amp", '&')
|
|
|
|
.Case("quot", '"')
|
|
|
|
.Case("apos", '\'')
|
|
|
|
.Default('\0');
|
|
|
|
|
|
|
|
if (Unescaped)
|
|
|
|
OS << Unescaped;
|
|
|
|
else
|
|
|
|
OS << Str.substr(Amp, Semi + 1);
|
|
|
|
Str = Str.substr(Amp + Semi + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return OS.str();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CodeCompletionString::Serialize(llvm::raw_ostream &OS) const {
|
|
|
|
for (iterator C = begin(), CEnd = end(); C != CEnd; ++C) {
|
|
|
|
switch (C->Kind) {
|
|
|
|
case CK_TypedText:
|
|
|
|
OS << "<typed-text>" << EscapedString(C->Text) << "</>";
|
|
|
|
break;
|
|
|
|
case CK_Text:
|
|
|
|
OS << "<text>" << EscapedString(C->Text) << "</>";
|
|
|
|
break;
|
|
|
|
case CK_Optional:
|
|
|
|
OS << "<optional>";
|
|
|
|
C->Optional->Serialize(OS);
|
|
|
|
OS << "</>";
|
|
|
|
break;
|
|
|
|
case CK_Placeholder:
|
|
|
|
OS << "<placeholder>" << EscapedString(C->Text) << "</>";
|
|
|
|
break;
|
|
|
|
case CK_Informative:
|
|
|
|
OS << "<informative>" << EscapedString(C->Text) << "</>";
|
|
|
|
break;
|
|
|
|
case CK_CurrentParameter:
|
|
|
|
OS << "<current-parameter>" << EscapedString(C->Text) << "</>";
|
|
|
|
break;
|
|
|
|
case CK_LeftParen:
|
|
|
|
OS << "<lparen/>";
|
|
|
|
break;
|
|
|
|
case CK_RightParen:
|
|
|
|
OS << "<rparen/>";
|
|
|
|
break;
|
|
|
|
case CK_LeftBracket:
|
|
|
|
OS << "<lbracket/>";
|
|
|
|
break;
|
|
|
|
case CK_RightBracket:
|
|
|
|
OS << "<rbracket/>";
|
|
|
|
break;
|
|
|
|
case CK_LeftBrace:
|
|
|
|
OS << "<lbrace/>";
|
|
|
|
break;
|
|
|
|
case CK_RightBrace:
|
|
|
|
OS << "<rbrace/>";
|
|
|
|
break;
|
|
|
|
case CK_LeftAngle:
|
|
|
|
OS << "<langle/>";
|
|
|
|
break;
|
|
|
|
case CK_RightAngle:
|
|
|
|
OS << "<rangle/>";
|
|
|
|
break;
|
|
|
|
case CK_Comma:
|
|
|
|
OS << "<comma/>";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Parse the next XML-ish tag of the form <blah>.
|
|
|
|
///
|
|
|
|
/// \param Str the string in which we're looking for the next tag.
|
|
|
|
///
|
|
|
|
/// \param TagPos if successful, will be set to the start of the tag we found.
|
|
|
|
///
|
|
|
|
/// \param Standalone will indicate whether this is a "standalone" tag that
|
|
|
|
/// has no associated data, e.g., <comma/>.
|
|
|
|
///
|
|
|
|
/// \param Terminator will indicate whether this is a terminating tag (that is
|
|
|
|
/// or starts with '/').
|
|
|
|
///
|
|
|
|
/// \returns the tag itself, without the angle brackets.
|
|
|
|
static llvm::StringRef ParseNextTag(llvm::StringRef Str,
|
|
|
|
llvm::StringRef::size_type &StartTag,
|
|
|
|
llvm::StringRef::size_type &AfterTag,
|
|
|
|
bool &Standalone, bool &Terminator) {
|
|
|
|
using llvm::StringRef;
|
|
|
|
|
|
|
|
Standalone = false;
|
|
|
|
Terminator = false;
|
|
|
|
AfterTag = StringRef::npos;
|
|
|
|
|
|
|
|
// Find the starting '<'.
|
|
|
|
StartTag = Str.find('<');
|
|
|
|
if (StartTag == StringRef::npos)
|
|
|
|
return llvm::StringRef();
|
|
|
|
|
|
|
|
// Find the corresponding '>'.
|
|
|
|
llvm::StringRef::size_type EndTag = Str.substr(StartTag).find('>');
|
|
|
|
if (EndTag == StringRef::npos)
|
|
|
|
return llvm::StringRef();
|
|
|
|
AfterTag = StartTag + EndTag + 1;
|
|
|
|
|
|
|
|
// Determine whether this is a terminating tag.
|
|
|
|
if (Str[StartTag + 1] == '/') {
|
|
|
|
Terminator = true;
|
|
|
|
Str = Str.substr(1);
|
|
|
|
--EndTag;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine whether this is a standalone tag.
|
|
|
|
if (!Terminator && Str[StartTag + EndTag - 1] == '/') {
|
|
|
|
Standalone = true;
|
|
|
|
if (EndTag > 1)
|
|
|
|
--EndTag;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Str.substr(StartTag + 1, EndTag - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
CodeCompletionString *CodeCompletionString::Deserialize(llvm::StringRef &Str) {
|
|
|
|
using llvm::StringRef;
|
|
|
|
|
|
|
|
CodeCompletionString *Result = new CodeCompletionString;
|
|
|
|
|
|
|
|
do {
|
|
|
|
// Parse the next tag.
|
|
|
|
StringRef::size_type StartTag, AfterTag;
|
|
|
|
bool Standalone, Terminator;
|
|
|
|
StringRef Tag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
|
|
|
|
Terminator);
|
|
|
|
|
|
|
|
if (StartTag == StringRef::npos)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Figure out what kind of chunk we have.
|
|
|
|
const unsigned UnknownKind = 10000;
|
|
|
|
unsigned Kind = llvm::StringSwitch<unsigned>(Tag)
|
|
|
|
.Case("typed-text", CK_TypedText)
|
|
|
|
.Case("text", CK_Text)
|
|
|
|
.Case("optional", CK_Optional)
|
|
|
|
.Case("placeholder", CK_Placeholder)
|
|
|
|
.Case("informative", CK_Informative)
|
|
|
|
.Case("current-parameter", CK_CurrentParameter)
|
|
|
|
.Case("lparen", CK_LeftParen)
|
|
|
|
.Case("rparen", CK_RightParen)
|
|
|
|
.Case("lbracket", CK_LeftBracket)
|
|
|
|
.Case("rbracket", CK_RightBracket)
|
|
|
|
.Case("lbrace", CK_LeftBrace)
|
|
|
|
.Case("rbrace", CK_RightBrace)
|
|
|
|
.Case("langle", CK_LeftAngle)
|
|
|
|
.Case("rangle", CK_RightAngle)
|
|
|
|
.Case("comma", CK_Comma)
|
|
|
|
.Default(UnknownKind);
|
|
|
|
|
|
|
|
// If we've hit a terminator tag, we're done.
|
|
|
|
if (Terminator)
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Consume the tag.
|
|
|
|
Str = Str.substr(AfterTag);
|
|
|
|
|
|
|
|
// Handle standalone tags now, since they don't need to be matched to
|
|
|
|
// anything.
|
|
|
|
if (Standalone) {
|
|
|
|
// Ignore anything we don't know about.
|
|
|
|
if (Kind == UnknownKind)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
switch ((ChunkKind)Kind) {
|
|
|
|
case CK_TypedText:
|
|
|
|
case CK_Text:
|
|
|
|
case CK_Optional:
|
|
|
|
case CK_Placeholder:
|
|
|
|
case CK_Informative:
|
|
|
|
case CK_CurrentParameter:
|
|
|
|
// There is no point in creating empty chunks of these kinds.
|
|
|
|
break;
|
|
|
|
|
|
|
|
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:
|
|
|
|
Result->AddChunk(Chunk((ChunkKind)Kind));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Kind == CK_Optional) {
|
|
|
|
// Deserialize the optional code-completion string.
|
|
|
|
std::auto_ptr<CodeCompletionString> Optional(Deserialize(Str));
|
|
|
|
Result->AddOptionalChunk(Optional);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef EndTag = ParseNextTag(Str, StartTag, AfterTag, Standalone,
|
|
|
|
Terminator);
|
|
|
|
if (StartTag == StringRef::npos || !Terminator || Standalone)
|
|
|
|
break; // Parsing failed; just give up.
|
|
|
|
|
|
|
|
if (EndTag.empty() || Tag == EndTag) {
|
|
|
|
// Found the matching end tag. Add this chunk based on the text
|
|
|
|
// between the tags, then consume that input.
|
|
|
|
StringRef Text = Str.substr(0, StartTag);
|
|
|
|
switch ((ChunkKind)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:
|
|
|
|
Result->AddChunk(Chunk((ChunkKind)Kind, UnescapeString(Text)));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CK_Optional:
|
|
|
|
// We've already added the optional chunk.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove this tag.
|
|
|
|
Str = Str.substr(AfterTag);
|
|
|
|
} while (!Str.empty());
|
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2009-09-23 04:16:58 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Code completion overload candidate implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
FunctionDecl *
|
|
|
|
CodeCompleteConsumer::OverloadCandidate::getFunction() const {
|
|
|
|
if (getKind() == CK_Function)
|
|
|
|
return Function;
|
|
|
|
else if (getKind() == CK_FunctionTemplate)
|
|
|
|
return FunctionTemplate->getTemplatedDecl();
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FunctionType *
|
|
|
|
CodeCompleteConsumer::OverloadCandidate::getFunctionType() const {
|
|
|
|
switch (Kind) {
|
|
|
|
case CK_Function:
|
|
|
|
return Function->getType()->getAs<FunctionType>();
|
|
|
|
|
|
|
|
case CK_FunctionTemplate:
|
|
|
|
return FunctionTemplate->getTemplatedDecl()->getType()
|
|
|
|
->getAs<FunctionType>();
|
|
|
|
|
|
|
|
case CK_FunctionType:
|
|
|
|
return Type;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-09-19 02:15:54 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Code completion consumer implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-09-21 20:56:56 +04:00
|
|
|
CodeCompleteConsumer::~CodeCompleteConsumer() { }
|
2009-09-19 02:15:54 +04:00
|
|
|
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
void
|
2009-11-13 11:58:20 +03:00
|
|
|
PrintingCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
|
|
|
|
Result *Results,
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
unsigned NumResults) {
|
|
|
|
// Print the results.
|
|
|
|
for (unsigned I = 0; I != NumResults; ++I) {
|
2009-10-10 02:16:47 +04:00
|
|
|
OS << "COMPLETION: ";
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
switch (Results[I].Kind) {
|
|
|
|
case Result::RK_Declaration:
|
|
|
|
OS << Results[I].Declaration->getNameAsString() << " : "
|
|
|
|
<< Results[I].Rank;
|
|
|
|
if (Results[I].Hidden)
|
|
|
|
OS << " (Hidden)";
|
2009-09-21 20:56:56 +04:00
|
|
|
if (CodeCompletionString *CCS
|
|
|
|
= Results[I].CreateCodeCompletionString(SemaRef)) {
|
2009-09-19 02:15:54 +04:00
|
|
|
OS << " : " << CCS->getAsString();
|
|
|
|
delete CCS;
|
|
|
|
}
|
|
|
|
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
OS << '\n';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Result::RK_Keyword:
|
|
|
|
OS << Results[I].Keyword << " : " << Results[I].Rank << '\n';
|
|
|
|
break;
|
2009-10-30 19:50:04 +03:00
|
|
|
|
|
|
|
case Result::RK_Macro: {
|
|
|
|
OS << Results[I].Macro->getName() << " : " << Results[I].Rank;
|
|
|
|
if (CodeCompletionString *CCS
|
|
|
|
= Results[I].CreateCodeCompletionString(SemaRef)) {
|
|
|
|
OS << " : " << CCS->getAsString();
|
|
|
|
delete CCS;
|
|
|
|
}
|
|
|
|
OS << '\n';
|
|
|
|
break;
|
|
|
|
}
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Once we've printed the code-completion results, suppress remaining
|
|
|
|
// diagnostics.
|
|
|
|
// FIXME: Move this somewhere else!
|
2009-09-21 20:56:56 +04:00
|
|
|
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82166 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-18 01:32:03 +04:00
|
|
|
}
|
2009-09-23 04:16:58 +04:00
|
|
|
|
|
|
|
void
|
2009-11-13 11:58:20 +03:00
|
|
|
PrintingCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
|
|
|
|
unsigned CurrentArg,
|
2009-09-23 04:16:58 +04:00
|
|
|
OverloadCandidate *Candidates,
|
|
|
|
unsigned NumCandidates) {
|
|
|
|
for (unsigned I = 0; I != NumCandidates; ++I) {
|
2009-09-23 04:34:09 +04:00
|
|
|
if (CodeCompletionString *CCS
|
|
|
|
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
|
2009-10-10 02:16:47 +04:00
|
|
|
OS << "OVERLOAD: " << CCS->getAsString() << "\n";
|
2009-09-23 04:34:09 +04:00
|
|
|
delete CCS;
|
2009-09-23 04:16:58 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Once we've printed the code-completion results, suppress remaining
|
|
|
|
// diagnostics.
|
|
|
|
// FIXME: Move this somewhere else!
|
|
|
|
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
|
|
|
|
}
|
2009-11-07 03:00:49 +03:00
|
|
|
|
|
|
|
void
|
2009-11-13 11:58:20 +03:00
|
|
|
CIndexCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &SemaRef,
|
|
|
|
Result *Results,
|
2009-11-07 03:00:49 +03:00
|
|
|
unsigned NumResults) {
|
|
|
|
// Print the results.
|
|
|
|
for (unsigned I = 0; I != NumResults; ++I) {
|
|
|
|
OS << "COMPLETION:" << Results[I].Rank << ":";
|
|
|
|
switch (Results[I].Kind) {
|
|
|
|
case Result::RK_Declaration:
|
|
|
|
if (RecordDecl *Record = dyn_cast<RecordDecl>(Results[I].Declaration)) {
|
|
|
|
if (Record->isStruct())
|
|
|
|
OS << "Struct:";
|
|
|
|
else if (Record->isUnion())
|
|
|
|
OS << "Union:";
|
|
|
|
else
|
|
|
|
OS << "Class:";
|
|
|
|
} else if (ObjCMethodDecl *Method
|
|
|
|
= dyn_cast<ObjCMethodDecl>(Results[I].Declaration)) {
|
|
|
|
if (Method->isInstanceMethod())
|
|
|
|
OS << "ObjCInstanceMethod:";
|
|
|
|
else
|
|
|
|
OS << "ObjCClassMethod:";
|
|
|
|
} else {
|
|
|
|
OS << Results[I].Declaration->getDeclKindName() << ":";
|
|
|
|
}
|
|
|
|
if (CodeCompletionString *CCS
|
|
|
|
= Results[I].CreateCodeCompletionString(SemaRef)) {
|
|
|
|
CCS->Serialize(OS);
|
|
|
|
delete CCS;
|
|
|
|
} else {
|
|
|
|
OS << "<typed-text>"
|
|
|
|
<< Results[I].Declaration->getNameAsString()
|
|
|
|
<< "</>";
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << '\n';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Result::RK_Keyword:
|
|
|
|
OS << "Keyword:<typed-text>" << Results[I].Keyword << "</>\n";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Result::RK_Macro: {
|
|
|
|
OS << "Macro:";
|
|
|
|
if (CodeCompletionString *CCS
|
|
|
|
= Results[I].CreateCodeCompletionString(SemaRef)) {
|
|
|
|
CCS->Serialize(OS);
|
|
|
|
delete CCS;
|
|
|
|
} else {
|
|
|
|
OS << "<typed-text>" << Results[I].Macro->getName() << "</>";
|
|
|
|
}
|
|
|
|
OS << '\n';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Once we've printed the code-completion results, suppress remaining
|
|
|
|
// diagnostics.
|
|
|
|
// FIXME: Move this somewhere else!
|
|
|
|
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-11-13 11:58:20 +03:00
|
|
|
CIndexCodeCompleteConsumer::ProcessOverloadCandidates(Sema &SemaRef,
|
|
|
|
unsigned CurrentArg,
|
2009-11-07 03:00:49 +03:00
|
|
|
OverloadCandidate *Candidates,
|
|
|
|
unsigned NumCandidates) {
|
|
|
|
for (unsigned I = 0; I != NumCandidates; ++I) {
|
|
|
|
if (CodeCompletionString *CCS
|
|
|
|
= Candidates[I].CreateSignatureString(CurrentArg, SemaRef)) {
|
|
|
|
OS << "OVERLOAD:";
|
|
|
|
CCS->Serialize(OS);
|
|
|
|
OS << '\n';
|
|
|
|
delete CCS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Once we've printed the code-completion results, suppress remaining
|
|
|
|
// diagnostics.
|
|
|
|
// FIXME: Move this somewhere else!
|
|
|
|
SemaRef.PP.getDiagnostics().setSuppressAllDiagnostics();
|
|
|
|
}
|