blob: 3254802dc0d600af8c100b0a840acfb6bd4bb445 [file] [log] [blame]
//===- unittest/Format/FormatTestJson.cpp - Formatting tests for Json -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "FormatTestUtils.h"
#include "clang/Format/Format.h"
#include "llvm/Support/Debug.h"
#include "gtest/gtest.h"
#define DEBUG_TYPE "format-test-json"
namespace clang {
namespace format {
class FormatTestJson : public ::testing::Test {
protected:
static std::string format(llvm::StringRef Code, unsigned Offset,
unsigned Length, const FormatStyle &Style) {
LLVM_DEBUG(llvm::errs() << "---\n");
LLVM_DEBUG(llvm::errs() << Code << "\n\n");
tooling::Replacements Replaces;
// Mock up what ClangFormat.cpp will do for JSON by adding a variable
// to trick JSON into being JavaScript
if (Style.isJson() && !Style.DisableFormat) {
auto Err = Replaces.add(
tooling::Replacement(tooling::Replacement("", 0, 0, "x = ")));
if (Err)
llvm::errs() << "Bad Json variable insertion\n";
}
auto ChangedCode = applyAllReplacements(Code, Replaces);
if (!ChangedCode)
llvm::errs() << "Bad Json varibale replacement\n";
StringRef NewCode = *ChangedCode;
std::vector<tooling::Range> Ranges(1, tooling::Range(0, NewCode.size()));
Replaces = reformat(Style, NewCode, Ranges);
auto Result = applyAllReplacements(NewCode, Replaces);
EXPECT_TRUE(static_cast<bool>(Result));
LLVM_DEBUG(llvm::errs() << "\n" << *Result << "\n\n");
return *Result;
}
static std::string
format(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(FormatStyle::LK_Json)) {
return format(Code, 0, Code.size(), Style);
}
static FormatStyle getStyleWithColumns(unsigned ColumnLimit) {
FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
Style.ColumnLimit = ColumnLimit;
return Style;
}
static void verifyFormatStable(llvm::StringRef Code,
const FormatStyle &Style) {
EXPECT_EQ(Code.str(), format(Code, Style)) << "Expected code is not stable";
}
static void
verifyFormat(llvm::StringRef Code,
const FormatStyle &Style = getLLVMStyle(FormatStyle::LK_Json)) {
verifyFormatStable(Code, Style);
EXPECT_EQ(Code.str(), format(test::messUp(Code), Style));
}
};
TEST_F(FormatTestJson, JsonRecord) {
verifyFormat("{}");
verifyFormat("{\n"
" \"name\": 1\n"
"}");
verifyFormat("{\n"
" \"name\": \"Foo\"\n"
"}");
verifyFormat("{\n"
" \"name\": {\n"
" \"value\": 1\n"
" }\n"
"}");
verifyFormat("{\n"
" \"name\": {\n"
" \"value\": 1\n"
" },\n"
" \"name\": {\n"
" \"value\": 2\n"
" }\n"
"}");
verifyFormat("{\n"
" \"name\": {\n"
" \"value\": [\n"
" 1,\n"
" 2,\n"
" ]\n"
" }\n"
"}");
verifyFormat("{\n"
" \"name\": {\n"
" \"value\": [\n"
" \"name\": {\n"
" \"value\": 1\n"
" },\n"
" \"name\": {\n"
" \"value\": 2\n"
" }\n"
" ]\n"
" }\n"
"}");
verifyFormat(R"({
"firstName": "John",
"lastName": "Smith",
"isAlive": true,
"age": 27,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021-3100"
},
"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
}
],
"children": [],
"spouse": null
})");
}
TEST_F(FormatTestJson, JsonArray) {
verifyFormat("[]");
verifyFormat("[\n"
" 1\n"
"]");
verifyFormat("[\n"
" 1,\n"
" 2\n"
"]");
verifyFormat("[\n"
" {},\n"
" {}\n"
"]");
verifyFormat("[\n"
" {\n"
" \"name\": 1\n"
" },\n"
" {}\n"
"]");
}
TEST_F(FormatTestJson, JsonArrayOneLine) {
FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
Style.BreakArrays = false;
Style.SpacesInContainerLiterals = false;
verifyFormat("[]", Style);
verifyFormat("[1]", Style);
verifyFormat("[1, 2]", Style);
verifyFormat("[1, 2, 3]", Style);
verifyFormat("[1, 2, 3, 4]", Style);
verifyFormat("[1, 2, 3, 4, 5]", Style);
verifyFormat("[\n"
" 1,\n"
" 2,\n"
" {\n"
" A: 1\n"
" }\n"
"]",
Style);
}
TEST_F(FormatTestJson, JsonNoStringSplit) {
FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
Style.IndentWidth = 4;
verifyFormat(
"[\n"
" {\n"
" "
"\"naaaaaaaa\": \"foooooooooooooooooooooo oooooooooooooooooooooo\"\n"
" },\n"
" {}\n"
"]",
Style);
verifyFormat("[\n"
" {\n"
" "
"\"naaaaaaaa\": "
"\"foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
"oooooooooooooooooooooooooo\"\n"
" },\n"
" {}\n"
"]",
Style);
Style.ColumnLimit = 80;
verifyFormat("[\n"
" {\n"
" "
"\"naaaaaaaa\":\n"
" "
"\"foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
"oooooooooooooooooooooooooo\"\n"
" },\n"
" {}\n"
"]",
Style);
}
TEST_F(FormatTestJson, DisableJsonFormat) {
FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
verifyFormatStable("{}", Style);
verifyFormatStable("{\n"
" \"name\": 1\n"
"}",
Style);
// Since we have to disable formatting to run this test, we shall refrain from
// calling test::messUp lest we change the unformatted code and cannot format
// it back to how it started.
Style.DisableFormat = true;
verifyFormatStable("{}", Style);
verifyFormatStable("{\n"
" \"name\": 1\n"
"}",
Style);
}
TEST_F(FormatTestJson, SpaceBeforeJsonColon) {
FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
verifyFormatStable("{\n"
" \"name\": 1\n"
"}",
Style);
Style.SpaceBeforeJsonColon = true;
verifyFormatStable("{}", Style);
verifyFormatStable("{\n"
" \"name\" : 1\n"
"}",
Style);
}
TEST_F(FormatTestJson, StartsWithWhitespaces) {
FormatStyle Style = getLLVMStyle(FormatStyle::LK_Json);
EXPECT_EQ("{\n"
" \"name\": 1\n"
"}",
format(" {\n"
" \"name\": 1\n"
"}",
Style));
// FIXME: The block below is over-indented.
EXPECT_EQ(" {\n"
" \"name\": 1\n"
" }",
format("\n{\n"
" \"name\": 1\n"
"}",
Style));
}
} // namespace format
} // end namespace clang