From ebceccdaa9e9a43344694539f6d1a0417352a837 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 29 Mar 2012 18:19:29 +0200 Subject: [PATCH] Fix LoadSolutionProjects-Thread. --- TODOnewNR.txt | 1 + .../Project/Src/CSharpSemanticHighlighter.cs | 4 +- .../Project/Src/Project/CSharpProject.cs | 9 +- .../CppBinding/Project/CppProject.cs | 9 -- .../FSharpBinding/FSharpProject.cs | 9 -- .../XamlBinding/XamlBinding/XamlParsedFile.cs | 2 +- .../ContextActions/EditorActionsProvider.cs | 2 +- .../GitAddIn/Src/OverlayIconManager.cs | 2 +- .../OverlayIconManager.cs | 2 +- .../Project/ICSharpCode.SharpDevelop.addin | 2 + .../Project/ICSharpCode.SharpDevelop.csproj | 3 +- .../Project/Src/Gui/Dialogs/GotoDialog.cs | 4 +- .../Project/ProjectCreateInformation.cs | 9 +- .../Project/Src/Project/CompilableProject.cs | 22 ++-- .../Src/Project/MSBuildBasedProject.cs | 1 + .../Project/Src/Project/MSBuildInternals.cs | 2 +- .../Src/Project/ProjectLoadInformation.cs | 9 ++ .../Project/Src/Project/Solution/Solution.cs | 3 +- .../Project/Src/Services/File/FileService.cs | 4 +- .../NavigationService/NavigationService.cs | 2 +- .../ParserService/IAssemblyParserService.cs | 37 +++++++ .../Services/ParserService/IParserService.cs | 51 +++++---- .../ParserService/ParseProjectContent.cs | 101 +++++++++--------- .../FindReferenceService.cs | 2 +- src/Main/Base/Project/Src/Services/SD.cs | 4 + .../WebReferences/WebReferenceTestHelper.cs | 5 - .../Parser}/AssemblyParserService.cs | 33 +++--- .../Parser}/LoadSolutionProjects.cs | 83 ++++++++------ src/Main/SharpDevelop/Parser/ParserService.cs | 21 ++-- src/Main/SharpDevelop/Sda/CallHelper.cs | 3 +- src/Main/SharpDevelop/SharpDevelop.csproj | 6 ++ 31 files changed, 256 insertions(+), 191 deletions(-) create mode 100644 src/Main/Base/Project/Src/Services/ParserService/IAssemblyParserService.cs rename src/Main/{Base/Project/Src/Services/ParserService => SharpDevelop/Parser}/AssemblyParserService.cs (90%) rename src/Main/{Base/Project/Src/Services/ParserService => SharpDevelop/Parser}/LoadSolutionProjects.cs (74%) diff --git a/TODOnewNR.txt b/TODOnewNR.txt index 2f83a96dfe..2a37df220e 100644 --- a/TODOnewNR.txt +++ b/TODOnewNR.txt @@ -22,6 +22,7 @@ Stuff that was renamed/moved: IReturnType -> ITypeReference (unresolved) or IType (resolved) Location -> TextLocation in ICSharpCode.NRefactory TextLocation -> moved to ICSharpCode.NRefactory + ParserService -> SD.ParserService Functionality changes: The result of a parser run (ParseInformation) now may contain a fully parsed AST. diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs index 7b78c01098..5cccbb9efc 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs @@ -62,14 +62,14 @@ namespace CSharpBinding this.parameterModifierColor = highlightingDefinition.GetNamedColor("ParameterModifiers"); SD.ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated; - SD.ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded; + SD.ParserService.LoadSolutionProjectsThread.Finished += ParserService_LoadSolutionProjectsThreadEnded; syntaxHighlighter.VisibleDocumentLinesChanged += syntaxHighlighter_VisibleDocumentLinesChanged; } public void Dispose() { SD.ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated; - SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded; + SD.ParserService.LoadSolutionProjectsThread.Finished -= ParserService_LoadSolutionProjectsThreadEnded; syntaxHighlighter.VisibleDocumentLinesChanged -= syntaxHighlighter_VisibleDocumentLinesChanged; } #endregion diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs index a0df8ab679..675b1dfeb4 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpProject.cs @@ -52,6 +52,7 @@ namespace CSharpBinding : base(loadInformation) { Init(); + InitializeProjectContent(new CSharpProjectContent()); } public const string DefaultTargetsFile = @"$(MSBuildBinPath)\Microsoft.CSharp.Targets"; @@ -73,6 +74,9 @@ namespace CSharpBinding PropertyStorageLocations.ConfigurationSpecific, false); SetProperty("Release", null, "DefineConstants", "TRACE", PropertyStorageLocations.ConfigurationSpecific, false); + + if (info.InitializeTypeSystem) + InitializeProjectContent(new CSharpProjectContent()); } public override void StartBuild(ProjectBuildOptions options, IBuildFeedbackSink feedbackSink) @@ -157,11 +161,6 @@ namespace CSharpBinding } */ - protected override IProjectContent CreateProjectContent() - { - return new CSharpProjectContent(); - } - protected override ProjectBehavior CreateDefaultBehavior() { return new CSharpProjectBehavior(this, base.CreateDefaultBehavior()); diff --git a/src/AddIns/BackendBindings/CppBinding/CppBinding/Project/CppProject.cs b/src/AddIns/BackendBindings/CppBinding/CppBinding/Project/CppProject.cs index efd149f2aa..1bea083584 100644 --- a/src/AddIns/BackendBindings/CppBinding/CppBinding/Project/CppProject.cs +++ b/src/AddIns/BackendBindings/CppBinding/CppBinding/Project/CppProject.cs @@ -185,15 +185,6 @@ namespace ICSharpCode.CppBinding.Project { return new CppProjectBehavior(this, base.CreateDefaultBehavior()); } - - public override ICSharpCode.NRefactory.TypeSystem.IProjectContent ProjectContent { - get { return null; } - } - - protected override ICSharpCode.NRefactory.TypeSystem.IProjectContent CreateProjectContent() - { - throw new NotSupportedException(); - } } public class CppProjectBehavior : ProjectBehavior diff --git a/src/AddIns/BackendBindings/FSharpBinding/FSharpProject.cs b/src/AddIns/BackendBindings/FSharpBinding/FSharpProject.cs index 6612af9c09..a52956f722 100644 --- a/src/AddIns/BackendBindings/FSharpBinding/FSharpProject.cs +++ b/src/AddIns/BackendBindings/FSharpBinding/FSharpProject.cs @@ -41,15 +41,6 @@ namespace FSharpBinding { return new FSharpProjectBehavior(this, base.CreateDefaultBehavior()); } - - public override ICSharpCode.NRefactory.TypeSystem.IProjectContent ProjectContent { - get { return null; } - } - - protected override ICSharpCode.NRefactory.TypeSystem.IProjectContent CreateProjectContent() - { - throw new NotSupportedException(); - } } public class FSharpProjectBehavior : ProjectBehavior diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParsedFile.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParsedFile.cs index 23e8efb78f..adf7f06a10 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParsedFile.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParsedFile.cs @@ -148,7 +148,7 @@ namespace ICSharpCode.XamlBinding element.GetAttributeValue("Name"); string modifier = element.GetAttributeValue(XamlBehavior.XamlNamespace, "FieldModifier"); - if (name != null) { + if (name != null && TypeDefinition != null) { var field = new DefaultUnresolvedField(TypeDefinition, name); field.Accessibility = Accessibility.Internal; field.Region = new DomRegion(file.FileName, textDocument.GetLocation(element.StartOffset), textDocument.GetLocation(element.EndOffset)); diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs index d79f6db158..512eb92e8f 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs @@ -83,7 +83,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.ContextActions /// async Task> GetActionsAsync(IEnumerable providers, CancellationToken cancellationToken) { - if (SD.ParserService.LoadSolutionProjectsThreadRunning) + if (SD.ParserService.LoadSolutionProjectsThread.IsRunning) return EmptyList.Instance; var providerList = providers.ToList(); var actions = await Task.WhenAll(providerList.Select(p => p.GetAvailableActionsAsync(this.EditorContext, cancellationToken))); diff --git a/src/AddIns/VersionControl/GitAddIn/Src/OverlayIconManager.cs b/src/AddIns/VersionControl/GitAddIn/Src/OverlayIconManager.cs index 86015748bc..5e5d655947 100644 --- a/src/AddIns/VersionControl/GitAddIn/Src/OverlayIconManager.cs +++ b/src/AddIns/VersionControl/GitAddIn/Src/OverlayIconManager.cs @@ -83,7 +83,7 @@ namespace ICSharpCode.GitAddIn // sleep a tiny bit to give main thread time to add more jobs to the queue Thread.Sleep(100); while (true) { - if (SD.ParserService.LoadSolutionProjectsThreadRunning) { + if (SD.ParserService.LoadSolutionProjectsThread.IsRunning) { // Run OverlayIconManager much more slowly while solution is being loaded. // This prevents the disk from seeking too much Thread.Sleep(100); diff --git a/src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs b/src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs index 427b4c363d..c44eee54f2 100644 --- a/src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs +++ b/src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs @@ -139,7 +139,7 @@ namespace ICSharpCode.Svn // sleep a tiny bit to give main thread time to add more jobs to the queue Thread.Sleep(2); while (true) { - if (SD.ParserService.LoadSolutionProjectsThreadRunning) { + if (SD.ParserService.LoadSolutionProjectsThread.IsRunning) { // Run OverlayIconManager much more slowly while solution is being loaded. // This prevents the disk from seeking too much Thread.Sleep(100); diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin index 42c4ffc310..6b6b6f02ac 100755 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin @@ -58,6 +58,8 @@ class="ICSharpCode.SharpDevelop.Parser.GlobalAssemblyCacheService"/> + diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 8aa16490c8..8e1e40bac0 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -372,13 +372,12 @@ - + - diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs b/src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs index 6b6f438beb..b94baef3ad 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs @@ -38,14 +38,14 @@ namespace ICSharpCode.SharpDevelop.Gui { InitializeComponent(); FormLocationHelper.ApplyWindow(this, "ICSharpCode.SharpDevelop.Gui.GotoDialog.Bounds", true); - SD.ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded; + SD.ParserService.LoadSolutionProjectsThread.Finished += ParserService_LoadSolutionProjectsThreadEnded; textBox.Focus(); } protected override void OnClosed(EventArgs e) { Instance = null; - SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded; + SD.ParserService.LoadSolutionProjectsThread.Finished -= ParserService_LoadSolutionProjectsThreadEnded; base.OnClosed(e); } diff --git a/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectCreateInformation.cs b/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectCreateInformation.cs index 9124e84cd3..ffe240d77e 100644 --- a/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectCreateInformation.cs +++ b/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectCreateInformation.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates createdProjects.AddRange(projects); } - public ReadOnlyCollection CreatedProjects { + public IReadOnlyList CreatedProjects { get { return createdProjects.AsReadOnly(); } } @@ -44,5 +44,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates public string ProjectBasePath { get; set; } public TargetFramework TargetFramework { get; set; } public Solution Solution { get; set; } + + /// + /// Whether to initialize the type system for the newly created project. + /// The default is false because SharpDevelop saves and re-loads newly created projects, + /// so we don't need a type system if we're going to re-load it anyways. + /// + public bool InitializeTypeSystem { get; set; } } } diff --git a/src/Main/Base/Project/Src/Project/CompilableProject.cs b/src/Main/Base/Project/Src/Project/CompilableProject.cs index 3b807bac74..825176582a 100644 --- a/src/Main/Base/Project/Src/Project/CompilableProject.cs +++ b/src/Main/Base/Project/Src/Project/CompilableProject.cs @@ -360,29 +360,27 @@ namespace ICSharpCode.SharpDevelop.Project #region Type System volatile ParseProjectContentContainer parseProjectContentContainer; - protected abstract IProjectContent CreateProjectContent(); - - ParseProjectContentContainer GetParseProjectContentContainer() + protected void InitializeProjectContent(IProjectContent initialProjectContent) { - if (parseProjectContentContainer == null) { - lock (SyncRoot) { - if (parseProjectContentContainer == null) { - parseProjectContentContainer = new ParseProjectContentContainer(this, CreateProjectContent()); - } - } + lock (SyncRoot) { + if (parseProjectContentContainer != null) + throw new InvalidOperationException("Already initialized."); + parseProjectContentContainer = new ParseProjectContentContainer(this, initialProjectContent); } - return parseProjectContentContainer; } public override IProjectContent ProjectContent { get { - return GetParseProjectContentContainer().ProjectContent; + var c = parseProjectContentContainer; + return c != null ? c.ProjectContent : null; } } public override void OnParseInformationUpdated(ParseInformationEventArgs args) { - GetParseProjectContentContainer().ParseInformationUpdated(args.OldParsedFile, args.NewParsedFile); + var c = parseProjectContentContainer; + if (c != null) + c.ParseInformationUpdated(args.OldParsedFile, args.NewParsedFile); // OnParseInformationUpdated is called inside a lock, but we don't want to raise the event inside that lock. // To ensure events are raised in the same order, we always invoke on the main thread. SD.MainThread.InvokeAsync( diff --git a/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs b/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs index 499120ab0c..611cda7dbb 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildBasedProject.cs @@ -1210,6 +1210,7 @@ namespace ICSharpCode.SharpDevelop.Project { this.projectCollection = loadInformation.ParentSolution.MSBuildProjectCollection; this.FileName = loadInformation.FileName; + this.ActiveConfiguration = loadInformation.Configuration; this.ActivePlatform = loadInformation.Platform; projectFile = ProjectRootElement.Open(loadInformation.FileName, projectCollection); diff --git a/src/Main/Base/Project/Src/Project/MSBuildInternals.cs b/src/Main/Base/Project/Src/Project/MSBuildInternals.cs index 251ffdd285..2d7ab7f7b3 100644 --- a/src/Main/Base/Project/Src/Project/MSBuildInternals.cs +++ b/src/Main/Base/Project/Src/Project/MSBuildInternals.cs @@ -234,7 +234,7 @@ namespace ICSharpCode.SharpDevelop.Project List resolvedAssemblies = new List(); List handledReferenceItems = new List(); foreach (var assembly in query) { - LoggingService.Debug("Got information about " + assembly.OriginalInclude + "; fullpath=" + assembly.FullPath); + //LoggingService.Debug("Got information about " + assembly.OriginalInclude + "; fullpath=" + assembly.FullPath); foreach (var referenceItem in assembly.ReferenceItems) { referenceItem.AssemblyName = assembly.AssemblyName; referenceItem.FileName = assembly.FullPath; diff --git a/src/Main/Base/Project/Src/Project/ProjectLoadInformation.cs b/src/Main/Base/Project/Src/Project/ProjectLoadInformation.cs index c5d4338e68..4c6332d939 100644 --- a/src/Main/Base/Project/Src/Project/ProjectLoadInformation.cs +++ b/src/Main/Base/Project/Src/Project/ProjectLoadInformation.cs @@ -13,10 +13,18 @@ namespace ICSharpCode.SharpDevelop.Project { public Solution ParentSolution { get; private set; } public string FileName { get; private set; } + public string Configuration { get; internal set; } public string Platform { get; internal set; } public string ProjectName { get; private set; } public string TypeGuid { get; set; } public IList ProjectSections {get; set;} + + /// + /// Whether to initialize the type system for the newly loaded project. + /// The default is true. + /// + public bool InitializeTypeSystem { get; set; } + internal string Guid { get; set; } internal bool? upgradeToolsVersion; @@ -47,6 +55,7 @@ namespace ICSharpCode.SharpDevelop.Project this.ParentSolution = parentSolution; this.FileName = fileName; this.ProjectName = projectName; + this.InitializeTypeSystem = true; } } } diff --git a/src/Main/Base/Project/Src/Project/Solution/Solution.cs b/src/Main/Base/Project/Src/Project/Solution/Solution.cs index 70e625ec2d..052a576ce5 100644 --- a/src/Main/Base/Project/Src/Project/Solution/Solution.cs +++ b/src/Main/Base/Project/Src/Project/Solution/Solution.cs @@ -587,7 +587,8 @@ namespace ICSharpCode.SharpDevelop.Project // set the target platform SolutionItem projectConfig = newSolution.GetProjectConfiguration(loadInfo.Guid); - loadInfo.Platform = AbstractProject.GetPlatformNameFromKey(projectConfig.Location); + loadInfo.Configuration = AbstractProject.GetConfigurationNameFromKey(projectConfig.Location); + loadInfo.Platform = FixPlatformNameForProject(AbstractProject.GetPlatformNameFromKey(projectConfig.Location)); loadInfo.ProgressMonitor = progressMonitor; progressMonitor.Progress = (double)i / projectsToLoad.Count; diff --git a/src/Main/Base/Project/Src/Services/File/FileService.cs b/src/Main/Base/Project/Src/Services/File/FileService.cs index f77e0399ba..f58b658c79 100644 --- a/src/Main/Base/Project/Src/Services/File/FileService.cs +++ b/src/Main/Base/Project/Src/Services/File/FileService.cs @@ -22,14 +22,14 @@ namespace ICSharpCode.SharpDevelop internal static void Unload() { - SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded; + SD.ParserService.LoadSolutionProjectsThread.Finished -= ParserServiceLoadSolutionProjectsThreadEnded; serviceInitialized = false; } internal static void InitializeService() { if (!serviceInitialized) { - SD.ParserService.LoadSolutionProjectsThreadEnded += ParserServiceLoadSolutionProjectsThreadEnded; + SD.ParserService.LoadSolutionProjectsThread.Finished += ParserServiceLoadSolutionProjectsThreadEnded; serviceInitialized = true; } } diff --git a/src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs b/src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs index b2eeabd56b..ee6ffe6688 100644 --- a/src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs +++ b/src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs @@ -70,7 +70,7 @@ namespace ICSharpCode.SharpDevelop // ignore files opened as part of loading a solution. ProjectService.SolutionLoading += ProjectService_SolutionLoading; - SD.ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEnded; + SD.ParserService.LoadSolutionProjectsThread.Finished += LoadSolutionProjectsThreadEnded; FileService.FileRenamed += FileService_FileRenamed; ProjectService.SolutionClosed += ProjectService_SolutionClosed; diff --git a/src/Main/Base/Project/Src/Services/ParserService/IAssemblyParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/IAssemblyParserService.cs new file mode 100644 index 0000000000..27536c9498 --- /dev/null +++ b/src/Main/Base/Project/Src/Services/ParserService/IAssemblyParserService.cs @@ -0,0 +1,37 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Threading; +using System.Threading.Tasks; + +using ICSharpCode.Core; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.SharpDevelop.Parser +{ + /// + /// Portions of parser service that deal with loading external assemblies for code completion. + /// + public interface IAssemblyParserService + { + IUnresolvedAssembly GetAssembly(FileName fileName, CancellationToken cancellationToken = default(CancellationToken)); + + Task GetAssemblyAsync(FileName fileName, CancellationToken cancellationToken = default(CancellationToken)); + + /// + /// using (AssemblyParserService.AvoidRedundantChecks()) + /// Within the using block, the AssemblyParserService will only check once per assembly if the + /// existing cached project content (if any) is up to date. + /// Any additional accesses will return that cached project content without causing an update check. + /// This applies only to the thread that called AvoidRedundantChecks() - other threads will + /// perform update checks as usual. + /// + IDisposable AvoidRedundantChecks(); + + /// + /// Gets the directory for cached project contents. + /// + string DomPersistencePath { get; } + } +} diff --git a/src/Main/Base/Project/Src/Services/ParserService/IParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/IParserService.cs index c25afafbaf..5b811be4e4 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/IParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/IParserService.cs @@ -12,6 +12,7 @@ using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Refactoring; @@ -29,26 +30,7 @@ namespace ICSharpCode.SharpDevelop.Parser /// IReadOnlyList TaskListTokens { get; set; } - #region Load Solution Projects Thread - /// - /// Gets whether the solution is being loaded, or a major re-parse is happening - /// (e.g. after adding a project). - /// - /// This property is only changed by the main thread. - bool LoadSolutionProjectsThreadRunning { get; } - - /// - /// This event is raised when the LoadSolutionProjectsThreadRunning property changes to true. - /// This always happens on the main thread. - /// - event EventHandler LoadSolutionProjectsThreadStarted; - - /// - /// This event is raised when the LoadSolutionProjectsThreadRunning property changes to false. - /// This always happens on the main thread. - /// - event EventHandler LoadSolutionProjectsThreadEnded; // TODO: rename to finished - #endregion + ILoadSolutionProjectsThread LoadSolutionProjectsThread { get; } #region GetCompilation /// @@ -288,4 +270,33 @@ namespace ICSharpCode.SharpDevelop.Parser event EventHandler ParseInformationUpdated; #endregion } + + public interface ILoadSolutionProjectsThread + { + /// + /// Gets whether the solution is being loaded, or a major re-parse is happening + /// (e.g. after adding a project). + /// + bool IsRunning { get; } + + /// + /// This event is raised when the IsRunning property changes to true. + /// This always happens on the main thread. + /// + event EventHandler Started; + + /// + /// This event is raised when the IsRunning property changes to false. + /// This always happens on the main thread. + /// + event EventHandler Finished; + + /// + /// Adds a new task to the job queue, and starts the LoadSolutionProjects thread (if its not already running). + /// + /// The action to run. Parameter: a nested progress monitor for the action. + /// Name of the action - shown in the status bar + /// Cost of the action + void AddJob(Action action, string name, double cost); + } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs index 693e80d075..3ba5210d74 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs @@ -5,8 +5,8 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using System.Threading.Tasks; - using ICSharpCode.Core; using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; @@ -28,9 +28,11 @@ namespace ICSharpCode.SharpDevelop.Parser IProjectContent projectContent; IAssemblyReference[] references = { MinimalCorlib.Instance }; - bool initializing; bool disposed; + // time necessary for loading references, in relation to time for a single C# file + const int LoadingReferencesWorkAmount = 15; + public ParseProjectContentContainer(MSBuildBasedProject project, IProjectContent initialProjectContent) { if (project == null) @@ -38,18 +40,22 @@ namespace ICSharpCode.SharpDevelop.Parser this.project = project; this.projectContent = initialProjectContent.SetAssemblyName(project.AssemblyName); - this.initializing = true; - LoadSolutionProjects.AddJob(Initialize, "Loading " + project.Name + "...", GetInitializationWorkAmount()); - } - - public void ParseInformationUpdated(IParsedFile oldFile, IParsedFile newFile) - { - // This method is called by the parser service within the parser service lock. - lock (lockObj) { - if (!disposed) - projectContent = projectContent.UpdateProjectContent(oldFile, newFile); - SD.ParserService.InvalidateCurrentSolutionSnapshot(); + ProjectService.ProjectItemAdded += OnProjectItemAdded; + ProjectService.ProjectItemRemoved += OnProjectItemRemoved; + + var parserService = SD.ParserService; + List filesToParse = new List(); + foreach (var file in project.Items.OfType()) { + if (IsParseableFile(file)) { + var fileName = FileName.Create(file.FileName); + parserService.AddOwnerProject(fileName, project, startAsyncParse: false, isLinkedFile: file.IsLink); + filesToParse.Add(fileName); + } } + + SD.ParserService.LoadSolutionProjectsThread.AddJob( + monitor => Initialize(monitor, filesToParse), + "Loading " + project.Name + "...", filesToParse.Count + LoadingReferencesWorkAmount); } public void Dispose() @@ -61,10 +67,9 @@ namespace ICSharpCode.SharpDevelop.Parser return; disposed = true; } - foreach (var fileName in GetFilesToParse(project.Items)) { - SD.ParserService.RemoveOwnerProject(fileName.Item1, project); + foreach (var parsedFile in projectContent.Files) { + SD.ParserService.RemoveOwnerProject(FileName.Create(parsedFile.FileName), project); } - initializing = false; } public IProjectContent ProjectContent { @@ -75,14 +80,24 @@ namespace ICSharpCode.SharpDevelop.Parser } } - const int LoadingReferencesWorkAmount = 15; // time necessary for loading references, in relation to time for a single C# file + public void ParseInformationUpdated(IParsedFile oldFile, IParsedFile newFile) + { + // This method is called by the parser service within the parser service (per-file) lock. + lock (lockObj) { + if (!disposed) + projectContent = projectContent.UpdateProjectContent(oldFile, newFile); + SD.ParserService.InvalidateCurrentSolutionSnapshot(); + } + } - int GetInitializationWorkAmount() + bool IsParseableFile(FileProjectItem projectItem) { - return project.Items.Count + LoadingReferencesWorkAmount; + if (projectItem == null || string.IsNullOrEmpty(projectItem.FileName)) + return false; + return projectItem.ItemType == ItemType.Compile || projectItem.ItemType == ItemType.Page; } - void Initialize(IProgressMonitor progressMonitor) + void Initialize(IProgressMonitor progressMonitor, List filesToParse) { ICollection projectItems = project.Items; lock (lockObj) { @@ -90,56 +105,35 @@ namespace ICSharpCode.SharpDevelop.Parser throw new ObjectDisposedException("ParseProjectContent"); } } - ProjectService.ProjectItemAdded += OnProjectItemAdded; - ProjectService.ProjectItemRemoved += OnProjectItemRemoved; + double scalingFactor = 1.0 / (project.Items.Count + LoadingReferencesWorkAmount); using (IProgressMonitor initReferencesProgressMonitor = progressMonitor.CreateSubTask(LoadingReferencesWorkAmount * scalingFactor), parseProgressMonitor = progressMonitor.CreateSubTask(projectItems.Count * scalingFactor)) { var resolveReferencesTask = ResolveReferencesAsync(projectItems, initReferencesProgressMonitor); - ParseFiles(projectItems, parseProgressMonitor); + ParseFiles(filesToParse, parseProgressMonitor); resolveReferencesTask.Wait(); } - initializing = false; - } - - static readonly ItemType[] compilableItemTypes = { ItemType.Compile, ItemType.Page }; - - IEnumerable> GetFilesToParse(IEnumerable projectItems) - { - return - from p in projectItems.OfType() - where compilableItemTypes.Contains(p.ItemType) && !String.IsNullOrEmpty(p.FileName) - select Tuple.Create(FileName.Create(p.FileName), p.IsLink); } - void ParseFiles(ICollection projectItems, IProgressMonitor progressMonitor) + void ParseFiles(IReadOnlyList filesToParse, IProgressMonitor progressMonitor) { ParseableFileContentFinder finder = new ParseableFileContentFinder(); - var fileList = GetFilesToParse(projectItems).ToList(); object progressLock = new object(); - double fileCountInverse = 1.0 / fileList.Count; + double fileCountInverse = 1.0 / filesToParse.Count; Parallel.ForEach( - fileList, + filesToParse, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = progressMonitor.CancellationToken }, - tuple => { - var fileName = tuple.Item1; - // Don't read files we don't have a parser for. - // This avoids loading huge files (e.g. sdps) when we have no intention of parsing them. - if (SD.ParserService.HasParser(fileName)) { - // We don't start an asynchronous parse operation since we want to - // parse on this thread. - SD.ParserService.AddOwnerProject(fileName, project, startAsyncParse: false, isLinkedFile: tuple.Item2); - ITextSource content = finder.Create(fileName); - if (content != null) { - SD.ParserService.ParseFile(fileName, content, project); - } + fileName => { + ITextSource content = finder.Create(fileName); + if (content != null) { + SD.ParserService.ParseFile(fileName, content, project); } lock (progressLock) { progressMonitor.Progress += fileCountInverse; @@ -172,7 +166,7 @@ namespace ICSharpCode.SharpDevelop.Parser foreach (string file in assemblyFiles) { progressMonitor.CancellationToken.ThrowIfCancellationRequested(); if (File.Exists(file)) { - var pc = AssemblyParserService.GetAssembly(FileName.Create(file), progressMonitor.CancellationToken); + var pc = SD.AssemblyParserService.GetAssembly(FileName.Create(file), progressMonitor.CancellationToken); if (pc != null) { newReferences.Add(pc); } @@ -232,7 +226,7 @@ namespace ICSharpCode.SharpDevelop.Parser } } FileProjectItem fileProjectItem = e.ProjectItem as FileProjectItem; - if (fileProjectItem != null && compilableItemTypes.Contains(fileProjectItem.ItemType)) { + if (IsParseableFile(fileProjectItem)) { var fileName = FileName.Create(e.ProjectItem.FileName); SD.ParserService.AddOwnerProject(fileName, project, startAsyncParse: true, isLinkedFile: fileProjectItem.IsLink); } @@ -256,7 +250,8 @@ namespace ICSharpCode.SharpDevelop.Parser } } - if (e.ProjectItem.ItemType == ItemType.Compile) { + FileProjectItem fileProjectItem = e.ProjectItem as FileProjectItem; + if (IsParseableFile(fileProjectItem)) { SD.ParserService.RemoveOwnerProject(FileName.Create(e.ProjectItem.FileName), project); } } diff --git a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs index 61550539e1..b3264c1bc8 100644 --- a/src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs +++ b/src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs @@ -68,7 +68,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring if (callback == null) throw new ArgumentNullException("callback"); SD.MainThread.VerifyAccess(); - if (SD.ParserService.LoadSolutionProjectsThreadRunning) { + if (SD.ParserService.LoadSolutionProjectsThread.IsRunning) { progressMonitor.ShowingDialog = true; MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}"); progressMonitor.ShowingDialog = false; diff --git a/src/Main/Base/Project/Src/Services/SD.cs b/src/Main/Base/Project/Src/Services/SD.cs index 5a24175d31..d3d2ccef06 100644 --- a/src/Main/Base/Project/Src/Services/SD.cs +++ b/src/Main/Base/Project/Src/Services/SD.cs @@ -93,6 +93,10 @@ namespace ICSharpCode.SharpDevelop get { return GetRequiredService(); } } + public static IAssemblyParserService AssemblyParserService { + get { return GetRequiredService(); } + } + public static IFileService FileService { get { return GetRequiredService(); } } diff --git a/src/Main/Base/Test/WebReferences/WebReferenceTestHelper.cs b/src/Main/Base/Test/WebReferences/WebReferenceTestHelper.cs index 96c837a631..23b40be391 100644 --- a/src/Main/Base/Test/WebReferences/WebReferenceTestHelper.cs +++ b/src/Main/Base/Test/WebReferences/WebReferenceTestHelper.cs @@ -44,11 +44,6 @@ namespace ICSharpCode.SharpDevelop.Tests.WebReferences get { return readOnly; } } - protected override IProjectContent CreateProjectContent() - { - throw new NotImplementedException(); - } - protected override ProjectBehavior CreateDefaultBehavior() { return new DotNetStartBehavior(this, null); diff --git a/src/Main/Base/Project/Src/Services/ParserService/AssemblyParserService.cs b/src/Main/SharpDevelop/Parser/AssemblyParserService.cs similarity index 90% rename from src/Main/Base/Project/Src/Services/ParserService/AssemblyParserService.cs rename to src/Main/SharpDevelop/Parser/AssemblyParserService.cs index 19d7bb65b1..7e99ff2e32 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/AssemblyParserService.cs +++ b/src/Main/SharpDevelop/Parser/AssemblyParserService.cs @@ -11,13 +11,13 @@ using System.Runtime.Serialization; using System.Threading; using System.Threading.Tasks; using System.Xml; + using ICSharpCode.Core; using ICSharpCode.NRefactory.Documentation; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; using ICSharpCode.SharpDevelop.Project; -using Microsoft.Build.Tasks; using Mono.Cecil; namespace ICSharpCode.SharpDevelop.Parser @@ -25,7 +25,7 @@ namespace ICSharpCode.SharpDevelop.Parser /// /// Portions of parser service that deal with loading external assemblies for code completion. /// - public static class AssemblyParserService + sealed class AssemblyParserService : IAssemblyParserService { #region Get Assembly By File Name sealed class LoadedAssembly @@ -41,11 +41,11 @@ namespace ICSharpCode.SharpDevelop.Parser } // TODO: use weak reference to IProjectContent (not to LoadedAssembly!) so that unused assemblies can be unloaded - static Dictionary projectContentDictionary = new Dictionary(); + Dictionary projectContentDictionary = new Dictionary(); [ThreadStatic] static Dictionary up2dateProjectContents; - public static IUnresolvedAssembly GetAssembly(FileName fileName, CancellationToken cancellationToken = default(CancellationToken)) + public IUnresolvedAssembly GetAssembly(FileName fileName, CancellationToken cancellationToken = default(CancellationToken)) { // We currently do not support cancelling the load operation itself, because another GetAssembly() call // with a different cancellation token might request the same assembly. @@ -58,7 +58,7 @@ namespace ICSharpCode.SharpDevelop.Parser return asm.ProjectContent.Result; } - public static Task GetAssemblyAsync(FileName fileName, CancellationToken cancellationToken = default(CancellationToken)) + public Task GetAssemblyAsync(FileName fileName, CancellationToken cancellationToken = default(CancellationToken)) { bool isNewTask; LoadedAssembly asm = GetLoadedAssembly(fileName, out isNewTask); @@ -75,7 +75,7 @@ namespace ICSharpCode.SharpDevelop.Parser /// This applies only to the thread that called AvoidRedundantChecks() - other threads will /// perform update checks as usual. /// - public static IDisposable AvoidRedundantChecks() + public IDisposable AvoidRedundantChecks() { if (up2dateProjectContents != null) return null; @@ -89,7 +89,7 @@ namespace ICSharpCode.SharpDevelop.Parser }); } - static void CleanWeakDictionary() + void CleanWeakDictionary() { List removed = new List(); foreach (var pair in projectContentDictionary) { @@ -100,7 +100,7 @@ namespace ICSharpCode.SharpDevelop.Parser projectContentDictionary.Remove(key); } - static LoadedAssembly GetLoadedAssembly(FileName fileName, out bool isNewTask) + LoadedAssembly GetLoadedAssembly(FileName fileName, out bool isNewTask) { isNewTask = false; LoadedAssembly asm; @@ -132,7 +132,7 @@ namespace ICSharpCode.SharpDevelop.Parser #endregion #region Load Assembly - static IUnresolvedAssembly LoadAssembly(FileName fileName, CancellationToken cancellationToken) + IUnresolvedAssembly LoadAssembly(FileName fileName, CancellationToken cancellationToken) { DateTime lastWriteTime = File.GetLastWriteTimeUtc(fileName); string cacheFileName = GetCacheFileName(fileName); @@ -229,9 +229,9 @@ namespace ICSharpCode.SharpDevelop.Parser /// /// Gets/Sets the directory for cached project contents. /// - public static string DomPersistencePath { get; set; } + public string DomPersistencePath { get; set; } - static string GetCacheFileName(FileName assemblyFileName) + string GetCacheFileName(FileName assemblyFileName) { if (DomPersistencePath == null) return null; @@ -271,7 +271,7 @@ namespace ICSharpCode.SharpDevelop.Parser } } - static void SaveToCache(string cacheFileName, DateTime lastWriteTime, IUnresolvedAssembly pc) + void SaveToCache(string cacheFileName, DateTime lastWriteTime, IUnresolvedAssembly pc) { if (cacheFileName == null) return; @@ -323,14 +323,5 @@ namespace ICSharpCode.SharpDevelop.Parser } } #endregion - - internal static string FindReferenceAssembly(string shortName) - { - string path = Path.Combine(referenceAssembliesPath, @".NETFramework\v4.0", shortName + ".dll"); - if (File.Exists(path)) - return path; - else - return null; - } } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/LoadSolutionProjects.cs b/src/Main/SharpDevelop/Parser/LoadSolutionProjects.cs similarity index 74% rename from src/Main/Base/Project/Src/Services/ParserService/LoadSolutionProjects.cs rename to src/Main/SharpDevelop/Parser/LoadSolutionProjects.cs index 092202de03..984eeb8509 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/LoadSolutionProjects.cs +++ b/src/Main/SharpDevelop/Parser/LoadSolutionProjects.cs @@ -6,6 +6,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Threading; +using System.Windows.Threading; using ICSharpCode.Core; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop.Gui; @@ -16,35 +17,45 @@ namespace ICSharpCode.SharpDevelop.Parser /// /// The background task that initializes the projects in the solution. /// - static class LoadSolutionProjects + sealed class LoadSolutionProjects : ILoadSolutionProjectsThread { - static JobQueue jobs = new JobQueue(); + readonly JobQueue jobs; - /// - /// Gets whether the LoadSolutionProjects thread is currently running. - /// - public static bool IsThreadRunning { - get { - return jobs.IsThreadRunningOrWaitingToStart; - } + public LoadSolutionProjects() + { + jobs = new JobQueue(this); } - /// - /// Occurs when the 'load solution projects' thread has finished. - /// This event is not raised when the 'load solution projects' is aborted because the solution was closed. - /// This event is raised on the main thread. - /// - public static event EventHandler ThreadEnded = delegate {}; + /// + public bool IsRunning { get; private set; } + + /// + public event EventHandler Started = delegate {}; + + /// + public event EventHandler Finished = delegate {}; + + Stopwatch threadRunningTime; - static void RaiseThreadEnded() + void RaiseThreadStarted() { - Gui.WorkbenchSingleton.SafeThreadAsyncCall( + threadRunningTime = Stopwatch.StartNew(); + SD.MainThread.InvokeAsync( delegate { - // only raise the event if the thread wasn't re-started - if (!IsThreadRunning) { - ThreadEnded(null, EventArgs.Empty); - } - }); + IsRunning = true; + Started(this, EventArgs.Empty); + }).FireAndForget(); + } + + void RaiseThreadEnded() + { + if (threadRunningTime != null) + LoggingService.Debug("LoadSolutionProjectsThread finished after " + threadRunningTime.Elapsed); + SD.MainThread.InvokeAsync( + delegate { + IsRunning = false; + Finished(this, EventArgs.Empty); + }).FireAndForget(); } static string GetLoadReferenceTaskTitle(string projectName) @@ -63,7 +74,7 @@ namespace ICSharpCode.SharpDevelop.Parser /// The action to run. Parameter: a nested progress monitor for the action. /// Name of the action - shown in the status bar /// Cost of the action - public static void AddJob(Action action, string name, double cost) + public void AddJob(Action action, string name, double cost) { if (action == null) throw new ArgumentNullException("action"); @@ -73,18 +84,17 @@ namespace ICSharpCode.SharpDevelop.Parser jobs.AddJob(new JobTask(action, name, cost)); // Start the thread with a bit delay so that the SD UI gets responsive first, // and so that the total cost is known for showing the progress bar. - System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke( - System.Windows.Threading.DispatcherPriority.Background, - new Action(jobs.StartRunningIfRequired)); + SD.MainThread.InvokeAsync(jobs.StartRunningIfRequired, DispatcherPriority.Background).FireAndForget(); } - public static void CancelAllJobs() + public void CancelAllJobs() { jobs.Clear(); } sealed class JobQueue { + readonly LoadSolutionProjects loadSolutionProjects; readonly object lockObj = new object(); readonly Queue actions = new Queue(); CancellationTokenSource cancellationSource = new CancellationTokenSource(); @@ -93,13 +103,21 @@ namespace ICSharpCode.SharpDevelop.Parser double totalWork; double workDone; + public JobQueue(LoadSolutionProjects loadSolutionProjects) + { + this.loadSolutionProjects = loadSolutionProjects; + } + public void AddJob(JobTask task) { if (task == null) throw new ArgumentNullException("task"); lock (lockObj) { + bool wasRunning = this.threadIsRunning || this.actions.Count > 0; this.totalWork += task.cost; this.actions.Enqueue(task); + if (!wasRunning) + loadSolutionProjects.RaiseThreadStarted(); } } @@ -117,12 +135,11 @@ namespace ICSharpCode.SharpDevelop.Parser if (!this.threadIsRunning && this.actions.Count > 0) { this.threadIsRunning = true; - progressMonitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor(cancellationSource.Token); + progressMonitor = SD.StatusBar.CreateProgressMonitor(cancellationSource.Token); progressMonitor.TaskName = this.actions.Peek().name; Thread thread = new Thread(new ThreadStart(RunThread)); thread.Name = "LoadSolutionProjects"; - thread.Priority = ThreadPriority.BelowNormal; thread.IsBackground = true; thread.Start(); } @@ -146,9 +163,13 @@ namespace ICSharpCode.SharpDevelop.Parser // restart if necessary: if (actions.Count > 0) { actions.Dequeue(); // dequeue the null - WorkbenchSingleton.SafeThreadAsyncCall(StartRunningIfRequired); + if (actions.Count > 0) + WorkbenchSingleton.SafeThreadAsyncCall(StartRunningIfRequired); + else + loadSolutionProjects.RaiseThreadEnded(); + } else { + loadSolutionProjects.RaiseThreadEnded(); } - RaiseThreadEnded(); return; } task = this.actions.Dequeue(); diff --git a/src/Main/SharpDevelop/Parser/ParserService.cs b/src/Main/SharpDevelop/Parser/ParserService.cs index cb9c7ce9c6..51b11b3792 100644 --- a/src/Main/SharpDevelop/Parser/ParserService.cs +++ b/src/Main/SharpDevelop/Parser/ParserService.cs @@ -31,8 +31,11 @@ namespace ICSharpCode.SharpDevelop.Parser public ParserService() { parserDescriptors = AddInTree.BuildItems("/Workspace/Parser", null, false); + this.LoadSolutionProjectsThread = new LoadSolutionProjects(); } + public ILoadSolutionProjectsThread LoadSolutionProjectsThread { get; private set; } + #region ParseInformationUpdated public event EventHandler ParseInformationUpdated = delegate {}; @@ -42,14 +45,16 @@ namespace ICSharpCode.SharpDevelop.Parser // To ensure events are raised in the same order, we always invoke on the main thread. WorkbenchSingleton.SafeThreadAsyncCall( delegate { - string addition; - if (e.OldParsedFile == null) - addition = " (new)"; - else if (e.NewParsedFile == null) - addition = " (removed)"; - else - addition = " (updated)"; - LoggingService.Debug("ParseInformationUpdated " + e.FileName + addition); + if (!LoadSolutionProjectsThread.IsRunning) { + string addition; + if (e.OldParsedFile == null) + addition = " (new)"; + else if (e.NewParsedFile == null) + addition = " (removed)"; + else + addition = " (updated)"; + LoggingService.Debug("ParseInformationUpdated " + e.FileName + addition); + } ParseInformationUpdated(null, e); }); } diff --git a/src/Main/SharpDevelop/Sda/CallHelper.cs b/src/Main/SharpDevelop/Sda/CallHelper.cs index 316b63be67..3b8d95049f 100644 --- a/src/Main/SharpDevelop/Sda/CallHelper.cs +++ b/src/Main/SharpDevelop/Sda/CallHelper.cs @@ -55,7 +55,6 @@ namespace ICSharpCode.SharpDevelop.Sda if (properties.PropertiesName != null) { startup.PropertiesName = properties.PropertiesName; } - AssemblyParserService.DomPersistencePath = properties.DomPersistencePath; if (properties.ApplicationRootPath != null) { FileUtility.ApplicationRootPath = properties.ApplicationRootPath; @@ -90,6 +89,8 @@ namespace ICSharpCode.SharpDevelop.Sda LoggingService.Info("Loading AddInTree..."); startup.RunInitialization(); + ((AssemblyParserService)SD.AssemblyParserService).DomPersistencePath = properties.DomPersistencePath; + // Register events to marshal back Project.ProjectService.BuildStarted += delegate { this.callback.StartBuild(); }; Project.ProjectService.BuildFinished += delegate { this.callback.EndBuild(); }; diff --git a/src/Main/SharpDevelop/SharpDevelop.csproj b/src/Main/SharpDevelop/SharpDevelop.csproj index c386ece61c..044d6680bb 100644 --- a/src/Main/SharpDevelop/SharpDevelop.csproj +++ b/src/Main/SharpDevelop/SharpDevelop.csproj @@ -81,6 +81,8 @@ LoadSaveOptions.xaml Code + + @@ -144,6 +146,10 @@ {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1} ICSharpCode.AvalonEdit + + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} + Mono.Cecil + {53DCA265-3C3C-42F9-B647-F72BA678122B} ICSharpCode.NRefactory.CSharp