<commit_before>// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.Editor.Implementation.EditAndContinue;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Notification;
using Microsoft.CodeAnalysis.Text;
using Microsoft.DiaSymReader;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.LanguageServices.Implementation.EditAndContinue.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.Utilities;
using Roslyn.Utilities;
using ShellInterop = Microsoft.VisualStudio.Shell.Interop;
using VsTextSpan = Microsoft.VisualStudio.TextManager.Interop.TextSpan;
using VsThreading = Microsoft.VisualStudio.Threading;
using Document = Microsoft.CodeAnalysis.Document;
using Microsoft.CodeAnalysis.Debugging;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.EditAndContinue
{
    internal sealed class VsENCRebuildableProjectImpl
    {
        private readonly AbstractProject _vsProject;

        // number of projects that are in the debug state:
        private static int s_debugStateProjectCount;

        // number of projects that are in the break state:
        private static int s_breakStateProjectCount;

        // projects that entered the break state:
        private static readonly List<KeyValuePair<ProjectId, ProjectReadOnlyReason>> s_breakStateEnteredProjects = new List<KeyValuePair<ProjectId, ProjectReadOnlyReason>>();

        // active statements of projects that entered the break state:
        private static readonly List<VsActiveStatement> s_pendingActiveStatements = new List<VsActiveStatement>();

        private static VsReadOnlyDocumentTracker s_readOnlyDocumentTracker;

        internal static readonly TraceLog log = new TraceLog(2048, "EnC");

        private static Solution s_breakStateEntrySolution;

        private static EncDebuggingSessionInfo s_encDebuggingSessionInfo;

        private readonly IEditAndContinueWorkspaceService _encService;
        private readonly IActiveStatementTrackingService _trackingService;
        private readonly EditAndContinueDiagnosticUpdateSource _diagnosticProvider;
        private readonly IDebugEncNotify _debugEncNotify;
        private readonly INotificationService _notifications;
        private readonly IVsEditorAdaptersFactoryService _editorAdaptersFactoryService;

        #region Per Project State

        private bool _changesApplied;

        // maps VS Active Statement Id, which is unique within this project, to our id
        private Dictionary<uint, ActiveStatementId> _activeStatementIds;

        private ProjectAnalysisSummary _lastEditSessionSummary = ProjectAnalysisSummary.NoChanges;
        private HashSet<uint> _activeMethods;
        private List<VsExceptionRegion> _exceptionRegions;
        private EmitBaseline _committedBaseline;
        private EmitBaseline _pendingBaseline;
        private Project _projectBeingEmitted;

        private ImmutableArray<DocumentId> _documentsWithEmitError = ImmutableArray<DocumentId>.Empty;

        /// <summary>
        /// Initialized when the project switches to debug state.
        /// Null if the project has no output file or we can't read the MVID.
        /// </summary>
        private ModuleMetadata _metadata;

        private ISymUnmanagedReader3 _pdbReader;

        private IntPtr _pdbReaderObjAsStream;

        #endregion

        private bool IsDebuggable
        {
            get { return _metadata != null; }
        }

        internal VsENCRebuildableProjectImpl(AbstractProject project)
        {
            _vsProject = project;

            _encService = _vsProject.Workspace.Services.GetService<IEditAndContinueWorkspaceService>();
            _trackingService = _vsProject.Workspace.Services.GetService<IActiveStatementTrackingService>();
            _notifications = _vsProject.Workspace.Services.GetService<INotificationService>();

            _debugEncNotify = (IDebugEncNotify)project.ServiceProvider.GetService(typeof(ShellInterop.SVsShellDebugger));

            var componentModel = (IComponentModel)project.ServiceProvider.GetService(typeof(SComponentModel));
            _diagnosticProvider = componentModel.GetService<EditAndContinueDiagnosticUpdateSource>();
            _editorAdaptersFactoryService = componentModel.GetService<IVsEditorAdaptersFactoryService>();

            Debug.Assert(_encService != null);
            Debug.Assert(_trackingService != null);
            Debug.Assert(_diagnosticProvider != null);
            Debug.Assert(_editorAdaptersFactoryService != null);
        }

        // called from an edit filter if an edit of a read-only buffer is attempted:
        internal bool OnEdit(DocumentId documentId)
        {
            if (_encService.IsProjectReadOnly(documentId.ProjectId, out var sessionReason, out var projectReason))
            {
                OnReadOnlyDocumentEditAttempt(documentId, sessionReason, projectReason);
                return true;
            }

            return false;
        }

        private void OnReadOnlyDocumentEditAttempt(
            DocumentId documentId,
            SessionReadOnlyReason sessionReason,
            ProjectReadOnlyReason projectReason)
        {
            if (sessionReason == SessionReadOnlyReason.StoppedAtException)
            {
                _debugEncNotify.NotifyEncEditAttemptedAtInvalidStopState();
                return;
            }

            var visualStudioWorkspace = _vsProject.Workspace as VisualStudioWorkspaceImpl;
            var hostProject = visualStudioWorkspace?.GetHostProject(documentId.ProjectId) as AbstractProject;
            if (hostProject?.EditAndContinueImplOpt?._metadata != null)
            {
                _debugEncNotify.NotifyEncEditDisallowedByProject(hostProject.Hierarchy);
                return;
            }

            // NotifyEncEditDisallowedByProject is broken if the project isn't built at the time the debugging starts (debugger bug 877586).

            string message;
            if (sessionReason == SessionReadOnlyReason.Running)
            {
                message = "Changes are not allowed while code is running.";
            }
            else
            {
                Debug.Assert(sessionReason == SessionReadOnlyReason.None);

                switch (projectReason)
                {
                    case ProjectReadOnlyReason.MetadataNotAvailable:
                        message = "Changes are not allowed if the project wasn't built when debugging started.";
                        break;

                    case ProjectReadOnlyReason.NotLoaded:
                        message = "Changes are not allowed if the assembly has not been loaded.";
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(projectReason);
                }
            }
<commit_msg>Improve EnC error message when DPL is on<commit_after>// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.EditAndContinue;
using Microsoft.CodeAnalysis.Editor.Implementation.EditAndContinue;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Notification;
using Microsoft.CodeAnalysis.Text;
using Microsoft.DiaSymReader;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Editor;
using Microsoft.VisualStudio.LanguageServices.Implementation.EditAndContinue.Interop;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem;
using Microsoft.VisualStudio.LanguageServices.Utilities;
using Roslyn.Utilities;
using ShellInterop = Microsoft.VisualStudio.Shell.Interop;
using VsTextSpan = Microsoft.VisualStudio.TextManager.Interop.TextSpan;
using VsThreading = Microsoft.VisualStudio.Threading;
using Document = Microsoft.CodeAnalysis.Document;
using Microsoft.CodeAnalysis.Debugging;
using Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem.Interop;
using Microsoft.VisualStudio.Shell.Interop;

namespace Microsoft.VisualStudio.LanguageServices.Implementation.EditAndContinue
{
    internal sealed class VsENCRebuildableProjectImpl
    {
        private readonly AbstractProject _vsProject;

        // number of projects that are in the debug state:
        private static int s_debugStateProjectCount;

        // number of projects that are in the break state:
        private static int s_breakStateProjectCount;

        // projects that entered the break state:
        private static readonly List<KeyValuePair<ProjectId, ProjectReadOnlyReason>> s_breakStateEnteredProjects = new List<KeyValuePair<ProjectId, ProjectReadOnlyReason>>();

        // active statements of projects that entered the break state:
        private static readonly List<VsActiveStatement> s_pendingActiveStatements = new List<VsActiveStatement>();

        private static VsReadOnlyDocumentTracker s_readOnlyDocumentTracker;

        internal static readonly TraceLog log = new TraceLog(2048, "EnC");

        private static Solution s_breakStateEntrySolution;

        private static EncDebuggingSessionInfo s_encDebuggingSessionInfo;

        private readonly IEditAndContinueWorkspaceService _encService;
        private readonly IActiveStatementTrackingService _trackingService;
        private readonly EditAndContinueDiagnosticUpdateSource _diagnosticProvider;
        private readonly IDebugEncNotify _debugEncNotify;
        private readonly INotificationService _notifications;
        private readonly IVsEditorAdaptersFactoryService _editorAdaptersFactoryService;

        #region Per Project State

        private bool _changesApplied;

        // maps VS Active Statement Id, which is unique within this project, to our id
        private Dictionary<uint, ActiveStatementId> _activeStatementIds;

        private ProjectAnalysisSummary _lastEditSessionSummary = ProjectAnalysisSummary.NoChanges;
        private HashSet<uint> _activeMethods;
        private List<VsExceptionRegion> _exceptionRegions;
        private EmitBaseline _committedBaseline;
        private EmitBaseline _pendingBaseline;
        private Project _projectBeingEmitted;

        private ImmutableArray<DocumentId> _documentsWithEmitError = ImmutableArray<DocumentId>.Empty;

        /// <summary>
        /// Initialized when the project switches to debug state.
        /// Null if the project has no output file or we can't read the MVID.
        /// </summary>
        private ModuleMetadata _metadata;

        private ISymUnmanagedReader3 _pdbReader;

        private IntPtr _pdbReaderObjAsStream;

        #endregion

        private bool IsDebuggable
        {
            get { return _metadata != null; }
        }

        internal VsENCRebuildableProjectImpl(AbstractProject project)
        {
            _vsProject = project;

            _encService = _vsProject.Workspace.Services.GetService<IEditAndContinueWorkspaceService>();
            _trackingService = _vsProject.Workspace.Services.GetService<IActiveStatementTrackingService>();
            _notifications = _vsProject.Workspace.Services.GetService<INotificationService>();

            _debugEncNotify = (IDebugEncNotify)project.ServiceProvider.GetService(typeof(ShellInterop.SVsShellDebugger));

            var componentModel = (IComponentModel)project.ServiceProvider.GetService(typeof(SComponentModel));
            _diagnosticProvider = componentModel.GetService<EditAndContinueDiagnosticUpdateSource>();
            _editorAdaptersFactoryService = componentModel.GetService<IVsEditorAdaptersFactoryService>();

            Debug.Assert(_encService != null);
            Debug.Assert(_trackingService != null);
            Debug.Assert(_diagnosticProvider != null);
            Debug.Assert(_editorAdaptersFactoryService != null);
        }

        // called from an edit filter if an edit of a read-only buffer is attempted:
        internal bool OnEdit(DocumentId documentId)
        {
            if (_encService.IsProjectReadOnly(documentId.ProjectId, out var sessionReason, out var projectReason))
            {
                OnReadOnlyDocumentEditAttempt(documentId, sessionReason, projectReason);
                return true;
            }

            return false;
        }

        private void OnReadOnlyDocumentEditAttempt(
            DocumentId documentId,
            SessionReadOnlyReason sessionReason,
            ProjectReadOnlyReason projectReason)
        {
            if (sessionReason == SessionReadOnlyReason.StoppedAtException)
            {
                _debugEncNotify.NotifyEncEditAttemptedAtInvalidStopState();
                return;
            }

            var visualStudioWorkspace = _vsProject.Workspace as VisualStudioWorkspaceImpl;
            var hostProject = visualStudioWorkspace?.GetHostProject(documentId.ProjectId) as AbstractProject;
            if (hostProject?.EditAndContinueImplOpt?._metadata != null)
            {
                _debugEncNotify.NotifyEncEditDisallowedByProject(hostProject.Hierarchy);
                return;
            }

            // NotifyEncEditDisallowedByProject is broken if the project isn't built at the time the debugging starts (debugger bug 877586).

            string message;
            if (sessionReason == SessionReadOnlyReason.Running)
            {
                message = "Changes are not allowed while code is running.";
            }
            else
            {
                Debug.Assert(sessionReason == SessionReadOnlyReason.None);

                switch (projectReason)
                {
                    case ProjectReadOnlyReason.MetadataNotAvailable:
                        bool deferredLoad = (_vsProject.ServiceProvider.GetService(typeof(SVsSolution)) as IVsSolution7)?.IsSolutionLoadDeferred() == true;
                        if (deferredLoad)
                        {
                            message = "Changes are not allowed if the project wasn't loaded and built when debugging started." + Environment.NewLine + 
                                      Environment.NewLine +
                                      "'Lightweight solution load' is enabled for the current solution. " +
                                      "Disable it to ensure that all projects are loaded when debugging starts.";
                        }
                        else
                        {
                            message = "Changes are not allowed if the project wasn't built when debugging started.";
                        }
                        break;

                    case ProjectReadOnlyReason.NotLoaded:
                        message = "Changes are not allowed if the assembly has not been loaded.";
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(projectReason);
                }
            }

{'fraction_non_alphanumeric': 0.05897626112759644, 'fraction_numerical': 0.002040059347181009, 'mean_word_length': 2.844344106463878, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6820644', 'n_tokens_mistral': 3775, 'n_tokens_neox': 3620, 'n_words': 960}