using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Threading; using AspClassic.Scripting.Utils; namespace AspClassic.Scripting; [Serializable] public class LanguageOptions { private bool _exceptionDetail; private bool _showClrExceptions; private bool _interpretedMode; private readonly bool _perfStats; private readonly bool _noAdaptiveCompilation; private readonly int _compilationThreshold; private readonly ReadOnlyCollection _searchPaths; protected static readonly ReadOnlyCollection EmptyStringCollection = new ReadOnlyCollection(ArrayUtils.EmptyStrings); public bool NoAdaptiveCompilation => _noAdaptiveCompilation; public int CompilationThreshold => _compilationThreshold; [Obsolete("No longer used.")] public bool InterpretedMode { get { return _interpretedMode; } set { _interpretedMode = value; } } public bool ExceptionDetail { get { return _exceptionDetail; } set { _exceptionDetail = value; } } public bool ShowClrExceptions { get { return _showClrExceptions; } set { _showClrExceptions = value; } } public bool PerfStats => _perfStats; public ReadOnlyCollection SearchPaths => _searchPaths; public LanguageOptions() : this(null) { } public LanguageOptions(IDictionary options) { _interpretedMode = GetOption(options, "InterpretedMode", defaultValue: false); _exceptionDetail = GetOption(options, "ExceptionDetail", defaultValue: false); _showClrExceptions = GetOption(options, "ShowClrExceptions", defaultValue: false); _perfStats = GetOption(options, "PerfStats", defaultValue: false); _noAdaptiveCompilation = GetOption(options, "NoAdaptiveCompilation", defaultValue: false); _compilationThreshold = GetOption(options, "CompilationThreshold", -1); _searchPaths = GetSearchPathsOption(options) ?? new ReadOnlyCollection(new string[0]); } public static T GetOption(IDictionary options, string name, T defaultValue) { if (options != null && options.TryGetValue(name, out var value)) { if (value is T) { return (T)value; } return (T)Convert.ChangeType(value, typeof(T), Thread.CurrentThread.CurrentCulture); } return defaultValue; } public static ReadOnlyCollection GetStringCollectionOption(IDictionary options, string name, params char[] separators) { if (options == null || !options.TryGetValue(name, out var value)) { return null; } if (value is ICollection collection) { foreach (string item in collection) { if (item == null) { throw new ArgumentException($"Invalid value for option {name}: collection shouldn't containt null items"); } } return new ReadOnlyCollection(ArrayUtils.MakeArray(collection)); } if (value is string str && separators != null && separators.Length > 0) { return new ReadOnlyCollection(StringUtils.Split(str, separators, int.MaxValue, StringSplitOptions.RemoveEmptyEntries)); } throw new ArgumentException($"Invalid value for option {name}"); } public static ReadOnlyCollection GetSearchPathsOption(IDictionary options) { return GetStringCollectionOption(options, "SearchPaths", Path.PathSeparator); } }