<commit_before>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Mono.Debugging.Client;
using Mono.Debugging.Backend;
using System.Diagnostics;
using System.Collections;

namespace Mono.Debugging.Evaluation
{
	public abstract class ObjectValueAdaptor: IDisposable
	{
		Dictionary<string, TypeDisplayData> typeDisplayData = new Dictionary<string, TypeDisplayData> ();

		// Time to wait while evaluating before switching to async mode
		public int DefaultEvaluationWaitTime { get; set; }
		
		public event EventHandler<BusyStateEventArgs> BusyStateChanged;
		
		AsyncEvaluationTracker asyncEvaluationTracker = new AsyncEvaluationTracker ();
		AsyncOperationManager asyncOperationManager = new AsyncOperationManager ();
		static Dictionary<string, string> netToCSharpTypes = new Dictionary<string, string> ();

		static ObjectValueAdaptor ()
		{
			netToCSharpTypes["System.Void"]    = "void";
			netToCSharpTypes["System.Object"]  = "object";
			netToCSharpTypes["System.Boolean"] = "bool";
			netToCSharpTypes["System.Byte"]    = "byte";
			netToCSharpTypes["System.SByte"]   = "sbyte";
			netToCSharpTypes["System.Char"]    = "char";
			netToCSharpTypes["System.Enum"]    = "enum";
			netToCSharpTypes["System.Int16"]   = "short";
			netToCSharpTypes["System.Int32"]   = "int";
			netToCSharpTypes["System.Int64"]   = "long";
			netToCSharpTypes["System.UInt16"]  = "ushort";
			netToCSharpTypes["System.UInt32"]  = "uint";
			netToCSharpTypes["System.UInt64"]  = "ulong";
			netToCSharpTypes["System.Single"]  = "float";
			netToCSharpTypes["System.Double"]  = "double";
			netToCSharpTypes["System.Decimal"] = "decimal";
			netToCSharpTypes["System.String"]  = "string";
		}
		
		public ObjectValueAdaptor ()
		{
			DefaultEvaluationWaitTime = 100;
			
			asyncOperationManager.BusyStateChanged += delegate(object sender, BusyStateEventArgs e) {
				OnBusyStateChanged (e);
			};
			asyncEvaluationTracker.WaitTime = DefaultEvaluationWaitTime;
		}
		
		public void Dispose ()
		{
			asyncEvaluationTracker.Dispose ();
			asyncOperationManager.Dispose ();
		}

		public ObjectValue CreateObjectValue (EvaluationContext ctx, IObjectValueSource source, ObjectPath path, object obj, ObjectValueFlags flags)
		{
			try {
				return CreateObjectValueImpl (ctx, source, path, obj, flags);
			} catch (Exception ex) {
				ctx.WriteDebuggerError (ex);
				return ObjectValue.CreateFatalError (path.LastName, ex.Message, flags);
			}
		}
		
		public virtual string GetDisplayTypeName (string typeName)
		{
			return GetDisplayTypeName (typeName.Replace ('+', '.'), 0, typeName.Length);
		}
		
		public string GetDisplayTypeName (EvaluationContext ctx, object type)
		{
			return GetDisplayTypeName (GetTypeName (ctx, type));
		}
		
