forked from MaskRay/ccls
-
Notifications
You must be signed in to change notification settings - Fork 0
/
clang_format.cc
117 lines (98 loc) · 4.19 KB
/
clang_format.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#if USE_CLANG_CXX
#include "clang_format.h"
#include "working_files.h"
#include <doctest/doctest.h>
#include <loguru.hpp>
using namespace clang;
using clang::format::FormatStyle;
namespace {
// TODO Objective-C 'header/interface' files may use .h, we should get this from
// project information.
FormatStyle::LanguageKind getLanguageKindFromFilename(
llvm::StringRef filename) {
if (filename.endswith(".m") || filename.endswith(".mm")) {
return FormatStyle::LK_ObjC;
}
return FormatStyle::LK_Cpp;
}
} // namespace
std::vector<tooling::Replacement> ClangFormatDocument(
WorkingFile* working_file,
int start,
int end,
lsFormattingOptions options) {
const auto language_kind =
getLanguageKindFromFilename(working_file->filename);
FormatStyle predefined_style;
getPredefinedStyle("chromium", language_kind, &predefined_style);
llvm::Expected<FormatStyle> style =
format::getStyle("file", working_file->filename, "chromium");
if (!style) {
// If, for some reason, we cannot get a format style, use Chromium's with
// tab configuration provided by the client editor.
LOG_S(ERROR) << llvm::toString(style.takeError());
predefined_style.UseTab = options.insertSpaces
? FormatStyle::UseTabStyle::UT_Never
: FormatStyle::UseTabStyle::UT_Always;
predefined_style.IndentWidth = options.tabSize;
}
auto format_result = reformat(
style ? *style : predefined_style, working_file->buffer_content,
llvm::ArrayRef<tooling::Range>(tooling::Range(start, end - start)),
working_file->filename);
return std::vector<tooling::Replacement>(format_result.begin(),
format_result.end());
}
TEST_SUITE("ClangFormat") {
TEST_CASE("entireDocument") {
const std::string sample_document = "int main() { int *i = 0; return 0; }";
WorkingFile* file = new WorkingFile("foo.cc", sample_document);
lsFormattingOptions formatting_options;
formatting_options.insertSpaces = true;
const auto replacements = ClangFormatDocument(
file, 0, sample_document.size(), formatting_options);
// echo "int main() { int *i = 0; return 0; }" | clang-format
// -style=Chromium -output-replacements-xml
//
// <?xml version='1.0'?>
// <replacements xml:space='preserve' incomplete_format='false'>
// <replacement offset='12' length='1'> </replacement>
// <replacement offset='16' length='1'></replacement>
// <replacement offset='18' length='0'> </replacement>
// <replacement offset='24' length='1'> </replacement>
// <replacement offset='34' length='1'> </replacement>
// </replacements>
REQUIRE(replacements.size() == 5);
REQUIRE(replacements[0].getOffset() == 12);
REQUIRE(replacements[0].getLength() == 1);
REQUIRE(replacements[0].getReplacementText() == "\n ");
REQUIRE(replacements[1].getOffset() == 16);
REQUIRE(replacements[1].getLength() == 1);
REQUIRE(replacements[1].getReplacementText() == "");
REQUIRE(replacements[2].getOffset() == 18);
REQUIRE(replacements[2].getLength() == 0);
REQUIRE(replacements[2].getReplacementText() == " ");
REQUIRE(replacements[3].getOffset() == 24);
REQUIRE(replacements[3].getLength() == 1);
REQUIRE(replacements[3].getReplacementText() == "\n ");
REQUIRE(replacements[4].getOffset() == 34);
REQUIRE(replacements[4].getLength() == 1);
REQUIRE(replacements[4].getReplacementText() == "\n");
}
TEST_CASE("range") {
const std::string sampleDocument = "int main() { int *i = 0; return 0; }";
WorkingFile* file = new WorkingFile("foo.cc", sampleDocument);
lsFormattingOptions formattingOptions;
formattingOptions.insertSpaces = true;
const auto replacements =
ClangFormatDocument(file, 30, sampleDocument.size(), formattingOptions);
REQUIRE(replacements.size() == 2);
REQUIRE(replacements[0].getOffset() == 24);
REQUIRE(replacements[0].getLength() == 1);
REQUIRE(replacements[0].getReplacementText() == "\n ");
REQUIRE(replacements[1].getOffset() == 34);
REQUIRE(replacements[1].getLength() == 1);
REQUIRE(replacements[1].getReplacementText() == "\n");
}
}
#endif