<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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis
{
    public abstract partial class Workspace
    {
        private readonly EventMap _eventMap = new EventMap();
        private const string WorkspaceChangeEventName = "WorkspaceChanged";
        private const string WorkspaceFailedEventName = "WorkspaceFailed";
        private const string DocumentOpenedEventName = "DocumentOpened";
        private const string DocumentClosedEventName = "DocumentClosed";
        private const string DocumentActiveContextChangedName = "DocumentActiveContextChanged";

        /// <summary>
        /// An event raised whenever the current solution is changed.
        /// </summary>
        public event EventHandler<WorkspaceChangeEventArgs> WorkspaceChanged
        {
            add
            {
                _eventMap.AddEventHandler(WorkspaceChangeEventName, value);
            }

            remove
            {
                _eventMap.RemoveEventHandler(WorkspaceChangeEventName, value);
            }
        }

        protected Task RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind kind, Solution oldSolution, Solution newSolution, ProjectId projectId = null, DocumentId documentId = null)
        {
            if (newSolution == null)
            {
                throw new ArgumentNullException(nameof(newSolution));
            }

            if (oldSolution == newSolution)
            {
                return Task.CompletedTask;
            }

            if (projectId == null && documentId != null)
            {
                projectId = documentId.ProjectId;
            }

            var ev = _eventMap.GetEventHandlers<EventHandler<WorkspaceChangeEventArgs>>(WorkspaceChangeEventName);
            if (ev.HasHandlers)
            {
                return this.ScheduleTask(() =>
                {
                    using (Logger.LogBlock(FunctionId.Workspace_Events, (s, p, d, k) => $"{s.Id} - {p} - {d} {kind.ToString()}", newSolution, projectId, documentId, kind, CancellationToken.None))
                    {
                        var args = new WorkspaceChangeEventArgs(kind, oldSolution, newSolution, projectId, documentId);
                        ev.RaiseEvent(handler => handler(this, args));
                    }
                }, "Workspace.WorkspaceChanged");
            }
            else
            {
                return Task.CompletedTask;
            }
        }

        /// <summary>
        /// An event raised whenever the workspace or part of its solution model
        /// fails to access a file or other external resource.
        /// </summary>
        public event EventHandler<WorkspaceDiagnosticEventArgs> WorkspaceFailed
        {
            add
            {
                _eventMap.AddEventHandler(WorkspaceFailedEventName, value);
            }

            remove
            {
                _eventMap.RemoveEventHandler(WorkspaceFailedEventName, value);
            }
        }

        protected internal virtual void OnWorkspaceFailed(WorkspaceDiagnostic diagnostic)
        {
            var ev = _eventMap.GetEventHandlers<EventHandler<WorkspaceDiagnosticEventArgs>>(WorkspaceFailedEventName);
            if (ev.HasHandlers)
            {
                var args = new WorkspaceDiagnosticEventArgs(diagnostic);
                ev.RaiseEvent(handler => handler(this, args));
            }
        }

        /// <summary>
        /// An event that is fired when a documents is opened in the editor.
        /// </summary>
        public event EventHandler<DocumentEventArgs> DocumentOpened
        {
            add
            {
                _eventMap.AddEventHandler(DocumentOpenedEventName, value);
            }

            remove
            {
                _eventMap.RemoveEventHandler(DocumentOpenedEventName, value);
            }
        }

        protected Task RaiseDocumentOpenedEventAsync(Document document)
        {
            var ev = _eventMap.GetEventHandlers<EventHandler<DocumentEventArgs>>(DocumentOpenedEventName);
            if (ev.HasHandlers && document != null)
            {
                return this.ScheduleTask(() =>
                {
                    var args = new DocumentEventArgs(document);
                    ev.RaiseEvent(handler => handler(this, args));
                }, "Workspace.WorkspaceChanged");
            }
            else
            {
                return Task.CompletedTask;
            }
        }

        /// <summary>
        /// An event that is fired when a document is closed in the editor.
        /// </summary>
        public event EventHandler<DocumentEventArgs> DocumentClosed
        {
            add
            {
                _eventMap.AddEventHandler(DocumentClosedEventName, value);
            }

            remove
            {
                _eventMap.RemoveEventHandler(DocumentClosedEventName, value);
            }
        }

        protected Task RaiseDocumentClosedEventAsync(Document document)
        {
            var ev = _eventMap.GetEventHandlers<EventHandler<DocumentEventArgs>>(DocumentClosedEventName);
            if (ev.HasHandlers && document != null)
            {
                return this.ScheduleTask(() =>
                {
                    var args = new DocumentEventArgs(document);
                    ev.RaiseEvent(handler => handler(this, args));
                }, "Workspace.DocumentClosed");
            }
            else
            {
                return Task.CompletedTask;
            }
        }

        /// <summary>
        /// An event that is fired when the active context document associated with a buffer 
        /// changes.
        /// </summary>
        public event EventHandler<DocumentActiveContextChangedEventArgs> DocumentActiveContextChanged
        {<commit_msg>Use existing constants rather than hard copied strings<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.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis
{
    public abstract partial class Workspace
    {
        private readonly EventMap _eventMap = new EventMap();
        private const string WorkspaceChangeEventName = "WorkspaceChanged";
        private const string WorkspaceFailedEventName = "WorkspaceFailed";
        private const string DocumentOpenedEventName = "DocumentOpened";
        private const string DocumentClosedEventName = "DocumentClosed";
        private const string DocumentActiveContextChangedName = "DocumentActiveContextChanged";

        /// <summary>
        /// An event raised whenever the current solution is changed.
        /// </summary>
        public event EventHandler<WorkspaceChangeEventArgs> WorkspaceChanged
        {
            add
            {
                _eventMap.AddEventHandler(WorkspaceChangeEventName, value);
            }

            remove
            {
                _eventMap.RemoveEventHandler(WorkspaceChangeEventName, value);
            }
        }

        protected Task RaiseWorkspaceChangedEventAsync(WorkspaceChangeKind kind, Solution oldSolution, Solution newSolution, ProjectId projectId = null, DocumentId documentId = null)
        {
            if (newSolution == null)
            {
                throw new ArgumentNullException(nameof(newSolution));
            }

            if (oldSolution == newSolution)
            {
                return Task.CompletedTask;
            }

            if (projectId == null && documentId != null)
            {
                projectId = documentId.ProjectId;
            }

            var ev = _eventMap.GetEventHandlers<EventHandler<WorkspaceChangeEventArgs>>(WorkspaceChangeEventName);
            if (ev.HasHandlers)
            {
                return this.ScheduleTask(() =>
                {
                    using (Logger.LogBlock(FunctionId.Workspace_Events, (s, p, d, k) => $"{s.Id} - {p} - {d} {kind.ToString()}", newSolution, projectId, documentId, kind, CancellationToken.None))
                    {
                        var args = new WorkspaceChangeEventArgs(kind, oldSolution, newSolution, projectId, documentId);
                        ev.RaiseEvent(handler => handler(this, args));
                    }
                }, WorkspaceChangeEventName);
            }
            else
            {
                return Task.CompletedTask;
            }
        }

        /// <summary>
        /// An event raised whenever the workspace or part of its solution model
        /// fails to access a file or other external resource.
        /// </summary>
        public event EventHandler<WorkspaceDiagnosticEventArgs> WorkspaceFailed
        {
            add
            {
                _eventMap.AddEventHandler(WorkspaceFailedEventName, value);
            }

            remove
            {
                _eventMap.RemoveEventHandler(WorkspaceFailedEventName, value);
            }
        }

        protected internal virtual void OnWorkspaceFailed(WorkspaceDiagnostic diagnostic)
        {
            var ev = _eventMap.GetEventHandlers<EventHandler<WorkspaceDiagnosticEventArgs>>(WorkspaceFailedEventName);
            if (ev.HasHandlers)
            {
                var args = new WorkspaceDiagnosticEventArgs(diagnostic);
                ev.RaiseEvent(handler => handler(this, args));
            }
        }

        /// <summary>
        /// An event that is fired when a documents is opened in the editor.
        /// </summary>
        public event EventHandler<DocumentEventArgs> DocumentOpened
        {
            add
            {
                _eventMap.AddEventHandler(DocumentOpenedEventName, value);
            }

            remove
            {
                _eventMap.RemoveEventHandler(DocumentOpenedEventName, value);
            }
        }

        protected Task RaiseDocumentOpenedEventAsync(Document document)
        {
            var ev = _eventMap.GetEventHandlers<EventHandler<DocumentEventArgs>>(DocumentOpenedEventName);
            if (ev.HasHandlers && document != null)
            {
                return this.ScheduleTask(() =>
                {
                    var args = new DocumentEventArgs(document);
                    ev.RaiseEvent(handler => handler(this, args));
                }, DocumentOpenedEventName);
            }
            else
            {
                return Task.CompletedTask;
            }
        }

        /// <summary>
        /// An event that is fired when a document is closed in the editor.
        /// </summary>
        public event EventHandler<DocumentEventArgs> DocumentClosed
        {
            add
            {
                _eventMap.AddEventHandler(DocumentClosedEventName, value);
            }

            remove
            {
                _eventMap.RemoveEventHandler(DocumentClosedEventName, value);
            }
        }

        protected Task RaiseDocumentClosedEventAsync(Document document)
        {
            var ev = _eventMap.GetEventHandlers<EventHandler<DocumentEventArgs>>(DocumentClosedEventName);
            if (ev.HasHandlers && document != null)
            {
                return this.ScheduleTask(() =>
                {
                    var args = new DocumentEventArgs(document);
                    ev.RaiseEvent(handler => handler(this, args));
                }, DocumentClosedEventName);
            }
            else
            {
                return Task.CompletedTask;
            }
        }

        /// <summary>
        /// An event that is fired when the active context document associated with a buffer 
        /// changes.
        /// </summary>
        public event EventHandler<DocumentActiveContextChangedEventArgs> DocumentActiveContextChanged
        {
{'fraction_non_alphanumeric': 0.07733593559404733, 'fraction_numerical': 0.0003252825892494104, 'mean_word_length': 1.7046404222564329, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 65, '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': '7247254', 'n_tokens_mistral': 2815, 'n_tokens_neox': 2751, 'n_words': 673}