		string GetDisplayTypeName (string typeName, int startIndex, int endIndex)
		{
			// Note: '[' denotes the start of an array
			//       '`' denotes a generic type
			//       ',' denotes the start of the assembly name
			int tokenIndex = typeName.IndexOfAny (new char [] { '[', '`', ',' }, startIndex, endIndex - startIndex);
			List<string> genericArgs = null;
			string array = string.Empty;
			int genericEndIndex = -1;
			int typeEndIndex;
			
			if (tokenIndex == -1) // Simple type
				return GetShortTypeName (typeName.Substring (startIndex, endIndex - startIndex));
			
			if (typeName[tokenIndex] == ',') // Simple type with an assembly name
				return GetShortTypeName (typeName.Substring (startIndex, tokenIndex - startIndex));
			
			// save the index of the end of the type name
			typeEndIndex = tokenIndex;
			
			// decode generic args first, if this is a generic type
			if (typeName[tokenIndex] == '`') {
				genericEndIndex = tokenIndex = typeName.IndexOf ('[', tokenIndex, endIndex - tokenIndex);
				genericArgs = GetGenericArguments (typeName, ref tokenIndex, endIndex);
			}
			
			// decode array rank info
			while (tokenIndex < endIndex && typeName[tokenIndex] == '[') {
				int arrayEndIndex = typeName.IndexOf (']', tokenIndex, endIndex - tokenIndex);
				if (arrayEndIndex == -1)
					break;
				arrayEndIndex++;
				array += typeName.Substring (tokenIndex, arrayEndIndex - tokenIndex);
				tokenIndex = arrayEndIndex;
			}
			
			string name = typeName.Substring (startIndex, typeEndIndex - startIndex);
			
			if (genericArgs == null)
				return GetShortTypeName (name) + array;
			
			// Use the prettier name for nullable types
			if (name == "System.Nullable" && genericArgs.Count == 1)
				return genericArgs[0] + "?";
			
			// Insert the generic arguments next to each type.
			// for example: Foo`1+Bar`1[System.Int32,System.String]
			// is converted to: Foo<int>.Bar<string>
			StringBuilder sb = new StringBuilder (name);
			int i = typeEndIndex + 1;
			int genericIndex = 0;
			int argCount, next;
			
			while (i < genericEndIndex) {
				// decode the argument count
				argCount = 0;
				while (i < genericEndIndex && char.IsDigit (typeName[i])) {
					argCount = (argCount * 10) + (typeName[i] - '0');
					i++;
				}
				
				// insert the argument types
				sb.Append ('<');
				while (argCount > 0 && genericIndex < genericArgs.Count) {
					sb.Append (genericArgs[genericIndex++]);
					if (--argCount > 0)
						sb.Append (',');
				}
				sb.Append ('>');
				
				// Find the end of the next generic type component
				if ((next = typeName.IndexOf ('`', i, genericEndIndex - i)) == -1)
					next = genericEndIndex;
				
				// Append the next generic type component
				sb.Append (typeName.Substring (i, next - i));
				
				i = next;
			}
			
			return sb.ToString ();
		}
		
		List<string> GetGenericArguments (string typeName, ref int i, int endIndex)<commit_msg>[Debugger] Prevent infinite loop in parsing generic type names.<commit_after>using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Mono.Debugging.Client;
using Mono.Debugging.Backend;
using System.Diagnostics;
using System.Collections;

namespace Mono.Debugging.Evaluation
{
	public abstract class ObjectValueAdaptor: IDisposable
	{
		Dictionary<string, TypeDisplayData> typeDisplayData = new Dictionary<string, TypeDisplayData> ();

		// Time to wait while evaluating before switching to async mode
		public int DefaultEvaluationWaitTime { get; set; }
		
		public event EventHandler<BusyStateEventArgs> BusyStateChanged;
		
		AsyncEvaluationTracker asyncEvaluationTracker = new AsyncEvaluationTracker ();
		AsyncOperationManager asyncOperationManager = new AsyncOperationManager ();
		static Dictionary<string, string> netToCSharpTypes = new Dictionary<string, string> ();

		static ObjectValueAdaptor ()
		{
			netToCSharpTypes["System.Void"]    = "void";
			netToCSharpTypes["System.Object"]  = "object";
			netToCSharpTypes["System.Boolean"] = "bool";
			netToCSharpTypes["System.Byte"]    = "byte";
			netToCSharpTypes["System.SByte"]   = "sbyte";
			netToCSharpTypes["System.Char"]    = "char";
			netToCSharpTypes["System.Enum"]    = "enum";
			netToCSharpTypes["System.Int16"]   = "short";
			netToCSharpTypes["System.Int32"]   = "int";
			netToCSharpTypes["System.Int64"]   = "long";
			netToCSharpTypes["System.UInt16"]  = "ushort";
			netToCSharpTypes["System.UInt32"]  = "uint";
			netToCSharpTypes["System.UInt64"]  = "ulong";
			netToCSharpTypes["System.Single"]  = "float";
			netToCSharpTypes["System.Double"]  = "double";
			netToCSharpTypes["System.Decimal"] = "decimal";
			netToCSharpTypes["System.String"]  = "string";
		}
		
		public ObjectValueAdaptor ()
		{
			DefaultEvaluationWaitTime = 100;
			
			asyncOperationManager.BusyStateChanged += delegate(object sender, BusyStateEventArgs e) {
				OnBusyStateChanged (e);
			};
			asyncEvaluationTracker.WaitTime = DefaultEvaluationWaitTime;
		}
		
