forked from OSchip/llvm-project
252 lines
7.0 KiB
C++
252 lines
7.0 KiB
C++
//===-- PopulateSwitchTest.cpp ----------------------------------*- C++ -*-===//
|
|
//
|
|
// 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 "TweakTesting.h"
|
|
#include "gmock/gmock.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace clang {
|
|
namespace clangd {
|
|
namespace {
|
|
|
|
TWEAK_TEST(PopulateSwitch);
|
|
|
|
TEST_F(PopulateSwitchTest, Test) {
|
|
struct Case {
|
|
CodeContext Context;
|
|
llvm::StringRef TestSource;
|
|
llvm::StringRef ExpectedSource;
|
|
llvm::StringRef FileName = "TestTU.cpp";
|
|
};
|
|
|
|
Case Cases[]{
|
|
{
|
|
// No enumerators
|
|
Function,
|
|
R""(enum Enum {}; ^switch ((Enum)0) {})"",
|
|
"unavailable",
|
|
},
|
|
{
|
|
// All enumerators already in switch (unscoped)
|
|
Function,
|
|
R""(enum Enum {A,B}; ^switch (A) {case A:break;case B:break;})"",
|
|
"unavailable",
|
|
},
|
|
{
|
|
// All enumerators already in switch (scoped)
|
|
Function,
|
|
R""(
|
|
enum class Enum {A,B};
|
|
^switch (Enum::A) {case Enum::A:break;case Enum::B:break;}
|
|
)"",
|
|
"unavailable",
|
|
},
|
|
{
|
|
// Default case in switch
|
|
Function,
|
|
R""(
|
|
enum class Enum {A,B};
|
|
^switch (Enum::A) {default:break;}
|
|
)"",
|
|
"unavailable",
|
|
},
|
|
{
|
|
// GNU range in switch
|
|
Function,
|
|
R""(
|
|
enum class Enum {A,B};
|
|
^switch (Enum::A) {case Enum::A ... Enum::B:break;}
|
|
)"",
|
|
"unavailable",
|
|
},
|
|
{
|
|
// Value dependent case expression
|
|
File,
|
|
R""(
|
|
enum class Enum {A,B};
|
|
template<Enum Value>
|
|
void function() {
|
|
^switch (Enum::A) {case Value:break;}
|
|
}
|
|
)"",
|
|
"unavailable",
|
|
},
|
|
{
|
|
// Body not CompoundStmt
|
|
Function,
|
|
R""(enum Enum {A}; ^switch (A);)"",
|
|
"unavailable",
|
|
},
|
|
{
|
|
// Selection on switch token
|
|
Function,
|
|
R""(enum Enum {A}; ^switch (A) {})"",
|
|
R""(enum Enum {A}; switch (A) {case A:break;})"",
|
|
},
|
|
{
|
|
// Selection on switch condition
|
|
Function,
|
|
R""(enum Enum {A}; switch (^A) {})"",
|
|
R""(enum Enum {A}; switch (A) {case A:break;})"",
|
|
},
|
|
{
|
|
// Selection of whole switch condition
|
|
Function,
|
|
R""(enum Enum {A}; switch ([[A]]) {})"",
|
|
R""(enum Enum {A}; switch (A) {case A:break;})"",
|
|
},
|
|
{
|
|
// Selection in switch body
|
|
Function,
|
|
R""(enum Enum {A}; switch (A) {^})"",
|
|
R""(enum Enum {A}; switch (A) {case A:break;})"",
|
|
},
|
|
{
|
|
// Scoped enumeration
|
|
Function,
|
|
R""(enum class Enum {A}; ^switch (Enum::A) {})"",
|
|
R""(enum class Enum {A}; switch (Enum::A) {case Enum::A:break;})"",
|
|
},
|
|
{
|
|
// Scoped enumeration with multiple enumerators
|
|
Function,
|
|
R""(
|
|
enum class Enum {A,B};
|
|
^switch (Enum::A) {}
|
|
)"",
|
|
R""(
|
|
enum class Enum {A,B};
|
|
switch (Enum::A) {case Enum::A:case Enum::B:break;}
|
|
)"",
|
|
},
|
|
{
|
|
// Only filling in missing enumerators (unscoped)
|
|
Function,
|
|
R""(
|
|
enum Enum {A,B,C};
|
|
^switch (A) {case B:break;}
|
|
)"",
|
|
R""(
|
|
enum Enum {A,B,C};
|
|
switch (A) {case B:break;case A:case C:break;}
|
|
)"",
|
|
},
|
|
{
|
|
// Only filling in missing enumerators,
|
|
// even when using integer literals
|
|
Function,
|
|
R""(
|
|
enum Enum {A,B=1,C};
|
|
^switch (A) {case 1:break;}
|
|
)"",
|
|
R""(
|
|
enum Enum {A,B=1,C};
|
|
switch (A) {case 1:break;case A:case C:break;}
|
|
)"",
|
|
},
|
|
{
|
|
// Only filling in missing enumerators (scoped)
|
|
Function,
|
|
R""(
|
|
enum class Enum {A,B,C};
|
|
^switch (Enum::A)
|
|
{case Enum::B:break;}
|
|
)"",
|
|
R""(
|
|
enum class Enum {A,B,C};
|
|
switch (Enum::A)
|
|
{case Enum::B:break;case Enum::A:case Enum::C:break;}
|
|
)"",
|
|
},
|
|
{
|
|
// Scoped enumerations in namespace
|
|
File,
|
|
R""(
|
|
namespace ns { enum class Enum {A}; }
|
|
void function() { ^switch (ns::Enum::A) {} }
|
|
)"",
|
|
R""(
|
|
namespace ns { enum class Enum {A}; }
|
|
void function() { switch (ns::Enum::A) {case ns::Enum::A:break;} }
|
|
)"",
|
|
},
|
|
{
|
|
// Unscoped enumerations in namespace
|
|
File,
|
|
R""(
|
|
namespace ns { enum Enum {A}; }
|
|
void function() { ^switch (ns::A) {} }
|
|
)"",
|
|
R""(
|
|
namespace ns { enum Enum {A}; }
|
|
void function() { switch (ns::A) {case ns::A:break;} }
|
|
)"",
|
|
},
|
|
{
|
|
// Duplicated constant names
|
|
Function,
|
|
R""(enum Enum {A,B,b=B}; ^switch (A) {})"",
|
|
R""(enum Enum {A,B,b=B}; switch (A) {case A:case B:break;})"",
|
|
},
|
|
{
|
|
// Duplicated constant names all in switch
|
|
Function,
|
|
R""(enum Enum {A,B,b=B}; ^switch (A) {case A:case B:break;})"",
|
|
"unavailable",
|
|
},
|
|
{
|
|
// Enum is dependent type
|
|
File,
|
|
R""(template<typename T> void f() {enum Enum {A}; ^switch (A) {}})"",
|
|
"unavailable",
|
|
},
|
|
{// C: Only filling in missing enumerators
|
|
Function,
|
|
R""(
|
|
enum CEnum {A,B,C};
|
|
enum CEnum val = A;
|
|
^switch (val) {case B:break;}
|
|
)"",
|
|
R""(
|
|
enum CEnum {A,B,C};
|
|
enum CEnum val = A;
|
|
switch (val) {case B:break;case A:case C:break;}
|
|
)"",
|
|
"TestTU.c"},
|
|
{// C: Only filling in missing enumerators w/ typedefs
|
|
Function,
|
|
R""(
|
|
typedef unsigned long UInteger;
|
|
enum ControlState : UInteger;
|
|
typedef enum ControlState ControlState;
|
|
enum ControlState : UInteger {A,B,C};
|
|
ControlState controlState = A;
|
|
switch (^controlState) {case A:break;}
|
|
)"",
|
|
R""(
|
|
typedef unsigned long UInteger;
|
|
enum ControlState : UInteger;
|
|
typedef enum ControlState ControlState;
|
|
enum ControlState : UInteger {A,B,C};
|
|
ControlState controlState = A;
|
|
switch (controlState) {case A:break;case B:case C:break;}
|
|
)"",
|
|
"TestTU.c"},
|
|
};
|
|
|
|
for (const auto &Case : Cases) {
|
|
Context = Case.Context;
|
|
FileName = Case.FileName;
|
|
EXPECT_EQ(apply(Case.TestSource), Case.ExpectedSource);
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace clangd
|
|
} // namespace clang
|