exhaustive_cases 진단: enum류 타입의 모든 상수에 case를 정의하세요
exhaustive_cases 진단: enum류 타입의 모든 상수에 case를 정의하세요
enum 같은 타입(enum-like type)의 값을 switch로 분기할 때, 알려진 모든 상수에 case 절을 정의하도록 안내하는 린트 규칙이에요. 빠뜨린 분기가 없도록 컴파일러가 도와주는 셈이죠.
출처: exhaustive_cases
본문
설명
enum류 타입(enum-like type)의 인스턴스를 switch로 분기할 때는 알려진 모든 상수를 다루어야 해요.
enum류 타입이란 다음 조건을 만족하는 클래스 또는 확장 타입(extension type)이에요.
- private이고 팩토리(factory)가 아닌 생성자만 가진다.
- 타입이 자기 자신(둘러싼 타입)인
static const필드를 두 개 이상 가진다.
이에 더해 enum류 클래스는 구체적(concrete, 비추상) 이고, 정의된 라이브러리 안에 하위 클래스가 없어야 해요.
enum류 타입의 모든 상수에 case 절을 정의하도록(DO) 해요. 확장 타입도 enum류가 될 수 있어요.
extension type const E._(int value) {
static const E a = E._(1);
static const E b = E._(2);
}
void f(E e) {
switch (e) { // LINT
case E.a:
print('a');
}
}
BAD:
아래 코드는 어떤 case도 빠뜨리지 않으려면 세 상수 e, f, g를 모두 다뤄야 하는데, g를 빠뜨리고 있어요.
class EnumLike {
final int i;
const EnumLike._(this.i);
static const e = EnumLike._(1);
static const f = EnumLike._(2);
static const g = EnumLike._(3);
}
void bad(EnumLike e) {
// Missing case.
switch(e) { // LINT
case EnumLike.e :
print('e');
break;
case EnumLike.f :
print('f');
break;
}
}
GOOD:
모든 case를 다뤘으니 문제없어요.
class EnumLike {
final int i;
const EnumLike._(this.i);
static const e = EnumLike._(1);
static const f = EnumLike._(2);
static const g = EnumLike._(3);
}
void ok(EnumLike e) {
// All cases covered.
switch(e) { // OK
case EnumLike.e :
print('e');
break;
case EnumLike.f :
print('f');
break;
case EnumLike.g :
print('g');
break;
}
}
활성화 방법
exhaustive_cases 규칙을 쓰려면 analysis_options.yaml 파일의 linter > rules 아래에 규칙을 추가하면 돼요.
linter:
rules:
- exhaustive_cases
대신 YAML 맵(map) 문법으로 린터 규칙을 설정한다면, linter > rules 아래에 exhaustive_cases: true를 추가해요.
linter:
rules:
exhaustive_cases: true