diff --git a/ConfigParser.cs b/ConfigParser.cs index a928747729578ad1ef7a39d21e48639fe23bd0fd..aca0b1ff74114438324ad3e4a6f309065002ef9e 100644 --- a/ConfigParser.cs +++ b/ConfigParser.cs @@ -146,6 +146,33 @@ class ConfigNoValueException: ConfigException return $"{Value.Place}: Value needed." ; } } +class ConfigUnusedOptionException: ConfigException +{ + public ConfigKeyValue Value; + public ConfigUnusedOptionException(ConfigKeyValue value) + { + Value = value; + } + public override string ErrorString() + { + return $"{Value.Place}: No such option." ; + } +} +class ConfigUnusedSectionException: ConfigException +{ + public ConfigSection Section; + public ConfigUnusedSectionException(ConfigSection section) + { + Section = section; + } + public override string ErrorString() + { + if(Section.SectionName == null) + return $"Global section not allowed." ; + else + return $"{Section.SectionName}: No such section." ; + } +} class ConfigParseValueException: ConfigException { public ConfigValue Value; @@ -279,6 +306,12 @@ class ConfigKeyValue: ConfigValue internal string? amen; internal string? tabs; public string Key {get; init;} + public bool Used = false; + public ConfigKeyValue Use() + { + Used = true; + return this; + } public override string FullName { get => Section.SectionName != null ? $"{Section.SectionName}: {Key}" : Key; @@ -338,6 +371,12 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue> public int Line; List<ConfigKeyValue> values = new(); Dictionary<string, ConfigKeyValue> valueByName = new(); + public bool Used = false; + public ConfigSection Use() + { + Used = true; + return this; + } internal ConfigSection(ConfigParser _Root, string? _SectionName, int _line) { Root = _Root; @@ -371,7 +410,7 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue> { if(!valueByName.TryGetValue(key, out var r)) return null; - return r; + return r.Use(); } public ConfigValue OptionalDefaultIsSectionName(string key) { @@ -381,7 +420,7 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue> { if(!valueByName.TryGetValue(key, out var r)) throw new ConfigNotDefinedException(this, key); - return r; + return r.Use(); } public bool Contains(string key) { @@ -396,6 +435,14 @@ class ConfigSection: IReadOnlyList<ConfigKeyValue> } } public ConfigSectionNameAsValue SectionNameAsValue() => new(this); + public void CheckUnused() + { + foreach(ConfigKeyValue it in this) + { + if(it.Used == false) + throw new ConfigUnusedOptionException(it); + } + } } class ConfigParser: IReadOnlyList<ConfigSection> { @@ -516,13 +563,21 @@ class ConfigParser: IReadOnlyList<ConfigSection> if(key == null) return MainSection; if(!sectionByName.TryGetValue(key, out var r)) return null; - return r; + return r.Use(); } public ConfigSection Mandatory(string? key) { if(key == null) return MainSection; if(!sectionByName.TryGetValue(key, out var r)) throw new ConfigSectionNotDefinedException(key); - return r; + return r.Use(); + } + public void CheckUnused() + { + foreach(ConfigSection it in this) + { + if(it.Used == false) + throw new ConfigUnusedSectionException(it); + } } } diff --git a/Program.cs b/Program.cs index edc16a96ff7fd83b63bf9c74c363f4c05dc605e8..692bb57de85d63cc1a0769c8bb731c723653daaf 100644 --- a/Program.cs +++ b/Program.cs @@ -251,7 +251,10 @@ refresh throw new Exception($"Missing constructor of {type} module"); Module module = (Module) constructor.Invoke(new object[]{}); modules.Add(addStandardModuleWrappers(s, module, this)); + s.Use(); + s.CheckUnused(); } + p.CheckUnused(); } public List<Block> Get() {