diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs index d84be5fa14..c89c43b6f9 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs @@ -50,6 +50,7 @@ namespace ICSharpCode.SharpDevelop.Parser lock (lockObj) { if (!disposed) projectContent = projectContent.UpdateProjectContent(oldFile, newFile); + ParserService.InvalidateCurrentSolutionSnapshot(); } } @@ -180,6 +181,7 @@ namespace ICSharpCode.SharpDevelop.Parser lock (lockObj) { projectContent = projectContent.RemoveAssemblyReferences(this.references).AddAssemblyReferences(newReferences); this.references = newReferences.ToArray(); + ParserService.InvalidateCurrentSolutionSnapshot(); } }, progressMonitor.CancellationToken); } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 13b14ec0c8..01e5d6ffff 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -52,13 +52,35 @@ namespace ICSharpCode.SharpDevelop.Parser return GetCurrentSolutionSnapshot().GetCompilation(solution != null ? solution.FindProjectContainingFile(fileName) : null); } + // Use a WeakReference for caching the solution snapshot - it can require + // lots of memory and may not be invalidated soon enough if the user + // is only browsing code. + volatile static WeakReference currentSolutionSnapshot; + /// - /// Gets a snapshot of the current compilations. This method is useful when a consistent snapshot - /// across multiple compilations is needed. + /// Gets a snapshot of the current compilations + /// This method is useful when a consistent snapshot across multiple compilations is needed. /// public static SharpDevelopSolutionSnapshot GetCurrentSolutionSnapshot() { - return new SharpDevelopSolutionSnapshot(); + var weakRef = currentSolutionSnapshot; + SharpDevelopSolutionSnapshot result; + if (weakRef == null || !weakRef.TryGetTarget(out result)) { + // create new snapshot if we don't have one cached + result = new SharpDevelopSolutionSnapshot(ProjectService.OpenSolution); + currentSolutionSnapshot = new WeakReference(result); + } + return result; + } + + /// + /// Invalidates the current solution snapshot, causing + /// the next call to create a new one. + /// This method needs to be called whenever IProject.ProjectContent changes. + /// + public static void InvalidateCurrentSolutionSnapshot() + { + currentSolutionSnapshot = null; } [Obsolete("Use project.ProjectContent instead")] @@ -901,6 +923,7 @@ namespace ICSharpCode.SharpDevelop.Parser //foreach (IProject project in ProjectService.OpenSolution.Projects) { // RegisterProjectContentForAddedProject(project); //} + InvalidateCurrentSolutionSnapshot(); } internal static void OnSolutionClosed() @@ -910,6 +933,7 @@ namespace ICSharpCode.SharpDevelop.Parser //projectContents.Clear(); } ClearAllFileEntries(); + InvalidateCurrentSolutionSnapshot(); } static void ClearAllFileEntries() diff --git a/src/Main/Base/Project/Src/Services/ParserService/SharpDevelopSolutionSnapshot.cs b/src/Main/Base/Project/Src/Services/ParserService/SharpDevelopSolutionSnapshot.cs index 2c7064acd6..92d1116433 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/SharpDevelopSolutionSnapshot.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/SharpDevelopSolutionSnapshot.cs @@ -15,14 +15,9 @@ namespace ICSharpCode.SharpDevelop.Parser Dictionary projectContentSnapshots = new Dictionary(); Lazy dummyCompilation; - public SharpDevelopSolutionSnapshot() - : this(ProjectService.OpenSolution) - { - dummyCompilation = new Lazy(() => new SimpleCompilation(this, MinimalCorlib.Instance)); - } - public SharpDevelopSolutionSnapshot(Solution solution) { + dummyCompilation = new Lazy(() => new SimpleCompilation(this, MinimalCorlib.Instance)); if (solution != null) { foreach (IProject project in solution.Projects) { var pc = project.ProjectContent;