// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. library test.enums; import 'dart:mirrors'; import 'package:analyzer/src/generated/element.dart'; import 'package:analyzer/src/generated/engine.dart'; import 'package:analyzer/src/generated/error.dart'; import 'package:analyzer/src/generated/html.dart' as html; import 'package:analyzer/src/generated/java_core.dart'; import 'package:analyzer/src/generated/resolver.dart'; import 'package:analyzer/src/generated/source.dart'; import 'package:analyzer/src/generated/utilities_dart.dart'; import 'package:unittest/unittest.dart'; import 'generated/ast_test.dart'; import 'reflective_tests.dart'; void main() { groupSep = ' | '; runReflectiveTests(EnumTest); } @reflectiveTest class EnumTest { void test_AnalysisLevel() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_AssignmentKind() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_CacheState() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_ElementKind() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_ErrorProperty() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_ErrorSeverity() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_ErrorType() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_html_TokenType() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_INIT_STATE() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_Modifier() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_ParameterKind() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_RedirectingConstructorKind() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_RetentionPriority() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_SourceKind() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_SourcePriority() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_UriKind() { new EnumTester() ..check_getters() ..check_explicit_values(); } void test_WrapperKind() { new EnumTester() ..check_getters() ..check_explicit_values(); } } /** * Helper class for testing invariants of enumerated types. */ class EnumTester { /** * Set of getter names which should be ignored when looking for getters * representing enum values. */ Set _ignoreGetters = new Set(); EnumTester({List ignoreGetters}) { // Always ignore a getter called "values". _ignoreGetters.add('values'); if (ignoreGetters != null) { for (String getterName in ignoreGetters) { _ignoreGetters.add(getterName); } } } /** * Get a map from getter name to the value returned by the getter, for all * static getters in [C] whose name isn't in [_ignoreGetters]. */ Map get _getters { Map result = {}; ClassMirror reflectedClass = reflectClass(C); reflectedClass.staticMembers.forEach((Symbol symbol, MethodMirror method) { if (!method.isGetter) { return; } String name = MirrorSystem.getName(symbol); if (_ignoreGetters.contains(name)) { return; } C value = reflectedClass.getField(symbol).reflectee; result[name] = value; }); return result; } /** * Check invariants on the list of enum values accessible via the static * getter "values". */ void check_explicit_values() { ClassMirror reflectedClass = reflectClass(C); List values = reflectedClass.getField(#values).reflectee; Map reverseMap = {}; // Check that "values" is a list of values of type C, with no duplicates. expect(values, isList); for (int i = 0; i < values.length; i++) { C value = values[i]; expect(value, new isInstanceOf(), reason: 'values[$i]'); if (reverseMap.containsKey(value)) { fail('values[$i] and values[${reverseMap[value]}] both equal $value'); } reverseMap[value] = i; } // Check that the set of values in the "values" list matches the set of // values accessible via static fields. expect(reverseMap.keys.toSet(), equals(_getters.values.toSet())); // Make sure the order of the list matches the ordinal numbers. for (int i = 0; i < values.length; i++) { expect(values[i].ordinal, equals(i), reason: 'values[$i].ordinal'); } } /** * Check invariants on the set of enum values accessible via the static * getters defined in the class [C] (with the exception of a getter called * "values"). */ void check_getters() { Map ordinals = {}; int numValues = 0; _getters.forEach((String name, C value) { String reason = 'getter: $name'; ++numValues; // Check the type of the value expect(value, new isInstanceOf(), reason: reason); // Check that the name of the getter matches the name stored in the enum. expect(value.name, equals(name), reason: reason); // Check that there are no duplicate ordinals. if (ordinals.containsKey(value.ordinal)) { fail( 'Getters $name and ${ordinals[value.ordinal]} have ordinal value ${value.ordinal}'); } ordinals[value.ordinal] = name; }); // Check that the set of ordinals runs from 0 to N-1, where N is the number // of enumerated values. Set expectedOrdinals = new Set(); for (int i = 0; i < numValues; i++) { expectedOrdinals.add(i); } expect(ordinals.keys.toSet(), equals(expectedOrdinals)); } }