From 664e27cfe7b0a91ca3ea8b299f89ca265238fb8c Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 5 Sep 2021 15:44:21 -0600 Subject: [PATCH] Fix mapped options using TS enums as a map --- src/lib/utils/options/declaration.ts | 16 +++++++++------- src/test/.editorconfig | 2 -- src/test/utils/options/options.test.ts | 13 ++++++++++++- 3 files changed, 21 insertions(+), 10 deletions(-) delete mode 100644 src/test/.editorconfig diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 112cdb418..d76a3b221 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -380,7 +380,7 @@ const converters: { return strArrValue; }, [ParameterType.Map](value, option) { - const key = String(value).toLowerCase(); + const key = String(value); if (option.map instanceof Map) { if (option.map.has(key)) { return option.map.get(key); @@ -388,6 +388,9 @@ const converters: { return value; } } else if (key in option.map) { + if (isTsNumericEnum(option.map) && typeof value === "number") { + return value; + } return option.map[key]; } else if (Object.values(option.map).includes(value)) { return value; @@ -505,6 +508,10 @@ function resolveModulePaths(modules: readonly string[], configPath: string) { }); } +function isTsNumericEnum(map: Record) { + return Object.values(map).every((key) => map[map[key]] === key); +} + /** * Returns an error message for a map option, indicating that a given value was not one of the values within the map. * @param map The values for the option. @@ -516,15 +523,10 @@ function getMapError( name: string ): string { let keys = map instanceof Map ? [...map.keys()] : Object.keys(map); - const getString = (key: string) => - String(map instanceof Map ? map.get(key) : map[key]); // If the map is a TS numeric enum we need to filter out the numeric keys. // TS numeric enums have the property that every key maps to a value, which maps back to that key. - if ( - !(map instanceof Map) && - keys.every((key) => getString(getString(key)) === key) - ) { + if (!(map instanceof Map) && isTsNumericEnum(map)) { // This works because TS enum keys may not be numeric. keys = keys.filter((key) => Number.isNaN(parseInt(key, 10))); } diff --git a/src/test/.editorconfig b/src/test/.editorconfig deleted file mode 100644 index fa117062d..000000000 --- a/src/test/.editorconfig +++ /dev/null @@ -1,2 +0,0 @@ -[*.html] -insert_final_newline = false diff --git a/src/test/utils/options/options.test.ts b/src/test/utils/options/options.test.ts index 71f5fd5a3..972f7b74c 100644 --- a/src/test/utils/options/options.test.ts +++ b/src/test/utils/options/options.test.ts @@ -1,4 +1,4 @@ -import { Logger, Options, ParameterType } from "../../../lib/utils"; +import { Logger, LogLevel, Options, ParameterType } from "../../../lib/utils"; import { BindOption, MapDeclarationOption, @@ -94,6 +94,17 @@ describe("Options", () => { throws(() => options.setValue("mapped" as any, "nonsense" as any)); }); + it("Handles mapped enums properly", () => { + const options = new Options(new Logger()); + options.addDefaultDeclarations(); + + equal(options.getValue("logLevel"), LogLevel.Info); + options.setValue("logLevel", LogLevel.Error); + equal(options.getValue("logLevel"), LogLevel.Error); + options.setValue("logLevel", "Verbose"); + equal(options.getValue("logLevel"), LogLevel.Verbose); + }); + it("Supports directly getting values", () => { equal(options.getRawValues().entryPoints, []); });