我有一个库,它使用并公开了一个clang :: CompilerInstance。 如何使用CompilerInstance获取代码完成建议?
基本上我正在寻找一个具有以下签名的函数:
vector<string> completeSnippet(
clang::CompilerInstance CI,
string codeSnippet,
int completeAtIndex
);
有什么想法吗?
提前致谢
答案 0 :(得分:4)
老实说,我没有弄清楚如何实施
vector<string> completeSnippet(
clang::CompilerInstance CI,
string codeSnippet,
int completeAtIndex
);
相反,我能提供的是
vector<std::string> completeSnippet(clang::CompilerInstance& ci,
const std::string& filename,
unsigned Line /* start from 1 */,
unsigned Column /* start from 1 */);
如果您不太关心性能,可以使用解决方法,可以将codeSnippet存储到文件中,然后传递文件名。
由于我不知道ci
的状态,例如,它是否有目标,我只是澄清主方法中的方法,您可以轻松地将其重构为函数。
int main()
{
std::string Filename("test.cpp");
unsigned Line = 7;
unsigned Column = 5;
clang::CompilerInstance ci;
// Create diagnostics and target
ci.createDiagnostics();
std::shared_ptr<clang::TargetOptions> to = std::make_shared<clang::TargetOptions>();
// clang -v
//to->Triple = "x86_64-pc-win32";
//to->Triple = "x86_64-apple-darwin";
to->Triple = "x86_64-apple-darwin15";
ci.setTarget(clang::TargetInfo::CreateTargetInfo(ci.getDiagnostics(), to));
// Create language options
clang::LangOptions &lo = ci.getLangOpts();
lo.CPlusPlus = true;
lo.CPlusPlus11 = true;
// Create code complete options
clang::CodeCompleteOptions cco;
cco.IncludeMacros = 0;
cco.IncludeCodePatterns = 1;
cco.IncludeGlobals = 1;
cco.IncludeBriefComments = 1;
// Set up the callback, I will go back to this callback class later
auto pCustomCodeCompleteConsumer = new CustomCodeCompleteConsumer(cco);
ci.setCodeCompletionConsumer(pCustomCodeCompleteConsumer);
// Set up code complete postions & file
// Until now I didn't find a way to pass in a string rather than a file name
clang::FrontendOptions& frontendOpts = ci.getFrontendOpts();
frontendOpts.CodeCompletionAt.FileName = Filename;
frontendOpts.CodeCompletionAt.Line = Line;
frontendOpts.CodeCompletionAt.Column = Column;
frontendOpts.Inputs.push_back(clang::FrontendInputFile(Filename, clang::InputKind::IK_CXX));
// Execute
clang::SyntaxOnlyAction Act;
if (Act.BeginSourceFile(ci, ci.getFrontendOpts().Inputs[0])) {
Act.Execute();
Act.EndSourceFile();
}
}
我从PrintingCodeCompleteConsumer
和Sema/CodeCompleteConsumer.cpp
中的Sema/CodeCompleteConsumer.h
复制了回调类的实现
class CustomCodeCompleteConsumer : public clang::CodeCompleteConsumer {
clang::CodeCompletionTUInfo CCTUInfo;
public:
CustomCodeCompleteConsumer(const clang::CodeCompleteOptions &CodeCompleteOpts)
: clang::CodeCompleteConsumer(CodeCompleteOpts, false), CCTUInfo(new clang::GlobalCodeCompletionAllocator) {}
void ProcessCodeCompleteResults(clang::Sema &SemaRef, clang::CodeCompletionContext Context,
clang::CodeCompletionResult *Results,
unsigned NumResults) override {
std::stable_sort(Results, Results + NumResults, [](auto& lhs, auto& rhs) {
return lhs.Priority > rhs.Priority;
});
using namespace clang;
for (unsigned I = 0; I != NumResults; ++I) {
std::string ccStr = "";
llvm::raw_string_ostream OS(ccStr);
OS << "COMPLETION: " << Results[I].Priority;
switch (Results[I].Kind) {
case CodeCompletionResult::RK_Declaration:
OS << "Decl : ";
OS << *Results[I].Declaration;
if (Results[I].Hidden)
OS << " (Hidden)";
if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef, Context,
getAllocator(),
CCTUInfo,
includeBriefComments())) {
OS << " : " << CCS->getAsString();
if (const char *BriefComment = CCS->getBriefComment())
OS << " : " << BriefComment;
}
OS << '\n';
break;
case CodeCompletionResult::RK_Keyword:
OS << "Keyword : ";
OS << Results[I].Keyword << '\n';
break;
case CodeCompletionResult::RK_Macro: {
OS << "Macro : ";
OS << Results[I].Macro->getName();
if (CodeCompletionString *CCS
= Results[I].CreateCodeCompletionString(SemaRef, Context,
getAllocator(),
CCTUInfo,
includeBriefComments())) {
OS << " : " << CCS->getAsString();
}
OS << '\n';
break;
}
case CodeCompletionResult::RK_Pattern: {
OS << "Pattern : "
<< Results[I].Pattern->getAsString() << '\n';
break;
}
}
OS.flush();
std::cout << ccStr;
}
}
void ProcessOverloadCandidates(clang::Sema &S, unsigned CurrentArg,
clang::OverloadCandidate *Candidates,
unsigned NumCandidates) {
}
clang::CodeCompletionAllocator &getAllocator() override {
return CCTUInfo.getAllocator();
}
clang::CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; }
};
我对原始ProcessCodeCompleteResults
做了一点改动,将信息输出到控制台。
我的头文件:
#define __STDC_CONSTANT_MACROS
#define __STDC_LIMIT_MACROS
#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendActions.h>
#include <clang/Lex/Preprocessor.h>
#include <clang/Basic/TargetOptions.h>
#include <clang/Basic/TargetInfo.h>
#include <clang/Basic/LangOptions.h>
#include <clang/Basic/SourceManager.h>
#include <clang/Basic/SourceLocation.h>
#include <clang/Basic/FileManager.h>
#include <clang/Sema/Sema.h>
#include <clang/Sema/CodeCompleteOptions.h>
#include <clang/Sema/CodeCompleteConsumer.h>
#include <clang/Parse/ParseAST.h>
#include <clang/AST/ASTContext.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/Decl.h>
#include <llvm/Support/raw_ostream.h>
#include <iostream>
剩下的问题:
假设我们有两个测试文件:
<强> test1.cpp 强>
void myFunc(int param) {
}
int main() {
int count = 5;
cou
return 0;
}
<强>测试2.cpp 强>
void myFunc(int param) {
}
int main() {
int count = 5;
myFunc
return 0;
}
lang++ -cc1 -fsyntax-only -code-completion-at test2.cpp:7:4 test2.cpp
并clang++ -cc1 -fsyntax-only -code-completion-at test1.cpp:7:4 test1.cpp
输出相同的内容:
COMPLETION: __FUNCTION__
COMPLETION: __PRETTY_FUNCTION__
COMPLETION: _Nonnull
COMPLETION: _Null_unspecified
COMPLETION: _Nullable
COMPLETION: bool
COMPLETION: char
COMPLETION: class
COMPLETION: const
COMPLETION: Pattern : const_cast<<#type#>>(<#expression#>)
COMPLETION: count : [#int#]count
COMPLETION: Pattern : [#void#]delete <#expression#>
COMPLETION: Pattern : [#void#]delete [] <#expression#>
COMPLETION: double
COMPLETION: Pattern : dynamic_cast<<#type#>>(<#expression#>)
COMPLETION: enum
COMPLETION: extern
COMPLETION: Pattern : [#bool#]false
COMPLETION: float
COMPLETION: Pattern : goto <#label#>
COMPLETION: int
COMPLETION: long
COMPLETION: main : [#int#]main()
COMPLETION: myFunc : [#void#]myFunc(<#int param#>)
COMPLETION: Pattern : new <#type#>(<#expressions#>)
COMPLETION: Pattern : new <#type#>[<#size#>](<#expressions#>)
COMPLETION: operator
COMPLETION: Pattern : reinterpret_cast<<#type#>>(<#expression#>)
COMPLETION: Pattern : return <#expression#>
COMPLETION: short
COMPLETION: signed
COMPLETION: Pattern : [#size_t#]sizeof(<#expression-or-type#>)
COMPLETION: static
COMPLETION: Pattern : static_cast<<#type#>>(<#expression#>)
COMPLETION: struct
COMPLETION: Pattern : [#bool#]true
COMPLETION: Pattern : typedef <#type#> <#name#>
COMPLETION: Pattern : [#std::type_info#]typeid(<#expression-or-type#>)
COMPLETION: Pattern : typename <#qualifier#>::<#name#>
COMPLETION: Pattern : typeof <#expression#>
COMPLETION: Pattern : typeof(<#type#>)
COMPLETION: union
COMPLETION: unsigned
COMPLETION: Pattern : using namespace <#identifier#>
COMPLETION: void
COMPLETION: volatile
COMPLETION: wchar_t
与我的实施相同:
COMPLETION: 65 Keyword : __PRETTY_FUNCTION__
COMPLETION: 65 Keyword : __FUNCTION__
COMPLETION: 65 Keyword : __func__
COMPLETION: 50 Decl : myFunc : [#void#]myFunc(<#int param#>)
COMPLETION: 50 Decl : main : [#int#]main()
COMPLETION: 50 Keyword : short
COMPLETION: 50 Keyword : long
COMPLETION: 50 Keyword : signed
COMPLETION: 50 Keyword : unsigned
COMPLETION: 50 Keyword : void
COMPLETION: 50 Keyword : char
COMPLETION: 50 Keyword : int
COMPLETION: 50 Keyword : float
COMPLETION: 50 Keyword : double
COMPLETION: 50 Keyword : enum
COMPLETION: 50 Keyword : struct
COMPLETION: 50 Keyword : union
COMPLETION: 50 Keyword : const
COMPLETION: 50 Keyword : volatile
COMPLETION: 50 Keyword : bool
COMPLETION: 50 Keyword : class
COMPLETION: 50 Keyword : wchar_t
COMPLETION: 50 Keyword : auto
COMPLETION: 50 Keyword : char16_t
COMPLETION: 50 Keyword : char32_t
COMPLETION: 50 Keyword : _Nonnull
COMPLETION: 50 Keyword : _Null_unspecified
COMPLETION: 50 Keyword : _Nullable
COMPLETION: 40 Pattern : typedef <#type#> <#name#>
COMPLETION: 40 Pattern : if(<#condition#>){<#statements#>
}
COMPLETION: 40 Pattern : switch(<#condition#>){
}
COMPLETION: 40 Pattern : while(<#condition#>){<#statements#>
}
COMPLETION: 40 Pattern : do{<#statements#>
}while(<#expression#>)
COMPLETION: 40 Pattern : for(<#init-statement#>;<#condition#>;<#inc-expression#>){
<#statements#>
}
COMPLETION: 40 Pattern : return <#expression#>
COMPLETION: 40 Pattern : goto <#label#>
COMPLETION: 40 Pattern : using namespace <#identifier#>
COMPLETION: 40 Keyword : extern
COMPLETION: 40 Keyword : static
COMPLETION: 40 Pattern : [#bool#]true
COMPLETION: 40 Pattern : [#bool#]false
COMPLETION: 40 Pattern : dynamic_cast<<#type#>>(<#expression#>)
COMPLETION: 40 Pattern : static_cast<<#type#>>(<#expression#>)
COMPLETION: 40 Pattern : reinterpret_cast<<#type#>>(<#expression#>)
COMPLETION: 40 Pattern : const_cast<<#type#>>(<#expression#>)
COMPLETION: 40 Pattern : [#std::type_info#]typeid(<#expression-or-type#>)
COMPLETION: 40 Pattern : new <#type#>(<#expressions#>)
COMPLETION: 40 Pattern : new <#type#>[<#size#>](<#expressions#>)
COMPLETION: 40 Pattern : [#void#]delete <#expression#>
COMPLETION: 40 Pattern : [#void#]delete [] <#expression#>
COMPLETION: 40 Pattern : [#std::nullptr_t#]nullptr
COMPLETION: 40 Pattern : [#size_t#]alignof(<#type#>)
COMPLETION: 40 Pattern : [#bool#]noexcept(<#expression#>)
COMPLETION: 40 Pattern : [#size_t#]sizeof...(<#parameter-pack#>)
COMPLETION: 40 Pattern : [#size_t#]sizeof(<#expression-or-type#>)
COMPLETION: 40 Pattern : typename <#qualifier#>::<#name#>
COMPLETION: 40 Pattern : decltype(<#expression#>)
COMPLETION: 40 Pattern : typeof <#expression#>
COMPLETION: 40 Pattern : typeof(<#type#>)
COMPLETION: 40 Keyword : operator
COMPLETION: 34 Decl : count : [#int#]count
虽然我已按priority
您可以参考ASTUnit::CodeComplete
中的AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults
和lib/Frontend/ASTUnit.cpp
,详细了解clang_codeCompleteAt
的逻辑