		public void Dispose ()
		{
			asyncEvaluationTracker.Dispose ();
			asyncOperationManager.Dispose ();
		}

		public ObjectValue CreateObjectValue (EvaluationContext ctx, IObjectValueSource source, ObjectPath path, object obj, ObjectValueFlags flags)
		{
			try {
				return CreateObjectValueImpl (ctx, source, path, obj, flags);
			} catch (Exception ex) {
				ctx.WriteDebuggerError (ex);
				return ObjectValue.CreateFatalError (path.LastName, ex.Message, flags);
			}
		}
		
		public virtual string GetDisplayTypeName (string typeName)
		{
			return GetDisplayTypeName (typeName.Replace ('+', '.'), 0, typeName.Length);
		}
		
		public string GetDisplayTypeName (EvaluationContext ctx, object type)
		{
			return GetDisplayTypeName (GetTypeName (ctx, type));
		}
		
		string GetDisplayTypeName (string typeName, int startIndex, int endIndex)
		{
			// Note: '[' denotes the start of an array
			//       '`' denotes a generic type
			//       ',' denotes the start of the assembly name
			int tokenIndex = typeName.IndexOfAny (new char [] { '[', '`', ',' }, startIndex, endIndex - startIndex);
			List<string> genericArgs = null;
			string array = string.Empty;
			int genericEndIndex = -1;
			int typeEndIndex;
			
			if (tokenIndex == -1) // Simple type
				return GetShortTypeName (typeName.Substring (startIndex, endIndex - startIndex));
			
			if (typeName[tokenIndex] == ',') // Simple type with an assembly name
				return GetShortTypeName (typeName.Substring (startIndex, tokenIndex - startIndex));
			
			// save the index of the end of the type name
			typeEndIndex = tokenIndex;
			
			// decode generic args first, if this is a generic type
			if (typeName[tokenIndex] == '`') {
				genericEndIndex = tokenIndex = typeName.IndexOf ('[', tokenIndex, endIndex - tokenIndex);
				genericArgs = GetGenericArguments (typeName, ref tokenIndex, endIndex);
			}
			
			// decode array rank info
			while (tokenIndex < endIndex && typeName[tokenIndex] == '[') {
				int arrayEndIndex = typeName.IndexOf (']', tokenIndex, endIndex - tokenIndex);
				if (arrayEndIndex == -1)
					break;
				arrayEndIndex++;
				array += typeName.Substring (tokenIndex, arrayEndIndex - tokenIndex);
				tokenIndex = arrayEndIndex;
			}
			
			string name = typeName.Substring (startIndex, typeEndIndex - startIndex);
			
			if (genericArgs == null)
				return GetShortTypeName (name) + array;
			
			// Use the prettier name for nullable types
			if (name == "System.Nullable" && genericArgs.Count == 1)
				return genericArgs[0] + "?";
			
			// Insert the generic arguments next to each type.
			// for example: Foo`1+Bar`1[System.Int32,System.String]
			// is converted to: Foo<int>.Bar<string>
			StringBuilder sb = new StringBuilder (name);
			int i = typeEndIndex + 1;
			int genericIndex = 0;
			int argCount, next;
			
			while (i < genericEndIndex) {
				// decode the argument count
				argCount = 0;
				while (i < genericEndIndex && char.IsDigit (typeName[i])) {
					argCount = (argCount * 10) + (typeName[i] - '0');
					i++;
				}
				
				// insert the argument types
				sb.Append ('<');
				while (argCount > 0 && genericIndex < genericArgs.Count) {
					sb.Append (genericArgs[genericIndex++]);
					if (--argCount > 0)
						sb.Append (',');
				}
				sb.Append ('>');
				
				// Find the end of the next generic type component
				if ((next = typeName.IndexOf ('`', i, genericEndIndex - i)) == -1)
					next = genericEndIndex;
				
				// Append the next generic type component
				sb.Append (typeName.Substring (i, next - i));
				
				i = next + 1;
			}
			
			return sb.ToString ();
		}
		
		List<string> GetGenericArguments (string typeName, ref int i, int endIndex)
{'fraction_non_alphanumeric': 0.11990240501917045, 'fraction_numerical': 0.0060125479261066575, 'mean_word_length': 3.598157051282051, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6986181', 'n_tokens_mistral': 4184, 'n_tokens_neox': 3393, 'n_words': 890}