mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-26 17:41:58 +00:00
[formatting] Add textDocument/rangeFormatting
This commit is contained in:
parent
aca8e42033
commit
12ad0303be
@ -1,25 +1,16 @@
|
|||||||
#if USE_CLANG_CXX
|
#if USE_CLANG_CXX
|
||||||
|
|
||||||
#include "clang_format.h"
|
#include "clang_format.h"
|
||||||
|
#include "working_files.h"
|
||||||
|
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
|
|
||||||
using namespace clang::format;
|
using namespace clang::format;
|
||||||
using namespace clang::tooling;
|
using namespace clang::tooling;
|
||||||
|
|
||||||
ClangFormat::ClangFormat(llvm::StringRef document_filename,
|
namespace {
|
||||||
llvm::StringRef document,
|
|
||||||
llvm::ArrayRef<clang::tooling::Range> ranges,
|
|
||||||
int tab_size,
|
|
||||||
bool insert_spaces)
|
|
||||||
: document_filename_(document_filename),
|
|
||||||
document_(document),
|
|
||||||
ranges_(ranges),
|
|
||||||
tab_size_(tab_size),
|
|
||||||
insert_spaces_(insert_spaces) {}
|
|
||||||
ClangFormat::~ClangFormat(){};
|
|
||||||
|
|
||||||
static FormatStyle::LanguageKind getLanguageKindFromFilename(
|
FormatStyle::LanguageKind getLanguageKindFromFilename(
|
||||||
llvm::StringRef filename) {
|
llvm::StringRef filename) {
|
||||||
if (filename.endswith(".m") || filename.endswith(".mm")) {
|
if (filename.endswith(".m") || filename.endswith(".mm")) {
|
||||||
return FormatStyle::LK_ObjC;
|
return FormatStyle::LK_ObjC;
|
||||||
@ -27,23 +18,32 @@ static FormatStyle::LanguageKind getLanguageKindFromFilename(
|
|||||||
return FormatStyle::LK_Cpp;
|
return FormatStyle::LK_Cpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Replacement> ClangFormat::FormatWholeDocument() {
|
} // namespace
|
||||||
const auto language_kind = getLanguageKindFromFilename(document_filename_);
|
|
||||||
|
std::vector<Replacement> ClangFormatDocument(WorkingFile* working_file,
|
||||||
|
int start,
|
||||||
|
int end,
|
||||||
|
lsFormattingOptions options) {
|
||||||
|
const auto language_kind =
|
||||||
|
getLanguageKindFromFilename(working_file->filename);
|
||||||
FormatStyle predefined_style;
|
FormatStyle predefined_style;
|
||||||
getPredefinedStyle("chromium", language_kind, &predefined_style);
|
getPredefinedStyle("chromium", language_kind, &predefined_style);
|
||||||
llvm::Expected<FormatStyle> style =
|
llvm::Expected<FormatStyle> style =
|
||||||
getStyle("file", document_filename_, "chromium");
|
getStyle("file", working_file->filename, "chromium");
|
||||||
if (!style) {
|
if (!style) {
|
||||||
// If, for some reason, we cannot get a format style, use Chromium's with
|
// If, for some reason, we cannot get a format style, use Chromium's with
|
||||||
// tab configuration provided by the client editor.
|
// tab configuration provided by the client editor.
|
||||||
LOG_S(ERROR) << llvm::toString(style.takeError());
|
LOG_S(ERROR) << llvm::toString(style.takeError());
|
||||||
predefined_style.UseTab = insert_spaces_
|
predefined_style.UseTab = options.insertSpaces
|
||||||
? FormatStyle::UseTabStyle::UT_Never
|
? FormatStyle::UseTabStyle::UT_Never
|
||||||
: FormatStyle::UseTabStyle::UT_Always;
|
: FormatStyle::UseTabStyle::UT_Always;
|
||||||
predefined_style.IndentWidth = tab_size_;
|
predefined_style.IndentWidth = options.tabSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto format_result = reformat(*style, document_, ranges_, document_filename_);
|
auto format_result = reformat(
|
||||||
|
*style, working_file->buffer_content,
|
||||||
|
llvm::ArrayRef<clang::tooling::Range>(clang::tooling::Range(start, end)),
|
||||||
|
working_file->filename);
|
||||||
return std::vector<Replacement>(format_result.begin(), format_result.end());
|
return std::vector<Replacement>(format_result.begin(), format_result.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,26 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
#if USE_CLANG_CXX
|
#if USE_CLANG_CXX
|
||||||
|
|
||||||
#pragma once
|
#include "language_server_api.h"
|
||||||
|
#include "working_files.h"
|
||||||
|
|
||||||
#include <clang/Format/Format.h>
|
#include <clang/Format/Format.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct ClangFormat {
|
std::vector<clang::tooling::Replacement> ClangFormatDocument(
|
||||||
llvm::StringRef document_filename_;
|
WorkingFile* working_file,
|
||||||
llvm::StringRef document_;
|
int start,
|
||||||
llvm::ArrayRef<clang::tooling::Range> ranges_;
|
int end,
|
||||||
int tab_size_;
|
lsFormattingOptions options);
|
||||||
bool insert_spaces_;
|
|
||||||
|
|
||||||
ClangFormat(llvm::StringRef document_filename,
|
|
||||||
llvm::StringRef document,
|
|
||||||
llvm::ArrayRef<clang::tooling::Range> ranges,
|
|
||||||
int tab_size,
|
|
||||||
bool insert_spaces);
|
|
||||||
~ClangFormat();
|
|
||||||
|
|
||||||
std::vector<clang::tooling::Replacement> FormatWholeDocument();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -459,6 +459,24 @@ enum class lsDocumentHighlightKind {
|
|||||||
};
|
};
|
||||||
MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind, int);
|
MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind, int);
|
||||||
|
|
||||||
|
|
||||||
|
struct lsFormattingOptions {
|
||||||
|
// Size of a tab in spaces.
|
||||||
|
int tabSize;
|
||||||
|
// Prefer spaces over tabs.
|
||||||
|
bool insertSpaces;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(lsFormattingOptions, tabSize, insertSpaces);
|
||||||
|
|
||||||
|
struct lsTextDocumentFormattingParams {
|
||||||
|
// The text document.
|
||||||
|
lsTextDocumentIdentifier textDocument;
|
||||||
|
|
||||||
|
// The format options, like tabs or spaces.
|
||||||
|
lsFormattingOptions options;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(lsTextDocumentFormattingParams, textDocument, options);
|
||||||
|
|
||||||
// A document highlight is a range inside a text document which deserves
|
// A document highlight is a range inside a text document which deserves
|
||||||
// special attention. Usually a document highlight is visualized by changing
|
// special attention. Usually a document highlight is visualized by changing
|
||||||
// the background color of its range.
|
// the background color of its range.
|
||||||
|
@ -142,6 +142,11 @@ struct InitializeHandler : BaseMessageHandler<Ipc_InitializeRequest> {
|
|||||||
out.result.capabilities.documentSymbolProvider = true;
|
out.result.capabilities.documentSymbolProvider = true;
|
||||||
out.result.capabilities.workspaceSymbolProvider = true;
|
out.result.capabilities.workspaceSymbolProvider = true;
|
||||||
|
|
||||||
|
#if USE_CLANG_CXX
|
||||||
|
out.result.capabilities.documentFormattingProvider = true;
|
||||||
|
out.result.capabilities.documentRangeFormattingProvider = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
out.result.capabilities.documentLinkProvider = lsDocumentLinkOptions();
|
out.result.capabilities.documentLinkProvider = lsDocumentLinkOptions();
|
||||||
out.result.capabilities.documentLinkProvider->resolveProvider = false;
|
out.result.capabilities.documentLinkProvider->resolveProvider = false;
|
||||||
|
|
||||||
|
@ -6,25 +6,6 @@
|
|||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct lsFormattingOptions {
|
|
||||||
// Size of a tab in spaces.
|
|
||||||
int tabSize;
|
|
||||||
// Prefer spaces over tabs.
|
|
||||||
bool insertSpaces;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsFormattingOptions, tabSize, insertSpaces);
|
|
||||||
|
|
||||||
struct lsTextDocumentFormattingParams {
|
|
||||||
// The text document.
|
|
||||||
lsTextDocumentIdentifier textDocument;
|
|
||||||
|
|
||||||
// The format options, like tabs or spaces.
|
|
||||||
lsFormattingOptions options;
|
|
||||||
};
|
|
||||||
MAKE_REFLECT_STRUCT(lsTextDocumentFormattingParams,
|
|
||||||
textDocument,
|
|
||||||
options);
|
|
||||||
|
|
||||||
struct Ipc_TextDocumentFormatting
|
struct Ipc_TextDocumentFormatting
|
||||||
: public IpcMessage<Ipc_TextDocumentFormatting> {
|
: public IpcMessage<Ipc_TextDocumentFormatting> {
|
||||||
const static IpcId kIpcId = IpcId::TextDocumentFormatting;
|
const static IpcId kIpcId = IpcId::TextDocumentFormatting;
|
||||||
@ -57,20 +38,14 @@ struct TextDocumentFormattingHandler
|
|||||||
WorkingFile* working_file =
|
WorkingFile* working_file =
|
||||||
working_files->GetFileByFilename(file->def->path);
|
working_files->GetFileByFilename(file->def->path);
|
||||||
|
|
||||||
int tab_size = request->params.options.tabSize;
|
|
||||||
bool insert_spaces = request->params.options.insertSpaces;
|
|
||||||
|
|
||||||
const auto clang_format = MakeUnique<ClangFormat>(
|
|
||||||
working_file->filename, working_file->buffer_content,
|
|
||||||
llvm::ArrayRef<clang::tooling::Range>(
|
|
||||||
clang::tooling::Range(0, working_file->buffer_content.size())),
|
|
||||||
tab_size, insert_spaces);
|
|
||||||
const auto replacements = clang_format->FormatWholeDocument();
|
|
||||||
response.result = ConvertClangReplacementsIntoTextEdits(
|
response.result = ConvertClangReplacementsIntoTextEdits(
|
||||||
working_file->buffer_content, replacements);
|
working_file->buffer_content,
|
||||||
|
ClangFormatDocument(working_file, 0,
|
||||||
|
working_file->buffer_content.size(),
|
||||||
|
request->params.options));
|
||||||
#else
|
#else
|
||||||
LOG_S(WARNING) << "You must compile cquery with --use-clang-cxx to use "
|
LOG_S(WARNING) << "You must compile cquery with --use-clang-cxx to use "
|
||||||
"document formatting.";
|
"textDocument/formatting.";
|
||||||
// TODO: Fallback to execute the clang-format binary?
|
// TODO: Fallback to execute the clang-format binary?
|
||||||
response.result = {};
|
response.result = {};
|
||||||
#endif
|
#endif
|
||||||
|
61
src/messages/text_document_range_formatting.cc
Normal file
61
src/messages/text_document_range_formatting.cc
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "clang_format.h"
|
||||||
|
#include "lex_utils.h"
|
||||||
|
#include "message_handler.h"
|
||||||
|
#include "queue_manager.h"
|
||||||
|
#include "working_files.h"
|
||||||
|
|
||||||
|
#include <loguru.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct Ipc_TextDocumentRangeFormatting
|
||||||
|
: public IpcMessage<Ipc_TextDocumentRangeFormatting> {
|
||||||
|
const static IpcId kIpcId = IpcId::TextDocumentRangeFormatting;
|
||||||
|
|
||||||
|
lsRequestId id;
|
||||||
|
lsRange range;
|
||||||
|
lsTextDocumentFormattingParams params;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Ipc_TextDocumentRangeFormatting, id, range, params);
|
||||||
|
REGISTER_IPC_MESSAGE(Ipc_TextDocumentRangeFormatting);
|
||||||
|
|
||||||
|
struct Out_TextDocumentRangeFormatting
|
||||||
|
: public lsOutMessage<Out_TextDocumentRangeFormatting> {
|
||||||
|
lsRequestId id;
|
||||||
|
std::vector<lsTextEdit> result;
|
||||||
|
};
|
||||||
|
MAKE_REFLECT_STRUCT(Out_TextDocumentRangeFormatting, jsonrpc, id, result);
|
||||||
|
|
||||||
|
struct TextDocumentRangeFormattingHandler
|
||||||
|
: BaseMessageHandler<Ipc_TextDocumentRangeFormatting> {
|
||||||
|
void Run(Ipc_TextDocumentRangeFormatting* request) override {
|
||||||
|
Out_TextDocumentRangeFormatting response;
|
||||||
|
response.id = request->id;
|
||||||
|
#if USE_CLANG_CXX
|
||||||
|
QueryFile* file;
|
||||||
|
if (!FindFileOrFail(db, project, request->id,
|
||||||
|
request->params.textDocument.uri.GetPath(), &file)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkingFile* working_file =
|
||||||
|
working_files->GetFileByFilename(file->def->path);
|
||||||
|
|
||||||
|
int start = GetOffsetForPosition(request->range.start,
|
||||||
|
working_file->buffer_content),
|
||||||
|
end = GetOffsetForPosition(request->range.end,
|
||||||
|
working_file->buffer_content);
|
||||||
|
response.result = ConvertClangReplacementsIntoTextEdits(
|
||||||
|
working_file->buffer_content,
|
||||||
|
ClangFormatDocument(working_file, start, end, request->params.options));
|
||||||
|
#else
|
||||||
|
LOG_S(WARNING) << "You must compile cquery with --use-clang-cxx to use "
|
||||||
|
"textDocument/rangeFormatting.";
|
||||||
|
// TODO: Fallback to execute the clang-format binary?
|
||||||
|
response.result = {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QueueManager::WriteStdout(IpcId::TextDocumentRangeFormatting, response);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
REGISTER_MESSAGE_HANDLER(TextDocumentRangeFormattingHandler);
|
||||||
|
} // namespace
|
Loading…
Reference in New Issue
Block a user