252 lines · cpp
1//===-- PopulateSwitchTest.cpp ----------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "TweakTesting.h"10#include "gmock/gmock.h"11#include "gtest/gtest.h"12 13namespace clang {14namespace clangd {15namespace {16 17TWEAK_TEST(PopulateSwitch);18 19TEST_F(PopulateSwitchTest, Test) {20 struct Case {21 CodeContext Context;22 llvm::StringRef TestSource;23 llvm::StringRef ExpectedSource;24 llvm::StringRef FileName = "TestTU.cpp";25 };26 27 Case Cases[]{28 {29 // No enumerators30 Function,31 R""(enum Enum {}; ^switch ((Enum)0) {})"",32 "unavailable",33 },34 {35 // All enumerators already in switch (unscoped)36 Function,37 R""(enum Enum {A,B}; ^switch (A) {case A:break;case B:break;})"",38 "unavailable",39 },40 {41 // All enumerators already in switch (scoped)42 Function,43 R""(44 enum class Enum {A,B};45 ^switch (Enum::A) {case Enum::A:break;case Enum::B:break;}46 )"",47 "unavailable",48 },49 {50 // Default case in switch51 Function,52 R""(53 enum class Enum {A,B};54 ^switch (Enum::A) {default:break;}55 )"",56 "unavailable",57 },58 {59 // GNU range in switch60 Function,61 R""(62 enum class Enum {A,B};63 ^switch (Enum::A) {case Enum::A ... Enum::B:break;}64 )"",65 "unavailable",66 },67 {68 // Value dependent case expression69 File,70 R""(71 enum class Enum {A,B};72 template<Enum Value>73 void function() {74 ^switch (Enum::A) {case Value:break;}75 }76 )"",77 "unavailable",78 },79 {80 // Body not CompoundStmt81 Function,82 R""(enum Enum {A}; ^switch (A);)"",83 "unavailable",84 },85 {86 // Selection on switch token87 Function,88 R""(enum Enum {A}; ^switch (A) {})"",89 R""(enum Enum {A}; switch (A) {case A:break;})"",90 },91 {92 // Selection on switch condition93 Function,94 R""(enum Enum {A}; switch (^A) {})"",95 R""(enum Enum {A}; switch (A) {case A:break;})"",96 },97 {98 // Selection of whole switch condition99 Function,100 R""(enum Enum {A}; switch ([[A]]) {})"",101 R""(enum Enum {A}; switch (A) {case A:break;})"",102 },103 {104 // Selection in switch body105 Function,106 R""(enum Enum {A}; switch (A) {^})"",107 R""(enum Enum {A}; switch (A) {case A:break;})"",108 },109 {110 // Scoped enumeration111 Function,112 R""(enum class Enum {A}; ^switch (Enum::A) {})"",113 R""(enum class Enum {A}; switch (Enum::A) {case Enum::A:break;})"",114 },115 {116 // Scoped enumeration with multiple enumerators117 Function,118 R""(119 enum class Enum {A,B};120 ^switch (Enum::A) {}121 )"",122 R""(123 enum class Enum {A,B};124 switch (Enum::A) {case Enum::A:case Enum::B:break;}125 )"",126 },127 {128 // Only filling in missing enumerators (unscoped)129 Function,130 R""(131 enum Enum {A,B,C};132 ^switch (A) {case B:break;}133 )"",134 R""(135 enum Enum {A,B,C};136 switch (A) {case B:break;case A:case C:break;}137 )"",138 },139 {140 // Only filling in missing enumerators,141 // even when using integer literals142 Function,143 R""(144 enum Enum {A,B=1,C};145 ^switch (A) {case 1:break;}146 )"",147 R""(148 enum Enum {A,B=1,C};149 switch (A) {case 1:break;case A:case C:break;}150 )"",151 },152 {153 // Only filling in missing enumerators (scoped)154 Function,155 R""(156 enum class Enum {A,B,C};157 ^switch (Enum::A)158 {case Enum::B:break;}159 )"",160 R""(161 enum class Enum {A,B,C};162 switch (Enum::A)163 {case Enum::B:break;case Enum::A:case Enum::C:break;}164 )"",165 },166 {167 // Scoped enumerations in namespace168 File,169 R""(170 namespace ns { enum class Enum {A}; }171 void function() { ^switch (ns::Enum::A) {} }172 )"",173 R""(174 namespace ns { enum class Enum {A}; }175 void function() { switch (ns::Enum::A) {case ns::Enum::A:break;} }176 )"",177 },178 {179 // Unscoped enumerations in namespace180 File,181 R""(182 namespace ns { enum Enum {A}; }183 void function() { ^switch (ns::A) {} }184 )"",185 R""(186 namespace ns { enum Enum {A}; }187 void function() { switch (ns::A) {case ns::A:break;} }188 )"",189 },190 {191 // Duplicated constant names192 Function,193 R""(enum Enum {A,B,b=B}; ^switch (A) {})"",194 R""(enum Enum {A,B,b=B}; switch (A) {case A:case B:break;})"",195 },196 {197 // Duplicated constant names all in switch198 Function,199 R""(enum Enum {A,B,b=B}; ^switch (A) {case A:case B:break;})"",200 "unavailable",201 },202 {203 // Enum is dependent type204 File,205 R""(template<typename T> void f() {enum Enum {A}; ^switch (A) {}})"",206 "unavailable",207 },208 {// C: Only filling in missing enumerators209 Function,210 R""(211 enum CEnum {A,B,C};212 enum CEnum val = A;213 ^switch (val) {case B:break;}214 )"",215 R""(216 enum CEnum {A,B,C};217 enum CEnum val = A;218 switch (val) {case B:break;case A:case C:break;}219 )"",220 "TestTU.c"},221 {// C: Only filling in missing enumerators w/ typedefs222 Function,223 R""(224 typedef unsigned long UInteger;225 enum ControlState : UInteger;226 typedef enum ControlState ControlState;227 enum ControlState : UInteger {A,B,C};228 ControlState controlState = A;229 switch (^controlState) {case A:break;}230 )"",231 R""(232 typedef unsigned long UInteger;233 enum ControlState : UInteger;234 typedef enum ControlState ControlState;235 enum ControlState : UInteger {A,B,C};236 ControlState controlState = A;237 switch (controlState) {case A:break;case B:case C:break;}238 )"",239 "TestTU.c"},240 };241 242 for (const auto &Case : Cases) {243 Context = Case.Context;244 FileName = Case.FileName;245 EXPECT_EQ(apply(Case.TestSource), Case.ExpectedSource);246 }247}248 249} // namespace250} // namespace clangd251} // namespace clang252