2016-05-23 37 views
7

Próbuję utworzyć wirtualne pliki dla kodowania w klangu. Niestety moja aplikacja uległa awarii. Mam następującą konfigurację:jak utworzyć wirtualny plik w klangu dla kodowania-dekompozycji

auto createVirtualFile = [](
    clang::CompilerInstance& ci, 
    std::string name, 
    llvm::StringRef input 
) { 
    std::unique_ptr<llvm::MemoryBuffer> 
    MB(llvm::MemoryBuffer::getMemBuffer(input, name)); 
    return std::move(MB); 
}; 

Gdy plik jest tworzony i skonfigurować CodeCompletConsumer:

auto setupCodeComplete = [](
    clang::CompilerInstance& ci, 
    std::string File, 
    int Line, 
    int Column 
) { 
    auto& F = ci.getFrontendOpts(); 
    F.CodeCompletionAt.FileName = File; 
    F.CodeCompletionAt.Line = Line; 
    F.CodeCompletionAt.Column = Column; 
    clang::FrontendInputFile FrontFile(File, clang::IK_CXX); 
    //F.Inputs.push_back(FrontFile); 
    ci.createCodeCompletionConsumer(); 
    return FrontFile; 
}; 

I powoływać się na te dwie funkcje w następujący sposób i wykonać składni tylko czynność:

auto runCodeCompleteAt = [] (
    clang::CompilerInstance& ci, 
    std::string Filename, 
    std::string Code, 
    int Line, 
    int Column 
) { 
    auto fid = createVirtualFile(ci, Filename, Code); 
    auto File = setupCodeComplete(ci, Filename, Line, Column); 
    clang::SyntaxOnlyAction Act; 
    if (Act.BeginSourceFile(ci, File)) { 
    Act.Execute(); // segfault 
    Act.EndSourceFile(); 
    } 
}; 

auto runExample = [](auto& ci){ 
    runCodeCompleterAt(ci, "test.cpp", "std::cou", 1, 7); 
} 

Doceniam wszelkie wskazówki.

+0

[OT] std :: move w "return std :: move (MB);" powinno zostać usunięte. (zabrania tylko RVO). – Jarod42

+1

[OT] MB to unique_ptr, czy nie powinienem otwarcie mówić o przenoszeniu własności? – Gaetano

+1

Spójrz na [kiedy-należy-stdmove-należy użyć-na-funkcji-wartość-zwrotu] (http://stackoverflow.com/questions/14856344/when-should-stdmove-be-used-on-a -funkcja-wartość-zwrotu) – Jarod42

Odpowiedz

3

Problem polega na tym, że można dodać llvm::MemoryBuffer do clang::FrontendInputFile, clang::SyntaxOnlyAction nie akceptuje takiego wejścia, spowoduje to błąd asercji. Jak już powiedziałem w previous answer, możesz zajrzeć do ASTUnit::CodeComplete w lib/Frontend/ASTUnit.cpp.

Właściwie można użyć remappedFiles powiązać nazwę pliku z bufora:

int main() 
{ 
    unsigned Line = 2; 
    unsigned Column = 13; 
    clang::CompilerInstance ci; 
    llvm::StringRef codeStr("void MyFoo() {}\nint main() {My return 0}"); 

    // Just a dummy filename, the file even doesnt' exist. 
    std::string Filename("virtualFile.cpp"); 
    std::unique_ptr<llvm::MemoryBuffer> MB(llvm::MemoryBuffer::getMemBuffer(codeStr, Filename)); 

    // 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)); 

    clang::PreprocessorOptions& preprocessorOpts = ci.getPreprocessorOpts(); 
    preprocessorOpts.clearRemappedFiles(); 
    preprocessorOpts.addRemappedFile(Filename, MB.release()); 

    // Execute 
    clang::SyntaxOnlyAction Act; 
    if (Act.BeginSourceFile(ci, ci.getFrontendOpts().Inputs[0])) { 
     Act.Execute(); 
     Act.EndSourceFile(); 
    } 
} 

Wyjście zawiera COMPLETION: 50 Decl : MyFoo : [#void#]MyFoo().

uzyskać tę odpowiedź z segmentu kodu

PreprocessorOpts.clearRemappedFiles(); 
    PreprocessorOpts.RetainRemappedFileBuffers = true; 
    for (const auto &RemappedFile : RemappedFiles) { 
    PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second); 
    OwnedBuffers.push_back(RemappedFile.second); 
    } 

w ASTUnit::CodeComplete.

Uważam, że warto przeczytać AugmentedCodeCompleteConsumer, aby skorzystać z tych wskazówek dotyczących zakończenia.