DbgEngineEEAssignmentResult AssignCore(DbgEvaluationInfo evalInfo, string expression, string valueExpression, DbgEvaluationOptions options)
        {
            var resultFlags = DbgEEAssignmentResultFlags.None;

            try {
                var info       = dbgAliasProvider.GetAliases(evalInfo);
                var refsResult = dbgModuleReferenceProvider.GetModuleReferences(evalInfo.Runtime, evalInfo.Frame, info.typeReferences);
                if (refsResult.ErrorMessage != null)
                {
                    return(new DbgEngineEEAssignmentResult(resultFlags, refsResult.ErrorMessage));
                }

                var compRes = expressionCompiler.CompileAssignment(evalInfo, refsResult.ModuleReferences, info.aliases, expression, valueExpression, options);
                evalInfo.CancellationToken.ThrowIfCancellationRequested();
                if (compRes.IsError)
                {
                    return(new DbgEngineEEAssignmentResult(resultFlags | DbgEEAssignmentResultFlags.CompilerError, compRes.ErrorMessage));
                }

                var state = dnILInterpreter.CreateState(compRes.Assembly);
                Debug.Assert(compRes.CompiledExpressions.Length == 1);
                ref var exprInfo = ref compRes.CompiledExpressions[0];
                if (exprInfo.ErrorMessage != null)
                {
                    return(new DbgEngineEEAssignmentResult(resultFlags | DbgEEAssignmentResultFlags.CompilerError, exprInfo.ErrorMessage));
                }
                resultFlags |= DbgEEAssignmentResultFlags.ExecutedCode;
                var res = dnILInterpreter.Execute(evalInfo, state, exprInfo.TypeName, exprInfo.MethodName, options, out _);
                if (res.HasError)
                {
                    return(new DbgEngineEEAssignmentResult(resultFlags, res.ErrorMessage));
                }
                if (res.ValueIsException)
                {
                    res.Value.Dispose();
                    var error = string.Format(dnSpy_Debugger_DotNet_Resources.Method_X_ThrewAnExceptionOfType_Y, expression, res.Value.Type.FullName);
                    return(new DbgEngineEEAssignmentResult(resultFlags, error));
                }

                res.Value?.Dispose();
                return(new DbgEngineEEAssignmentResult());
            }
        DbgEngineLocalsValueNodeInfo[] GetNodesCore(DbgEvaluationInfo evalInfo, DbgValueNodeEvaluationOptions options, DbgLocalsValueNodeEvaluationOptions localsOptions)
        {
            DbgEngineLocalsValueNodeInfo[]? valueNodes = null;
            try {
                var module = evalInfo.Frame.Module;
                if (module is null)
                {
                    return(Array.Empty <DbgEngineLocalsValueNodeInfo>());
                }
                var languageDebugInfo = evalInfo.Context.TryGetLanguageDebugInfo();
                if (languageDebugInfo is null)
                {
                    return(Array.Empty <DbgEngineLocalsValueNodeInfo>());
                }
                var methodDebugInfo = languageDebugInfo.MethodDebugInfo;

                // All the variables windows use the same cached module references so make sure we pass
                // in the same arguments so it won't get recreated every time the method gets called.
                var info       = dbgAliasProvider.GetAliases(evalInfo);
                var refsResult = dbgModuleReferenceProvider.GetModuleReferences(evalInfo.Runtime, evalInfo.Frame, info.typeReferences);
                if (!(refsResult.ErrorMessage is null))
                {
                    return new[] { CreateInternalErrorNode(evalInfo, refsResult.ErrorMessage) }
                }
                ;
                Debug.Assert(!(refsResult.ModuleReferences is null));

                // Since we attach this to the module, the module doesn't have to be part of Key
                var state = StateWithKey <GetNodesState> .GetOrCreate(module, this);

                var localsOptionsKey = localsOptions & ~(DbgLocalsValueNodeEvaluationOptions.ShowCompilerGeneratedVariables | DbgLocalsValueNodeEvaluationOptions.ShowDecompilerGeneratedVariables);
                var key = new GetNodesState.Key(methodDebugInfo.DebugInfoVersion,
                                                methodDebugInfo.Method.MDToken.ToInt32(), languageDebugInfo.MethodVersion,
                                                refsResult.ModuleReferences, MethodDebugScopeUtils.GetScope(methodDebugInfo.Scope, languageDebugInfo.ILOffset),
                                                options, localsOptionsKey);

                var evalOptions = DbgEvaluationOptions.None;
                if ((options & DbgValueNodeEvaluationOptions.NoFuncEval) != 0)
                {
                    evalOptions |= DbgEvaluationOptions.NoFuncEval;
                }
                if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowRawLocals) != 0)
                {
                    evalOptions |= DbgEvaluationOptions.RawLocals;
                }

                ValueInfo[] valueInfos;
                byte[]      assemblyBytes;
                int         compilerGeneratedCount;
                int         decompilerGeneratedCount;
                if (key.Equals(state.CachedKey))
                {
                    valueInfos               = state.CachedValueInfos;
                    assemblyBytes            = state.CachedAssemblyBytes;
                    decompilerGeneratedCount = state.CachedDecompilerGeneratedCount;
                    compilerGeneratedCount   = state.CachedCompilerGeneratedCount;
                }
                else
                {
                    var compilationResult = expressionCompiler.CompileGetLocals(evalInfo, refsResult.ModuleReferences, evalOptions);
                    evalInfo.CancellationToken.ThrowIfCancellationRequested();
                    if (compilationResult.IsError)
                    {
                        return new[] { CreateInternalErrorNode(evalInfo, compilationResult.ErrorMessage !) }
        DbgEngineLocalsValueNodeInfo[] GetNodesCore(DbgEvaluationInfo evalInfo, DbgValueNodeEvaluationOptions options, DbgLocalsValueNodeEvaluationOptions localsOptions)
        {
            DbgEngineLocalsValueNodeInfo[] valueNodes = null;
            try {
                var module = evalInfo.Frame.Module;
                if (module == null)
                {
                    return(Array.Empty <DbgEngineLocalsValueNodeInfo>());
                }
                var languageDebugInfo = evalInfo.Context.TryGetLanguageDebugInfo();
                if (languageDebugInfo == null)
                {
                    return(Array.Empty <DbgEngineLocalsValueNodeInfo>());
                }
                var methodDebugInfo = languageDebugInfo.MethodDebugInfo;

                // All the variables windows use the same cached module references so make sure we pass
                // in the same arguments so it won't get recreated every time the method gets called.
                var info       = dbgAliasProvider.GetAliases(evalInfo);
                var refsResult = dbgModuleReferenceProvider.GetModuleReferences(evalInfo.Runtime, evalInfo.Frame, info.typeReferences);
                if (refsResult.ErrorMessage != null)
                {
                    return new[] { CreateInternalErrorNode(evalInfo, refsResult.ErrorMessage) }
                }
                ;

                // Since we attach this to the module, the module doesn't have to be part of Key
                var state = StateWithKey <GetNodesState> .GetOrCreate(module, this);

                var localsOptionsKey = localsOptions & ~(DbgLocalsValueNodeEvaluationOptions.ShowCompilerGeneratedVariables | DbgLocalsValueNodeEvaluationOptions.ShowDecompilerGeneratedVariables);
                var key = new GetNodesState.Key(methodDebugInfo.DecompilerSettingsVersion,
                                                methodDebugInfo.Method.MDToken.ToInt32(), languageDebugInfo.MethodVersion,
                                                refsResult.ModuleReferences, MethodDebugScopeUtils.GetScope(methodDebugInfo.Scope, languageDebugInfo.ILOffset),
                                                options, localsOptionsKey);

                var evalOptions = DbgEvaluationOptions.None;
                if ((options & DbgValueNodeEvaluationOptions.NoFuncEval) != 0)
                {
                    evalOptions |= DbgEvaluationOptions.NoFuncEval;
                }
                if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowRawLocals) != 0)
                {
                    evalOptions |= DbgEvaluationOptions.RawLocals;
                }

                ValueInfo[] valueInfos;
                byte[]      assemblyBytes;
                int         compilerGeneratedCount;
                int         decompilerGeneratedCount;
                if (key.Equals(state.CachedKey))
                {
                    valueInfos               = state.CachedValueInfos;
                    assemblyBytes            = state.CachedAssemblyBytes;
                    decompilerGeneratedCount = state.CachedDecompilerGeneratedCount;
                    compilerGeneratedCount   = state.CachedCompilerGeneratedCount;
                }
                else
                {
                    var compilationResult = expressionCompiler.CompileGetLocals(evalInfo, refsResult.ModuleReferences, evalOptions);
                    evalInfo.CancellationToken.ThrowIfCancellationRequested();
                    if (compilationResult.IsError)
                    {
                        return new[] { CreateInternalErrorNode(evalInfo, compilationResult.ErrorMessage) }
                    }
                    ;

                    decompilerGeneratedCount = GetDecompilerGeneratedVariablesCount(methodDebugInfo.Scope, languageDebugInfo.ILOffset);

                    valueInfos = new ValueInfo[compilationResult.CompiledExpressions.Length + decompilerGeneratedCount];
                    int valueInfosIndex = 0;
                    compilerGeneratedCount = 0;
                    for (int i = 0; i < compilationResult.CompiledExpressions.Length; i++, valueInfosIndex++)
                    {
                        if ((compilationResult.CompiledExpressions[i].ResultFlags & DbgDotNetCompiledExpressionResultFlags.CompilerGenerated) != 0)
                        {
                            compilerGeneratedCount++;
                        }
                        valueInfos[valueInfosIndex] = new CompiledExpressionValueInfo(compilationResult.CompiledExpressions, i);
                    }

                    if (decompilerGeneratedCount > 0)
                    {
                        var scope = methodDebugInfo.Scope;
                        for (;;)
                        {
                            foreach (var local in scope.Locals)
                            {
                                if (local.IsDecompilerGenerated)
                                {
                                    valueInfos[valueInfosIndex] = new DecompilerGeneratedVariableValueInfo(local.Name);
                                    valueInfosIndex++;
                                }
                            }

                            bool found = false;
                            foreach (var childScope in scope.Scopes)
                            {
                                if (childScope.Span.Start <= languageDebugInfo.ILOffset && languageDebugInfo.ILOffset < childScope.Span.End)
                                {
                                    found = true;
                                    scope = childScope;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                break;
                            }
                        }
                    }

                    if (valueInfos.Length != valueInfosIndex)
                    {
                        throw new InvalidOperationException();
                    }

                    assemblyBytes                        = compilationResult.Assembly;
                    state.CachedKey                      = key;
                    state.CachedValueInfos               = valueInfos;
                    state.CachedAssemblyBytes            = assemblyBytes;
                    state.CachedILInterpreterState       = null;
                    state.CachedDecompilerGeneratedCount = decompilerGeneratedCount;
                    state.CachedCompilerGeneratedCount   = compilerGeneratedCount;
                }

                int count = valueInfos.Length;
                if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowCompilerGeneratedVariables) == 0)
                {
                    count -= compilerGeneratedCount;
                }
                if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowDecompilerGeneratedVariables) == 0)
                {
                    count -= decompilerGeneratedCount;
                }
                valueNodes = count == 0 ? Array.Empty <DbgEngineLocalsValueNodeInfo>() : new DbgEngineLocalsValueNodeInfo[count];
                var valueCreator = new DbgDotNetValueCreator(valueNodeFactory, dnILInterpreter, evalInfo, options, evalOptions, assemblyBytes);
                int w            = 0;
                for (int i = 0; i < valueInfos.Length; i++)
                {
                    evalInfo.CancellationToken.ThrowIfCancellationRequested();
                    var valueInfo = valueInfos[i];

                    DbgEngineLocalsValueNodeInfo valueNodeInfo;
                    switch (valueInfo.Kind)
                    {
                    case ValueInfoKind.CompiledExpression:
                        var compExpr = (CompiledExpressionValueInfo)valueInfo;
                        if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowCompilerGeneratedVariables) == 0 && compExpr.IsCompilerGenerated)
                        {
                            continue;
                        }
                        valueNodeInfo = new DbgEngineLocalsValueNodeInfo(
                            compExpr.IsParameter ? DbgLocalsValueNodeKind.Parameter : DbgLocalsValueNodeKind.Local,
                            valueCreator.CreateValueNode(ref state.CachedILInterpreterState, ref compExpr.CompiledExpressionResult));
                        break;

                    case ValueInfoKind.DecompilerGeneratedVariable:
                        if ((localsOptions & DbgLocalsValueNodeEvaluationOptions.ShowDecompilerGeneratedVariables) == 0)
                        {
                            continue;
                        }
                        var decGen = (DecompilerGeneratedVariableValueInfo)valueInfo;
                        valueNodeInfo = new DbgEngineLocalsValueNodeInfo(DbgLocalsValueNodeKind.Local,
                                                                         valueNodeFactory.CreateError(evalInfo,
                                                                                                      new DbgDotNetText(new DbgDotNetTextPart(DbgTextColor.Local, decGen.Name)),
                                                                                                      dnSpy_Debugger_DotNet_Resources.DecompilerGeneratedVariablesCanNotBeEvaluated,
                                                                                                      decGen.Name, false));
                        break;

                    default:
                        throw new InvalidOperationException();
                    }

                    valueNodes[w++] = valueNodeInfo;
                }
                if (w != valueNodes.Length)
                {
                    throw new InvalidOperationException();
                }

                return(valueNodes);
            }
            catch (Exception ex) {
                if (valueNodes != null)
                {
                    evalInfo.Runtime.Process.DbgManager.Close(valueNodes.Select(a => a.ValueNode).Where(a => a != null));
                }
                if (!ExceptionUtils.IsInternalDebuggerError(ex))
                {
                    throw;
                }
                return(new[] { CreateInternalErrorNode(evalInfo, PredefinedEvaluationErrorMessages.InternalDebuggerError) });
            }
        }