diff --git a/SemDiff.Core/DataStore.cs b/SemDiff.Core/DataStore.cs
deleted file mode 100644
index 22ea133..0000000
--- a/SemDiff.Core/DataStore.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2015 semdiffdotnet. Distributed under the MIT License.
-// See LICENSE file or opensource.org/licenses/MIT.
-using Microsoft.CodeAnalysis;
-using System;
-using System.Collections.Generic;
-using System.Collections.Immutable;
-using System.Linq;
-
-namespace SemDiff.Core
-{
- ///
- /// Simplifies the retrieval of syntax trees based on the repo they are in and allows updating
- /// the tree without relocating the repo based on the path
- ///
- internal class DataStore
- {
- //At the highest level we have a dictionary that maps the assembly
- //name to info about the repository and it's files
-#pragma warning disable CC0052 // Make field readonly
-
- private ImmutableDictionary store =
- ImmutableDictionary.Empty;
-
-#pragma warning restore CC0052 // Make field readonly
-
- public ImmutableDictionary Store => store;
-
- public RepoFileSyntaxTreeInfo InterlockedAddOrUpdate(string assembly,
- IEnumerable trees, Func getRepoFunc)
- {
- return ImmutableInterlocked.AddOrUpdate(ref store,
- assembly, s => InUpdate(trees, getRepoFunc),
- (s, r) => InUpdate(trees, getRepoFunc, r));
- }
-
- private static RepoFileSyntaxTreeInfo InUpdate(IEnumerable trees,
- Func getRepoFunc, RepoFileSyntaxTreeInfo? previous = null)
- {
- return trees.Aggregate(previous ?? RepoFileSyntaxTreeInfo.Empty,
- (rfsti, tree) => rfsti.AddOrUpdateSyntaxTree(tree, getRepoFunc));
- }
-
- //This is basically a customized tuple that contains two dictionaries that
- //ultimately maps the Repo to all the syntax trees
- internal struct RepoFileSyntaxTreeInfo
- {
- //This maps from the (absolute) path of a file to the SyntaxTree that represents it
- public ImmutableDictionary FileSyntaxTreeLookup;
-
- //This maps from our repositories to a list of all the files (under version control),
- //the string represents the absolute path of the file locally
- public ImmutableDictionary> RepoFileLookup;
-
- public static RepoFileSyntaxTreeInfo Empty { get; } = new RepoFileSyntaxTreeInfo
- {
- RepoFileLookup = ImmutableDictionary>.Empty,
- FileSyntaxTreeLookup = ImmutableDictionary.Empty,
- };
-
- public IEnumerable Repos => RepoFileLookup.Keys;
-
- public RepoFileSyntaxTreeInfo AddOrUpdateSyntaxTree(SyntaxTree tree, Func getRepoFunc)
- {
- //Note that if the file isn't in a repo it will be in
- //the FileSyntaxTreeLookup, but it will not be in the repo
- return new RepoFileSyntaxTreeInfo
- {
- FileSyntaxTreeLookup = FileSyntaxTreeLookup.SetItem(tree.FilePath, tree),
- //Use the presence in the File Syntax Lookup as an indicator of if we have already found the repo
- RepoFileLookup = FileSyntaxTreeLookup.ContainsKey(tree.FilePath)
- ? RepoFileLookup
- : AddFileToRepo(RepoFileLookup, getRepoFunc?.Invoke(tree), tree.FilePath)
- };
- }
-
- public IEnumerable GetTreesForRepo(Repo repo)
- {
- var fileTreeLookup = FileSyntaxTreeLookup; //Makes the compiler happy about the following closure
- return RepoFileLookup[repo].Select(s => fileTreeLookup[s]);
- }
-
- private static ImmutableDictionary> AddFileToRepo(
- ImmutableDictionary> initial, Repo repo, string filePath)
- {
- return repo != null
- ? initial.ContainsKey(repo)
- ? initial.SetItem(repo, initial[repo].Add(filePath))
- : initial.Add(repo, ImmutableList.Empty.Add(filePath))
- : initial;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/SemDiff.Core/Extensions.cs b/SemDiff.Core/Extensions.cs
index 55a8966..789e252 100644
--- a/SemDiff.Core/Extensions.cs
+++ b/SemDiff.Core/Extensions.cs
@@ -278,5 +278,32 @@ public static IEnumerable> Map(this IEnumerable sourcel, IE
{
return source;
}
+
+ internal static Dictionary> GetRepoAndTrees(this Compilation comp, Func getRepo)
+ {
+ if (getRepo == null)
+ throw new InvalidOperationException();
+
+ var dictionary = new Dictionary>();
+ foreach (var t in comp.SyntaxTrees)
+ {
+ var repo = getRepo(t);
+ if (repo == null)
+ {
+ continue; //Not a part of a repo
+ }
+ if (dictionary.ContainsKey(repo))
+ {
+ dictionary[repo].Add(t);
+ }
+ else
+ {
+ var list = new List();
+ list.Add(t);
+ dictionary[repo] = list;
+ }
+ }
+ return dictionary;
+ }
}
}
\ No newline at end of file
diff --git a/SemDiff.Core/SemDiff.Core.csproj b/SemDiff.Core/SemDiff.Core.csproj
index 2c43c2c..6167e1e 100644
--- a/SemDiff.Core/SemDiff.Core.csproj
+++ b/SemDiff.Core/SemDiff.Core.csproj
@@ -137,7 +137,6 @@
-
diff --git a/SemDiff.Core/SemDiffAnalyzer.cs b/SemDiff.Core/SemDiffAnalyzer.cs
index d3e8756..e08150f 100644
--- a/SemDiff.Core/SemDiffAnalyzer.cs
+++ b/SemDiff.Core/SemDiffAnalyzer.cs
@@ -5,6 +5,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using SemDiff.Core.Exceptions;
using System;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
@@ -22,8 +23,9 @@ namespace SemDiff.Core
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class SemDiffAnalyzer : DiagnosticAnalyzer
{
+ private static readonly ConcurrentDictionary _treePathLookup = new ConcurrentDictionary();
+ private static int libGit2SharpNativePathSet;
public override ImmutableArray SupportedDiagnostics => Diagnostics.Supported;
- internal static DataStore Store { get; } = new DataStore();
///
/// Called once at session start to register actions in the analysis context.
@@ -40,9 +42,7 @@ public override void Initialize(AnalysisContext context)
context.RegisterCompilationAction(OnCompilation);
}
- private int libGit2SharpNativePathSet;
-
- private void SetupLibGit2Sharp()
+ private static void SetupLibGit2Sharp()
{
// It is important to only set the native library path before they are accessed for the first time.
// Otherwise exceptions will be thrown. So this code is only executed once.
@@ -71,6 +71,13 @@ private void SetupLibGit2Sharp()
}
}
+ private static Repo GetRepo(SyntaxTree tree)
+ {
+ return _treePathLookup.AddOrUpdate(tree.FilePath,
+ p => Repo.GetRepoFor(p),
+ (p, o) => o ?? Repo.GetRepoFor(p)); //Always check again if null
+ }
+
private static void OnCompilation(CompilationAnalysisContext context)
{
var diags = OnCompilationAsync(context.Compilation).Result;
@@ -85,9 +92,8 @@ private async static Task> OnCompilationAsync(Compilatio
Logger.Trace($"Entering {nameof(OnCompilationAsync)}: {comp.AssemblyName}");
try
{
- var data = Store.InterlockedAddOrUpdate(comp.AssemblyName, comp.SyntaxTrees, GetRepo);
- var repos = data.Repos;
- foreach (var repo in repos)
+ var data = comp.GetRepoAndTrees(GetRepo);
+ foreach (var repo in data.Keys)
{
try
{
@@ -121,11 +127,12 @@ private async static Task> OnCompilationAsync(Compilatio
}
var diagnostics = new List();
- foreach (var r in repos)
+ foreach (var rt in data)
{
- foreach (var t in data.GetTreesForRepo(r))
+ var repo = rt.Key;
+ foreach (var t in rt.Value) //Foreach tree
{
- diagnostics.AddRange(Analyze(comp.GetSemanticModel(t), r));
+ diagnostics.AddRange(Analyze(comp.GetSemanticModel(t), repo));
}
}
return diagnostics;
@@ -141,8 +148,6 @@ private async static Task> OnCompilationAsync(Compilatio
}
}
- private static Repo GetRepo(SyntaxTree tree) => Repo.GetRepoFor(tree.FilePath);
-
private static IEnumerable Analyze(SemanticModel semanticModel, Repo repo)
{
Logger.Trace($"Entering {nameof(Analyze)}: {semanticModel?.SyntaxTree?.FilePath}");