Cling patch for code completion.
This commit is contained in:
parent
8ef4931a12
commit
cc5da51f21
@ -62,6 +62,12 @@ namespace cling {
|
|||||||
///
|
///
|
||||||
unsigned CheckPointerValidity : 1;
|
unsigned CheckPointerValidity : 1;
|
||||||
|
|
||||||
|
///\brief Offset into the input line to enable the setting of the
|
||||||
|
/// code completion point.
|
||||||
|
/// -1 diasables code completion.
|
||||||
|
///
|
||||||
|
int CodeCompletionOffset = -1;
|
||||||
|
|
||||||
CompilationOptions() {
|
CompilationOptions() {
|
||||||
DeclarationExtraction = 0;
|
DeclarationExtraction = 0;
|
||||||
ValuePrinting = VPDisabled;
|
ValuePrinting = VPDisabled;
|
||||||
@ -84,7 +90,8 @@ namespace cling {
|
|||||||
CodeGeneration == Other.CodeGeneration &&
|
CodeGeneration == Other.CodeGeneration &&
|
||||||
CodeGenerationForModule == Other.CodeGenerationForModule &&
|
CodeGenerationForModule == Other.CodeGenerationForModule &&
|
||||||
IgnorePromptDiags == Other.IgnorePromptDiags &&
|
IgnorePromptDiags == Other.IgnorePromptDiags &&
|
||||||
CheckPointerValidity == Other.CheckPointerValidity;
|
CheckPointerValidity == Other.CheckPointerValidity &&
|
||||||
|
CodeCompletionOffset == Other.CodeCompletionOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(CompilationOptions Other) const {
|
bool operator!=(CompilationOptions Other) const {
|
||||||
@ -97,7 +104,8 @@ namespace cling {
|
|||||||
CodeGeneration != Other.CodeGeneration ||
|
CodeGeneration != Other.CodeGeneration ||
|
||||||
CodeGenerationForModule != Other.CodeGenerationForModule ||
|
CodeGenerationForModule != Other.CodeGenerationForModule ||
|
||||||
IgnorePromptDiags != Other.IgnorePromptDiags ||
|
IgnorePromptDiags != Other.IgnorePromptDiags ||
|
||||||
CheckPointerValidity != Other.CheckPointerValidity;
|
CheckPointerValidity != Other.CheckPointerValidity ||
|
||||||
|
CodeCompletionOffset != Other.CodeCompletionOffset;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // end namespace cling
|
} // end namespace cling
|
||||||
|
@ -303,7 +303,7 @@ namespace cling {
|
|||||||
///\param[in] llvmdir - ???
|
///\param[in] llvmdir - ???
|
||||||
///\param[in] noRuntime - flag to control the presence of runtime universe
|
///\param[in] noRuntime - flag to control the presence of runtime universe
|
||||||
///
|
///
|
||||||
Interpreter(Interpreter &parentInterpreter,int argc, const char* const *argv,
|
Interpreter(const Interpreter &parentInterpreter,int argc, const char* const *argv,
|
||||||
const char* llvmdir = 0, bool noRuntime = true);
|
const char* llvmdir = 0, bool noRuntime = true);
|
||||||
|
|
||||||
virtual ~Interpreter();
|
virtual ~Interpreter();
|
||||||
@ -467,6 +467,18 @@ namespace cling {
|
|||||||
///
|
///
|
||||||
CompilationResult parseForModule(const std::string& input);
|
CompilationResult parseForModule(const std::string& input);
|
||||||
|
|
||||||
|
///\brief Code completes user input.
|
||||||
|
///
|
||||||
|
/// The interface circumvents the most of the extra work necessary to
|
||||||
|
/// code complete code.
|
||||||
|
///
|
||||||
|
/// @param[in] input - The input containing the string to be completed.
|
||||||
|
/// @param[out] T - The cling::Transaction of the input
|
||||||
|
///
|
||||||
|
///\returns Whether the operation was fully successful.
|
||||||
|
///
|
||||||
|
CompilationResult codeComplete(const std::string& input, unsigned offset);
|
||||||
|
|
||||||
///\brief Compiles input line, which doesn't contain statements.
|
///\brief Compiles input line, which doesn't contain statements.
|
||||||
///
|
///
|
||||||
/// The interface circumvents the most of the extra work necessary to
|
/// The interface circumvents the most of the extra work necessary to
|
||||||
|
@ -30,6 +30,7 @@ namespace clang {
|
|||||||
class Token;
|
class Token;
|
||||||
class FileEntry;
|
class FileEntry;
|
||||||
class Module;
|
class Module;
|
||||||
|
class CodeCompleteConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace cling {
|
namespace cling {
|
||||||
@ -161,6 +162,13 @@ namespace cling {
|
|||||||
/// for instance when throwing interpreter exceptions.
|
/// for instance when throwing interpreter exceptions.
|
||||||
virtual void PrintStackTrace() {}
|
virtual void PrintStackTrace() {}
|
||||||
|
|
||||||
|
///\brief Cling creates the code complete consumer for its child interp.
|
||||||
|
virtual void CreateCodeCompleteConsumer(Interpreter* child) const;
|
||||||
|
|
||||||
|
///\brief Get the resukts of the code completion.
|
||||||
|
virtual void GetCompletionResults(Interpreter* child,
|
||||||
|
std::vector<std::string>&) const;
|
||||||
|
|
||||||
///\brief DynamicScopes only! Set to true if it is currently evaluating a
|
///\brief DynamicScopes only! Set to true if it is currently evaluating a
|
||||||
/// dynamic expr.
|
/// dynamic expr.
|
||||||
///
|
///
|
||||||
|
@ -109,6 +109,8 @@ namespace cling {
|
|||||||
|
|
||||||
const Interpreter& getInterpreter() const { return m_Interp; }
|
const Interpreter& getInterpreter() const { return m_Interp; }
|
||||||
|
|
||||||
|
Interpreter& getInterpreter() { return m_Interp; }
|
||||||
|
|
||||||
///\brief Get the output stream used by the MetaProcessor for its output.
|
///\brief Get the output stream used by the MetaProcessor for its output.
|
||||||
/// (in contrast to the interpreter's output which is redirected using
|
/// (in contrast to the interpreter's output which is redirected using
|
||||||
/// setStdStream()).
|
/// setStdStream()).
|
||||||
|
@ -3,9 +3,37 @@
|
|||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class ClingASTImporter : public ASTImporter {
|
||||||
|
private:
|
||||||
|
cling::ASTImportSource& m_source;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ClingASTImporter(ASTContext &ToContext, FileManager &ToFileManager,
|
||||||
|
ASTContext &FromContext, FileManager &FromFileManager,
|
||||||
|
bool MinimalImport, cling::ASTImportSource& source) :
|
||||||
|
ASTImporter(ToContext, ToFileManager, FromContext,
|
||||||
|
FromFileManager, MinimalImport), m_source(source) {}
|
||||||
|
|
||||||
|
Decl *Imported(Decl *From, Decl *To) override {
|
||||||
|
ASTImporter::Imported(From, To);
|
||||||
|
|
||||||
|
// Put the name of the Decl imported with the
|
||||||
|
// DeclarationName coming from the parent, in my map.
|
||||||
|
if (DeclContext *declContextParent = llvm::dyn_cast<DeclContext>(From)) {
|
||||||
|
DeclContext *declContextChild = llvm::dyn_cast<DeclContext>(To);
|
||||||
|
m_source.addToDeclContext(declContextChild, declContextParent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return To;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
namespace cling {
|
namespace cling {
|
||||||
|
|
||||||
ASTImportSource::ASTImportSource(cling::Interpreter *parent_interpreter,
|
ASTImportSource::ASTImportSource(const cling::Interpreter *parent_interpreter,
|
||||||
cling::Interpreter *child_interpreter) :
|
cling::Interpreter *child_interpreter) :
|
||||||
m_parent_Interp(parent_interpreter), m_child_Interp(child_interpreter) {
|
m_parent_Interp(parent_interpreter), m_child_Interp(child_interpreter) {
|
||||||
|
|
||||||
@ -88,10 +116,10 @@ namespace cling {
|
|||||||
FileManager &child_FM = m_child_Interp->getCI()->getFileManager();
|
FileManager &child_FM = m_child_Interp->getCI()->getFileManager();
|
||||||
FileManager &parent_FM = m_parent_Interp->getCI()->getFileManager();
|
FileManager &parent_FM = m_parent_Interp->getCI()->getFileManager();
|
||||||
|
|
||||||
// Clang's ASTImporter
|
// Cling's ASTImporter
|
||||||
ASTImporter importer(to_ASTContext, child_FM,
|
ClingASTImporter importer(to_ASTContext, child_FM,
|
||||||
from_ASTContext, parent_FM,
|
from_ASTContext, parent_FM,
|
||||||
/*MinimalImport : ON*/ true);
|
/*MinimalImport : ON*/ true, *this);
|
||||||
|
|
||||||
for (DeclContext::lookup_iterator I = lookup_result.begin(),
|
for (DeclContext::lookup_iterator I = lookup_result.begin(),
|
||||||
E = lookup_result.end();
|
E = lookup_result.end();
|
||||||
@ -120,6 +148,8 @@ namespace cling {
|
|||||||
bool ASTImportSource::FindExternalVisibleDeclsByName(
|
bool ASTImportSource::FindExternalVisibleDeclsByName(
|
||||||
const DeclContext *childCurrentDeclContext, DeclarationName childDeclName) {
|
const DeclContext *childCurrentDeclContext, DeclarationName childDeclName) {
|
||||||
|
|
||||||
|
assert(childDeclName && "Child Decl name is empty");
|
||||||
|
|
||||||
assert(childCurrentDeclContext->hasExternalVisibleStorage() &&
|
assert(childCurrentDeclContext->hasExternalVisibleStorage() &&
|
||||||
"DeclContext has no visible decls in storage");
|
"DeclContext has no visible decls in storage");
|
||||||
|
|
||||||
@ -132,21 +162,24 @@ namespace cling {
|
|||||||
} else {
|
} else {
|
||||||
// Get the identifier info from the parent interpreter
|
// Get the identifier info from the parent interpreter
|
||||||
// for this Name.
|
// for this Name.
|
||||||
llvm::StringRef name(childDeclName.getAsString());
|
std::string name = childDeclName.getAsString();
|
||||||
IdentifierTable &parentIdentifierTable =
|
if (!name.empty()) {
|
||||||
m_parent_Interp->getCI()->getASTContext().Idents;
|
llvm::StringRef nameRef(name);
|
||||||
IdentifierInfo &parentIdentifierInfo = parentIdentifierTable.get(name);
|
IdentifierTable &parentIdentifierTable =
|
||||||
DeclarationName parentDeclNameTemp(&parentIdentifierInfo);
|
m_parent_Interp->getCI()->getASTContext().Idents;
|
||||||
parentDeclName = parentDeclNameTemp;
|
IdentifierInfo &parentIdentifierInfo =
|
||||||
|
parentIdentifierTable.get(nameRef);
|
||||||
|
parentDeclName = DeclarationName(&parentIdentifierInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search in the map of the stored Decl Contexts for this
|
// Search in the map of the stored Decl Contexts for this
|
||||||
// Decl Context.
|
// Decl Context.
|
||||||
std::map<const clang::DeclContext *, clang::DeclContext *>::iterator I;
|
std::map<const clang::DeclContext *, clang::DeclContext *>::iterator I;
|
||||||
|
// If childCurrentDeclContext was found before and is already in the map,
|
||||||
|
// then do the lookup using the stored pointer.
|
||||||
if ((I = m_DeclContexts_map.find(childCurrentDeclContext))
|
if ((I = m_DeclContexts_map.find(childCurrentDeclContext))
|
||||||
!= m_DeclContexts_map.end()) {
|
!= m_DeclContexts_map.end()) {
|
||||||
// If childCurrentDeclContext was found before and is already in the map,
|
|
||||||
// then do the lookup using the stored pointer.
|
|
||||||
DeclContext *parentDeclContext = I->second;
|
DeclContext *parentDeclContext = I->second;
|
||||||
|
|
||||||
Decl *fromDeclContext = Decl::castFromDeclContext(parentDeclContext);
|
Decl *fromDeclContext = Decl::castFromDeclContext(parentDeclContext);
|
||||||
@ -168,4 +201,55 @@ namespace cling {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///\brief Make available to child all decls in parent's decl context
|
||||||
|
/// that corresponds to child decl context.
|
||||||
|
void ASTImportSource::completeVisibleDeclsMap(
|
||||||
|
const clang::DeclContext *childDeclContext) {
|
||||||
|
assert (childDeclContext && "No child decl context!");
|
||||||
|
|
||||||
|
if (!childDeclContext->hasExternalVisibleStorage())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Search in the map of the stored Decl Contexts for this
|
||||||
|
// Decl Context.
|
||||||
|
std::map<const clang::DeclContext *, clang::DeclContext *>::iterator I;
|
||||||
|
// If childCurrentDeclContext was found before and is already in the map,
|
||||||
|
// then do the lookup using the stored pointer.
|
||||||
|
if ((I = m_DeclContexts_map.find(childDeclContext))
|
||||||
|
!= m_DeclContexts_map.end()) {
|
||||||
|
|
||||||
|
DeclContext *parentDeclContext = I->second;
|
||||||
|
|
||||||
|
Decl *fromDeclContext = Decl::castFromDeclContext(parentDeclContext);
|
||||||
|
ASTContext &from_ASTContext = fromDeclContext->getASTContext();
|
||||||
|
|
||||||
|
Decl *toDeclContext = Decl::castFromDeclContext(childDeclContext);
|
||||||
|
ASTContext &to_ASTContext = toDeclContext->getASTContext();
|
||||||
|
|
||||||
|
// Prepare to import the Decl(Context) we found in the
|
||||||
|
// child interpreter by getting the file managers from
|
||||||
|
// each interpreter.
|
||||||
|
FileManager &child_FM = m_child_Interp->getCI()->getFileManager();
|
||||||
|
FileManager &parent_FM = m_parent_Interp->getCI()->getFileManager();
|
||||||
|
|
||||||
|
// Cling's ASTImporter
|
||||||
|
ClingASTImporter importer(to_ASTContext, child_FM,
|
||||||
|
from_ASTContext, parent_FM,
|
||||||
|
/*MinimalImport : ON*/ true, *this);
|
||||||
|
|
||||||
|
for (DeclContext::decl_iterator I_decl = parentDeclContext->decls_begin(),
|
||||||
|
E_decl = parentDeclContext->decls_end(); I_decl != E_decl; ++I_decl) {
|
||||||
|
if (NamedDecl* parentNamedDecl = llvm::dyn_cast<NamedDecl>(*I_decl)) {
|
||||||
|
DeclarationName newDeclName = parentNamedDecl->getDeclName();
|
||||||
|
ImportDecl(parentNamedDecl, importer, newDeclName, newDeclName,
|
||||||
|
childDeclContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const_cast<DeclContext *>(childDeclContext)->
|
||||||
|
setHasExternalVisibleStorage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace cling
|
} // end namespace cling
|
||||||
|
@ -35,7 +35,7 @@ namespace cling {
|
|||||||
class ASTImportSource : public clang::ExternalASTSource {
|
class ASTImportSource : public clang::ExternalASTSource {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cling::Interpreter *m_parent_Interp;
|
const cling::Interpreter *m_parent_Interp;
|
||||||
cling::Interpreter *m_child_Interp;
|
cling::Interpreter *m_child_Interp;
|
||||||
|
|
||||||
clang::Sema *m_Sema;
|
clang::Sema *m_Sema;
|
||||||
@ -56,11 +56,13 @@ namespace cling {
|
|||||||
std::map <clang::DeclarationName, clang::DeclarationName > m_DeclName_map;
|
std::map <clang::DeclarationName, clang::DeclarationName > m_DeclName_map;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ASTImportSource(cling::Interpreter *parent_interpreter,
|
ASTImportSource(const cling::Interpreter *parent_interpreter,
|
||||||
cling::Interpreter *child_interpreter);
|
cling::Interpreter *child_interpreter);
|
||||||
|
|
||||||
~ASTImportSource() { };
|
~ASTImportSource() { };
|
||||||
|
|
||||||
|
void completeVisibleDeclsMap(const clang::DeclContext *DC) override;
|
||||||
|
|
||||||
bool FindExternalVisibleDeclsByName(const clang::DeclContext *childCurrentDeclContext,
|
bool FindExternalVisibleDeclsByName(const clang::DeclContext *childCurrentDeclContext,
|
||||||
clang::DeclarationName childDeclName) override;
|
clang::DeclarationName childDeclName) override;
|
||||||
|
|
||||||
@ -86,6 +88,11 @@ namespace cling {
|
|||||||
clang::DeclarationName &childDeclName,
|
clang::DeclarationName &childDeclName,
|
||||||
clang::DeclarationName &parentDeclName,
|
clang::DeclarationName &parentDeclName,
|
||||||
const clang::DeclContext *childCurrentDeclContext);
|
const clang::DeclContext *childCurrentDeclContext);
|
||||||
|
|
||||||
|
void addToDeclContext(clang::DeclContext *child,
|
||||||
|
clang::DeclContext *parent) {
|
||||||
|
m_DeclContexts_map[child] = parent;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // end namespace cling
|
} // end namespace cling
|
||||||
#endif //CLING_ASTIMPORTSOURCE_H
|
#endif //CLING_ASTIMPORTSOURCE_H
|
||||||
|
@ -26,6 +26,7 @@ add_cling_library(clingInterpreter
|
|||||||
CheckEmptyTransactionTransformer.cpp
|
CheckEmptyTransactionTransformer.cpp
|
||||||
CIFactory.cpp
|
CIFactory.cpp
|
||||||
ClangInternalState.cpp
|
ClangInternalState.cpp
|
||||||
|
ClingCodeCompleteConsumer.cpp
|
||||||
ClingPragmas.cpp
|
ClingPragmas.cpp
|
||||||
DeclCollector.cpp
|
DeclCollector.cpp
|
||||||
DeclExtractor.cpp
|
DeclExtractor.cpp
|
||||||
|
@ -713,10 +713,20 @@ namespace cling {
|
|||||||
SourceLocation NewLoc = getLastMemoryBufferEndLoc().getLocWithOffset(1);
|
SourceLocation NewLoc = getLastMemoryBufferEndLoc().getLocWithOffset(1);
|
||||||
|
|
||||||
llvm::MemoryBuffer* MBNonOwn = MB.get();
|
llvm::MemoryBuffer* MBNonOwn = MB.get();
|
||||||
// Create FileID for the current buffer
|
|
||||||
FileID FID = SM.createFileID(std::move(MB), SrcMgr::C_User,
|
// Create FileEntry and FileID for the current buffer
|
||||||
/*LoadedID*/0,
|
const clang::FileEntry* FE
|
||||||
/*LoadedOffset*/0, NewLoc);
|
= SM.getFileManager().getVirtualFile("vfile for " + source_name.str(),
|
||||||
|
InputSize, 0 /* mod time*/);
|
||||||
|
SM.overrideFileContents(FE, std::move(MB));
|
||||||
|
FileID FID = SM.createFileID(FE, NewLoc, SrcMgr::C_User);
|
||||||
|
|
||||||
|
// Set the code completion point if completion is enabled.
|
||||||
|
if (CO.CodeCompletionOffset != -1) {
|
||||||
|
printf("Is it really the completion point?\n");
|
||||||
|
PP.SetCodeCompletionPoint(FE, 1, 45 + CO.CodeCompletionOffset);
|
||||||
|
m_Interpreter->unload(1);
|
||||||
|
}
|
||||||
|
|
||||||
m_MemoryBuffers.push_back(std::make_pair(MBNonOwn, FID));
|
m_MemoryBuffers.push_back(std::make_pair(MBNonOwn, FID));
|
||||||
|
|
||||||
@ -767,6 +777,11 @@ namespace cling {
|
|||||||
m_Consumer->HandleTopLevelDecl(ADecl.get());
|
m_Consumer->HandleTopLevelDecl(ADecl.get());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (CO.CodeCompletionOffset != -1) {
|
||||||
|
assert(PP.isCodeCompletionReached() && "Code completion set but not reached!");
|
||||||
|
return kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef LLVM_ON_WIN32
|
#ifdef LLVM_ON_WIN32
|
||||||
// Microsoft-specific:
|
// Microsoft-specific:
|
||||||
// Late parsed templates can leave unswallowed "macro"-like tokens.
|
// Late parsed templates can leave unswallowed "macro"-like tokens.
|
||||||
|
@ -237,7 +237,7 @@ namespace cling {
|
|||||||
///\brief Constructor for the child Interpreter.
|
///\brief Constructor for the child Interpreter.
|
||||||
/// Passing the parent Interpreter as an argument.
|
/// Passing the parent Interpreter as an argument.
|
||||||
///
|
///
|
||||||
Interpreter::Interpreter(Interpreter &parentInterpreter, int argc,
|
Interpreter::Interpreter(const Interpreter &parentInterpreter, int argc,
|
||||||
const char* const *argv,
|
const char* const *argv,
|
||||||
const char* llvmdir /*= 0*/, bool noRuntime) :
|
const char* llvmdir /*= 0*/, bool noRuntime) :
|
||||||
Interpreter(argc, argv, llvmdir, noRuntime, /* isChildInterp */ true) {
|
Interpreter(argc, argv, llvmdir, noRuntime, /* isChildInterp */ true) {
|
||||||
@ -255,7 +255,7 @@ namespace cling {
|
|||||||
|
|
||||||
// Inform the Translation Unit Decl of I2 that it has to search somewhere
|
// Inform the Translation Unit Decl of I2 that it has to search somewhere
|
||||||
// else to find the declarations.
|
// else to find the declarations.
|
||||||
getCI()->getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage();
|
getCI()->getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage(true);
|
||||||
|
|
||||||
// Give my IncrementalExecutor a pointer to the Incremental executor of the
|
// Give my IncrementalExecutor a pointer to the Incremental executor of the
|
||||||
// parent Interpreter.
|
// parent Interpreter.
|
||||||
@ -639,6 +639,34 @@ namespace cling {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Interpreter::CompilationResult
|
||||||
|
Interpreter::codeComplete(const std::string& input, unsigned offset) {
|
||||||
|
|
||||||
|
CompilationOptions CO;
|
||||||
|
CO.DeclarationExtraction = 0;
|
||||||
|
CO.ValuePrinting = 0;
|
||||||
|
CO.ResultEvaluation = 0;
|
||||||
|
CO.DynamicScoping = isDynamicLookupEnabled();
|
||||||
|
CO.Debug = isPrintingDebug();
|
||||||
|
CO.CheckPointerValidity = 0;
|
||||||
|
CO.CodeCompletionOffset = offset;
|
||||||
|
|
||||||
|
|
||||||
|
std::string wrappedInput = input;
|
||||||
|
std::string wrapperName;
|
||||||
|
if (ShouldWrapInput(input))
|
||||||
|
WrapInput(wrappedInput, wrapperName);
|
||||||
|
|
||||||
|
StateDebuggerRAII stateDebugger(this);
|
||||||
|
|
||||||
|
// This triggers the FileEntry to be created and the completion
|
||||||
|
// point to be set in clang.
|
||||||
|
m_IncrParser->Parse(wrappedInput, CO);
|
||||||
|
|
||||||
|
return kSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
Interpreter::CompilationResult
|
Interpreter::CompilationResult
|
||||||
Interpreter::declare(const std::string& input, Transaction** T/*=0 */) {
|
Interpreter::declare(const std::string& input, Transaction** T/*=0 */) {
|
||||||
CompilationOptions CO;
|
CompilationOptions CO;
|
||||||
|
@ -9,9 +9,11 @@
|
|||||||
|
|
||||||
#include "cling/Interpreter/InterpreterCallbacks.h"
|
#include "cling/Interpreter/InterpreterCallbacks.h"
|
||||||
|
|
||||||
|
#include "cling/Interpreter/ClingCodeCompleteConsumer.h"
|
||||||
#include "cling/Interpreter/Interpreter.h"
|
#include "cling/Interpreter/Interpreter.h"
|
||||||
|
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
|
#include "clang/Sema/CodeCompleteConsumer.h"
|
||||||
#include "clang/Frontend/CompilerInstance.h"
|
#include "clang/Frontend/CompilerInstance.h"
|
||||||
#include "clang/Lex/Preprocessor.h"
|
#include "clang/Lex/Preprocessor.h"
|
||||||
#include "clang/Sema/Sema.h"
|
#include "clang/Sema/Sema.h"
|
||||||
@ -239,6 +241,27 @@ namespace cling {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterpreterCallbacks::CreateCodeCompleteConsumer(Interpreter* child) const {
|
||||||
|
ClingCodeCompleteConsumer* consumer = new ClingCodeCompleteConsumer(
|
||||||
|
m_Interpreter->getCI()->getFrontendOpts().CodeCompleteOpts,
|
||||||
|
llvm::outs());
|
||||||
|
CompilerInstance* childCI = child->getCI();
|
||||||
|
//codeCompletionCI will own consumer!
|
||||||
|
childCI->setCodeCompletionConsumer(consumer);
|
||||||
|
clang::Sema& childSemaRef = childCI->getSema();
|
||||||
|
childSemaRef.CodeCompleter = consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InterpreterCallbacks::GetCompletionResults(Interpreter* child,
|
||||||
|
std::vector<std::string>& completions) const {
|
||||||
|
// Which cast to use , fno-rtti
|
||||||
|
ClingCodeCompleteConsumer* consumer =
|
||||||
|
(ClingCodeCompleteConsumer*)(
|
||||||
|
child->getCI()->getSema().CodeCompleter);
|
||||||
|
if (consumer)
|
||||||
|
consumer->getCompletions(completions);
|
||||||
|
}
|
||||||
|
|
||||||
void InterpreterCallbacks::UpdateWithNewDecls(const DeclContext *DC,
|
void InterpreterCallbacks::UpdateWithNewDecls(const DeclContext *DC,
|
||||||
DeclarationName Name,
|
DeclarationName Name,
|
||||||
llvm::ArrayRef<NamedDecl*> Decls) {
|
llvm::ArrayRef<NamedDecl*> Decls) {
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
#include "clang/Basic/LangOptions.h"
|
#include "clang/Basic/LangOptions.h"
|
||||||
#include "clang/Frontend/CompilerInstance.h"
|
#include "clang/Frontend/CompilerInstance.h"
|
||||||
|
|
||||||
|
#include "ClingTabCompletion.h"
|
||||||
|
|
||||||
// Fragment copied from LLVM's raw_ostream.cpp
|
// Fragment copied from LLVM's raw_ostream.cpp
|
||||||
#if defined(HAVE_UNISTD_H)
|
#if defined(HAVE_UNISTD_H)
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
@ -118,6 +120,11 @@ namespace cling {
|
|||||||
std::unique_ptr<TerminalDisplay> D(TerminalDisplay::Create());
|
std::unique_ptr<TerminalDisplay> D(TerminalDisplay::Create());
|
||||||
TextInput TI(*R, *D, histfilePath.empty() ? 0 : histfilePath.c_str());
|
TextInput TI(*R, *D, histfilePath.empty() ? 0 : histfilePath.c_str());
|
||||||
|
|
||||||
|
// Inform text input about the code complete consumer
|
||||||
|
ClingTabCompletion* CompletionConsumer = new ClingTabCompletion(m_MetaProcessor->getInterpreter());
|
||||||
|
TI.SetCompletion(CompletionConsumer);
|
||||||
|
|
||||||
|
|
||||||
TI.SetPrompt("[cling]$ ");
|
TI.SetPrompt("[cling]$ ");
|
||||||
std::string line;
|
std::string line;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
Loading…
Reference in New Issue
Block a user