{"action":"created","comment":{"url":"https://api.github.com/repos/dotnet/roslyn/pulls/comments/24776155","id":24776155,"diff_hunk":"@@ -0,0 +1,138 @@\n+﻿// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.\n+\n+using System;\n+using System.Collections.Concurrent;\n+using System.Collections.Generic;\n+using System.Collections.Immutable;\n+using System.Diagnostics;\n+using System.Runtime.CompilerServices;\n+using System.Threading;\n+using System.Threading.Tasks;\n+\n+namespace Microsoft.CodeAnalysis.Diagnostics\n+{\n+    /// <summary>\n+    /// Manages properties of analyzers (such as registered actions, supported diagnostics) for analyzer host's lifetime.\n+    /// \n+    /// It ensures the following for the lifetime of analyzer host:\n+    /// 1) <see cref=\"DiagnosticAnalyzer.Initialize(AnalysisContext)\"/> is invoked only once per-analyzer.\n+    /// 2) <see cref=\"DiagnosticAnalyzer.SupportedDiagnostics\"/> is invoked only once per-analyzer.\n+    /// 3) <see cref=\"CompilationStartAnalyzerAction\"/> registered during Initialize are invoked only once per-analyzer per-compilation.\n+    /// </summary>\n+    internal class AnalyzerManager\n+    {\n+        public static readonly AnalyzerManager Default = new AnalyzerManager();\n+\n+        // This map stores the tasks to compute HostSessionStartAnalysisScope for session wide analyzer actions, i.e. AnalyzerActions registered by analyzer's Initialize method.\n+        // These are run only once per every analyzer.\n+        private ImmutableDictionary<DiagnosticAnalyzer, Task<HostSessionStartAnalysisScope>> _sessionScopeMap =\n+            ImmutableDictionary<DiagnosticAnalyzer, Task<HostSessionStartAnalysisScope>>.Empty;\n+\n+        // This map stores the tasks to compute HostCompilationStartAnalysisScope for per-compilation analyzer actions, i.e. AnalyzerActions registered by analyzer's CompilationStartActions.\n+        // Compilation start actions will get executed once per-each compilation as user might want to return different set of custom actions for each compilation.\n+        private readonly ConditionalWeakTable<Compilation, ConcurrentDictionary<DiagnosticAnalyzer, Task<HostCompilationStartAnalysisScope>>> _compilationScopeMap =\n+            new ConditionalWeakTable<Compilation, ConcurrentDictionary<DiagnosticAnalyzer, Task<HostCompilationStartAnalysisScope>>>();\n+\n+        /// <summary>\n+        /// Cache descriptors for each diagnostic analyzer. We do this since <see cref=\"DiagnosticAnalyzer.SupportedDiagnostics\"/> is\n+        /// a property rather than metadata. We expect it to be cheap and immutable, but we can't force them to be so, we cache them\n+        /// and ask only once.\n+        /// </summary>\n+        private readonly ConditionalWeakTable<DiagnosticAnalyzer, IReadOnlyList<DiagnosticDescriptor>> _descriptorCache =","path":"src/Compilers/Core/AnalyzerDriver/AnalyzerManager.cs","position":41,"original_position":41,"commit_id":"22f25efaae49a32fef659a1b9c1e072a99dbbeb8","original_commit_id":"22f25efaae49a32fef659a1b9c1e072a99dbbeb8","user":{"login":"JohnHamby","id":10982715,"avatar_url":"https://avatars.githubusercontent.com/u/10982715?v=3","gravatar_id":"","url":"https://api.github.com/users/JohnHamby","html_url":"https://github.com/JohnHamby","followers_url":"https://api.github.com/users/JohnHamby/followers","following_url":"https://api.github.com/users/JohnHamby/following{/other_user}","gists_url":"https://api.github.com/users/JohnHamby/gists{/gist_id}","starred_url":"https://api.github.com/users/JohnHamby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JohnHamby/subscriptions","organizations_url":"https://api.github.com/users/JohnHamby/orgs","repos_url":"https://api.github.com/users/JohnHamby/repos","events_url":"https://api.github.com/users/JohnHamby/events{/privacy}","received_events_url":"https://api.github.com/users/JohnHamby/received_events","type":"User","site_admin":false},"body":"Why is _sessionScope a dictionary and _descriptorCache a conditional weak table?","created_at":"2015-02-16T21:11:07Z","updated_at":"2015-02-16T21:11:07Z","html_url":"https://github.com/dotnet/roslyn/pull/527#discussion_r24776155","pull_request_url":"https://api.github.com/repos/dotnet/roslyn/pulls/527","_links":{"self":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/comments/24776155"},"html":{"href":"https://github.com/dotnet/roslyn/pull/527#discussion_r24776155"},"pull_request":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/527"}}},"pull_request":{"url":"https://api.github.com/repos/dotnet/roslyn/pulls/527","id":29346499,"html_url":"https://github.com/dotnet/roslyn/pull/527","diff_url":"https://github.com/dotnet/roslyn/pull/527.diff","patch_url":"https://github.com/dotnet/roslyn/pull/527.patch","issue_url":"https://api.github.com/repos/dotnet/roslyn/issues/527","number":527,"state":"open","locked":false,"title":"Add AnalyzerManager to manage analyzers for lifetime of an analyzer host.","user":{"login":"mavasani","id":10605811,"avatar_url":"https://avatars.githubusercontent.com/u/10605811?v=3","gravatar_id":"","url":"https://api.github.com/users/mavasani","html_url":"https://github.com/mavasani","followers_url":"https://api.github.com/users/mavasani/followers","following_url":"https://api.github.com/users/mavasani/following{/other_user}","gists_url":"https://api.github.com/users/mavasani/gists{/gist_id}","starred_url":"https://api.github.com/users/mavasani/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mavasani/subscriptions","organizations_url":"https://api.github.com/users/mavasani/orgs","repos_url":"https://api.github.com/users/mavasani/repos","events_url":"https://api.github.com/users/mavasani/events{/privacy}","received_events_url":"https://api.github.com/users/mavasani/received_events","type":"User","site_admin":false},"body":"This is the first step towards unifying the IDE and compiler AnalyzerDrivers towards a common event queue based execution model. This change adds a shared AnalyzerManager to manage analyzers, it ensures the following for the lifetime of an analyzer host:\r\n\r\n1. DiagnosticAnalyzer.Initialize(AnalysisContext) is invoked only once per-analyzer.\r\n2. DiagnosticAnalyzer.SupportedDiagnostics is invoked only once per-analyzer.\r\n3. CompilationStartAnalyzerActions registered during Initialize are invoked only once per-analyzer per-compilation.\r\n\r\nConsumers of the AnalyzerManager API can query it for all the actions to execute for an analyzer for a given compilation, without worrying about session wide vs per-compilation actions and avoiding duplicate callbacks.\r\n\r\nAdditionally, the execution of Initialize method and CompilationStartActions has been moved to separate thread and computing the effective set of analyzer actions is now an async method; currently it is done synchronously on the primary thread of the compiler in AnalyzerDriver.Initialize method. This addresses a long outstanding issue that John Hamby had raised about avoiding callbacks into user code on the primary thread.\r\n\r\n@heejaechang: I have renamed the AnalyzerManager that you recently added in Features layer to WorkspaceAnalyzerManager to avoid a name clash and move some functionality from it into this AnalyzerManager type.\r\n\r\n@srivatsn @heejaechang John Hamby @gafter  can you please take a look?","created_at":"2015-02-16T02:22:24Z","updated_at":"2015-02-16T21:11:07Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5a700d883126027d509b4a95f072805213e56107","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/dotnet/roslyn/pulls/527/commits","review_comments_url":"https://api.github.com/repos/dotnet/roslyn/pulls/527/comments","review_comment_url":"https://api.github.com/repos/dotnet/roslyn/pulls/comments/{number}","comments_url":"https://api.github.com/repos/dotnet/roslyn/issues/527/comments","statuses_url":"https://api.github.com/repos/dotnet/roslyn/statuses/22f25efaae49a32fef659a1b9c1e072a99dbbeb8","head":{"label":"mavasani:AnalyzerActionManager","ref":"AnalyzerActionManager","sha":"22f25efaae49a32fef659a1b9c1e072a99dbbeb8","user":{"login":"mavasani","id":10605811,"avatar_url":"https://avatars.githubusercontent.com/u/10605811?v=3","gravatar_id":"","url":"https://api.github.com/users/mavasani","html_url":"https://github.com/mavasani","followers_url":"https://api.github.com/users/mavasani/followers","following_url":"https://api.github.com/users/mavasani/following{/other_user}","gists_url":"https://api.github.com/users/mavasani/gists{/gist_id}","starred_url":"https://api.github.com/users/mavasani/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mavasani/subscriptions","organizations_url":"https://api.github.com/users/mavasani/orgs","repos_url":"https://api.github.com/users/mavasani/repos","events_url":"https://api.github.com/users/mavasani/events{/privacy}","received_events_url":"https://api.github.com/users/mavasani/received_events","type":"User","site_admin":false},"repo":{"id":30584055,"name":"roslyn","full_name":"mavasani/roslyn","owner":{"login":"mavasani","id":10605811,"avatar_url":"https://avatars.githubusercontent.com/u/10605811?v=3","gravatar_id":"","url":"https://api.github.com/users/mavasani","html_url":"https://github.com/mavasani","followers_url":"https://api.github.com/users/mavasani/followers","following_url":"https://api.github.com/users/mavasani/following{/other_user}","gists_url":"https://api.github.com/users/mavasani/gists{/gist_id}","starred_url":"https://api.github.com/users/mavasani/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mavasani/subscriptions","organizations_url":"https://api.github.com/users/mavasani/orgs","repos_url":"https://api.github.com/users/mavasani/repos","events_url":"https://api.github.com/users/mavasani/events{/privacy}","received_events_url":"https://api.github.com/users/mavasani/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/mavasani/roslyn","description":"The .NET Compiler Platform (\"Roslyn\") provides open-source C# and Visual Basic compilers with rich code analysis APIs.","fork":true,"url":"https://api.github.com/repos/mavasani/roslyn","forks_url":"https://api.github.com/repos/mavasani/roslyn/forks","keys_url":"https://api.github.com/repos/mavasani/roslyn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mavasani/roslyn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mavasani/roslyn/teams","hooks_url":"https://api.github.com/repos/mavasani/roslyn/hooks","issue_events_url":"https://api.github.com/repos/mavasani/roslyn/issues/events{/number}","events_url":"https://api.github.com/repos/mavasani/roslyn/events","assignees_url":"https://api.github.com/repos/mavasani/roslyn/assignees{/user}","branches_url":"https://api.github.com/repos/mavasani/roslyn/branches{/branch}","tags_url":"https://api.github.com/repos/mavasani/roslyn/tags","blobs_url":"https://api.github.com/repos/mavasani/roslyn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mavasani/roslyn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mavasani/roslyn/git/refs{/sha}","trees_url":"https://api.github.com/repos/mavasani/roslyn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mavasani/roslyn/statuses/{sha}","languages_url":"https://api.github.com/repos/mavasani/roslyn/languages","stargazers_url":"https://api.github.com/repos/mavasani/roslyn/stargazers","contributors_url":"https://api.github.com/repos/mavasani/roslyn/contributors","subscribers_url":"https://api.github.com/repos/mavasani/roslyn/subscribers","subscription_url":"https://api.github.com/repos/mavasani/roslyn/subscription","commits_url":"https://api.github.com/repos/mavasani/roslyn/commits{/sha}","git_commits_url":"https://api.github.com/repos/mavasani/roslyn/git/commits{/sha}","comments_url":"https://api.github.com/repos/mavasani/roslyn/comments{/number}","issue_comment_url":"https://api.github.com/repos/mavasani/roslyn/issues/comments/{number}","contents_url":"https://api.github.com/repos/mavasani/roslyn/contents/{+path}","compare_url":"https://api.github.com/repos/mavasani/roslyn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mavasani/roslyn/merges","archive_url":"https://api.github.com/repos/mavasani/roslyn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mavasani/roslyn/downloads","issues_url":"https://api.github.com/repos/mavasani/roslyn/issues{/number}","pulls_url":"https://api.github.com/repos/mavasani/roslyn/pulls{/number}","milestones_url":"https://api.github.com/repos/mavasani/roslyn/milestones{/number}","notifications_url":"https://api.github.com/repos/mavasani/roslyn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mavasani/roslyn/labels{/name}","releases_url":"https://api.github.com/repos/mavasani/roslyn/releases{/id}","created_at":"2015-02-10T09:12:41Z","updated_at":"2015-02-10T09:13:10Z","pushed_at":"2015-02-16T01:53:06Z","git_url":"git://github.com/mavasani/roslyn.git","ssh_url":"git@github.com:mavasani/roslyn.git","clone_url":"https://github.com/mavasani/roslyn.git","svn_url":"https://github.com/mavasani/roslyn","homepage":"","size":50048,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"dotnet:master","ref":"master","sha":"298bdf88ed55b38da8ebe4def1c985ff7d88cec3","user":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"repo":{"id":29078997,"name":"roslyn","full_name":"dotnet/roslyn","owner":{"login":"dotnet","id":9141961,"avatar_url":"https://avatars.githubusercontent.com/u/9141961?v=3","gravatar_id":"","url":"https://api.github.com/users/dotnet","html_url":"https://github.com/dotnet","followers_url":"https://api.github.com/users/dotnet/followers","following_url":"https://api.github.com/users/dotnet/following{/other_user}","gists_url":"https://api.github.com/users/dotnet/gists{/gist_id}","starred_url":"https://api.github.com/users/dotnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dotnet/subscriptions","organizations_url":"https://api.github.com/users/dotnet/orgs","repos_url":"https://api.github.com/users/dotnet/repos","events_url":"https://api.github.com/users/dotnet/events{/privacy}","received_events_url":"https://api.github.com/users/dotnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dotnet/roslyn","description":"The .NET Compiler Platform (\"Roslyn\") provides open-source C# and Visual Basic compilers with rich code analysis APIs.","fork":false,"url":"https://api.github.com/repos/dotnet/roslyn","forks_url":"https://api.github.com/repos/dotnet/roslyn/forks","keys_url":"https://api.github.com/repos/dotnet/roslyn/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dotnet/roslyn/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dotnet/roslyn/teams","hooks_url":"https://api.github.com/repos/dotnet/roslyn/hooks","issue_events_url":"https://api.github.com/repos/dotnet/roslyn/issues/events{/number}","events_url":"https://api.github.com/repos/dotnet/roslyn/events","assignees_url":"https://api.github.com/repos/dotnet/roslyn/assignees{/user}","branches_url":"https://api.github.com/repos/dotnet/roslyn/branches{/branch}","tags_url":"https://api.github.com/repos/dotnet/roslyn/tags","blobs_url":"https://api.github.com/repos/dotnet/roslyn/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dotnet/roslyn/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dotnet/roslyn/git/refs{/sha}","trees_url":"https://api.github.com/repos/dotnet/roslyn/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dotnet/roslyn/statuses/{sha}","languages_url":"https://api.github.com/repos/dotnet/roslyn/languages","stargazers_url":"https://api.github.com/repos/dotnet/roslyn/stargazers","contributors_url":"https://api.github.com/repos/dotnet/roslyn/contributors","subscribers_url":"https://api.github.com/repos/dotnet/roslyn/subscribers","subscription_url":"https://api.github.com/repos/dotnet/roslyn/subscription","commits_url":"https://api.github.com/repos/dotnet/roslyn/commits{/sha}","git_commits_url":"https://api.github.com/repos/dotnet/roslyn/git/commits{/sha}","comments_url":"https://api.github.com/repos/dotnet/roslyn/comments{/number}","issue_comment_url":"https://api.github.com/repos/dotnet/roslyn/issues/comments/{number}","contents_url":"https://api.github.com/repos/dotnet/roslyn/contents/{+path}","compare_url":"https://api.github.com/repos/dotnet/roslyn/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dotnet/roslyn/merges","archive_url":"https://api.github.com/repos/dotnet/roslyn/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dotnet/roslyn/downloads","issues_url":"https://api.github.com/repos/dotnet/roslyn/issues{/number}","pulls_url":"https://api.github.com/repos/dotnet/roslyn/pulls{/number}","milestones_url":"https://api.github.com/repos/dotnet/roslyn/milestones{/number}","notifications_url":"https://api.github.com/repos/dotnet/roslyn/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dotnet/roslyn/labels{/name}","releases_url":"https://api.github.com/repos/dotnet/roslyn/releases{/id}","created_at":"2015-01-11T02:39:03Z","updated_at":"2015-02-16T20:57:19Z","pushed_at":"2015-02-16T20:57:18Z","git_url":"git://github.com/dotnet/roslyn.git","ssh_url":"git@github.com:dotnet/roslyn.git","clone_url":"https://github.com/dotnet/roslyn.git","svn_url":"https://github.com/dotnet/roslyn","homepage":"","size":67460,"stargazers_count":1215,"watchers_count":1215,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":228,"mirror_url":null,"open_issues_count":341,"forks":228,"open_issues":341,"watchers":1215,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/527"},"html":{"href":"https://github.com/dotnet/roslyn/pull/527"},"issue":{"href":"https://api.github.com/repos/dotnet/roslyn/issues/527"},"comments":{"href":"https://api.github.com/repos/dotnet/roslyn/issues/527/comments"},"review_comments":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/527/comments"},"review_comment":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/dotnet/roslyn/pulls/527/commits"},"statuses":{"href":"https://api.github.com/repos/dotnet/roslyn/statuses/22f25efaae49a32fef659a1b9c1e072a99dbbeb8"}}}}