示例#1
0
bool
ClangExpressionParser::RewriteExpression(DiagnosticManager &diagnostic_manager)
{
    clang::SourceManager &source_manager = m_compiler->getSourceManager();
    clang::edit::EditedSource editor(source_manager, m_compiler->getLangOpts(), nullptr);
    clang::edit::Commit commit(editor);
    clang::Rewriter rewriter(source_manager, m_compiler->getLangOpts());
    
    class RewritesReceiver : public edit::EditsReceiver {
      Rewriter &rewrite;

    public:
      RewritesReceiver(Rewriter &in_rewrite) : rewrite(in_rewrite) { }

      void insert(SourceLocation loc, StringRef text) override {
        rewrite.InsertText(loc, text);
      }
      void replace(CharSourceRange range, StringRef text) override {
        rewrite.ReplaceText(range.getBegin(), rewrite.getRangeSize(range), text);
      }
    };
    
    RewritesReceiver rewrites_receiver(rewriter);
    
    const DiagnosticList &diagnostics = diagnostic_manager.Diagnostics();
    size_t num_diags = diagnostics.size();
    if (num_diags == 0)
        return false;
    
    for (const Diagnostic *diag : diagnostic_manager.Diagnostics())
    {
        const ClangDiagnostic *diagnostic = llvm::dyn_cast<ClangDiagnostic>(diag);
        if (diagnostic && diagnostic->HasFixIts())
        {
             for (const FixItHint &fixit : diagnostic->FixIts())
             {
                // This is cobbed from clang::Rewrite::FixItRewriter.
                if (fixit.CodeToInsert.empty())
                {
                  if (fixit.InsertFromRange.isValid())
                  {
                      commit.insertFromRange(fixit.RemoveRange.getBegin(),
                                             fixit.InsertFromRange, /*afterToken=*/false,
                                             fixit.BeforePreviousInsertions);
                  }
                  else
                    commit.remove(fixit.RemoveRange);
                }
                else
                {
                  if (fixit.RemoveRange.isTokenRange() ||
                      fixit.RemoveRange.getBegin() != fixit.RemoveRange.getEnd())
                    commit.replace(fixit.RemoveRange, fixit.CodeToInsert);
                  else
                    commit.insert(fixit.RemoveRange.getBegin(), fixit.CodeToInsert,
                                /*afterToken=*/false, fixit.BeforePreviousInsertions);
                }
            }
        }
    }
    
    // FIXME - do we want to try to propagate specific errors here?
    if (!commit.isCommitable())
        return false;
    else if (!editor.commit(commit))
        return false;
    
    // Now play all the edits, and stash the result in the diagnostic manager.
    editor.applyRewrites(rewrites_receiver);
    RewriteBuffer &main_file_buffer = rewriter.getEditBuffer(source_manager.getMainFileID());

    std::string fixed_expression;
    llvm::raw_string_ostream out_stream(fixed_expression);
    
    main_file_buffer.write(out_stream);
    out_stream.flush();
    diagnostic_manager.SetFixedExpression(fixed_expression);
    
    return true;
}