Browse Source

Run LoadSolutionProjectsThread when a solution is being opened.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
d4e36711ec
  1. 23
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/RopeTextSource.cs
  2. 7
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs
  3. 6
      src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs
  4. 30
      src/Main/Base/Project/Src/Project/CompilableProject.cs
  5. 255
      src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
  6. 3
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

23
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/RopeTextSource.cs

@ -14,6 +14,7 @@ namespace ICSharpCode.AvalonEdit.Document
public sealed class RopeTextSource : ITextSource public sealed class RopeTextSource : ITextSource
{ {
readonly Rope<char> rope; readonly Rope<char> rope;
readonly ITextSourceVersion version;
/// <summary> /// <summary>
/// Creates a new RopeTextSource. /// Creates a new RopeTextSource.
@ -22,7 +23,18 @@ namespace ICSharpCode.AvalonEdit.Document
{ {
if (rope == null) if (rope == null)
throw new ArgumentNullException("rope"); throw new ArgumentNullException("rope");
this.rope = rope; this.rope = rope.Clone();
}
/// <summary>
/// Creates a new RopeTextSource.
/// </summary>
public RopeTextSource(Rope<char> rope, ITextSourceVersion version)
{
if (rope == null)
throw new ArgumentNullException("rope");
this.rope = rope.Clone();
this.version = version;
} }
/// <summary> /// <summary>
@ -30,7 +42,6 @@ namespace ICSharpCode.AvalonEdit.Document
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// RopeTextSource only publishes a copy of the contained rope to ensure that the underlying rope cannot be modified. /// RopeTextSource only publishes a copy of the contained rope to ensure that the underlying rope cannot be modified.
/// Unless the creator of the RopeTextSource still has a reference on the rope, RopeTextSource is immutable.
/// </remarks> /// </remarks>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification="Not a property because it creates a clone")] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification="Not a property because it creates a clone")]
public Rope<char> GetRope() public Rope<char> GetRope()
@ -75,8 +86,7 @@ namespace ICSharpCode.AvalonEdit.Document
/// <inheritdoc/> /// <inheritdoc/>
public ITextSource CreateSnapshot() public ITextSource CreateSnapshot()
{ {
// we clone the underlying rope because the creator of the RopeTextSource might be modifying it return this;
return new RopeTextSource(rope.Clone());
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -91,8 +101,9 @@ namespace ICSharpCode.AvalonEdit.Document
return rope.IndexOfAny(anyOf, startIndex, count); return rope.IndexOfAny(anyOf, startIndex, count);
} }
ITextSourceVersion ITextSource.Version { /// <inheritdoc/>
get { return null; } public ITextSourceVersion Version {
get { return version; }
} }
string ITextSource.GetText(ICSharpCode.Editor.ISegment segment) string ITextSource.GetText(ICSharpCode.Editor.ISegment segment)

7
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Document/TextDocument.cs

@ -298,7 +298,9 @@ namespace ICSharpCode.AvalonEdit.Document
public ITextSource CreateSnapshot() public ITextSource CreateSnapshot()
{ {
lock (lockObject) { lock (lockObject) {
return new RopeTextSource(rope.Clone()); if (currentCheckpoint == null)
currentCheckpoint = new ChangeTrackingCheckpoint(lockObject);
return new RopeTextSource(rope, currentCheckpoint);
} }
} }
@ -325,7 +327,7 @@ namespace ICSharpCode.AvalonEdit.Document
if (currentCheckpoint == null) if (currentCheckpoint == null)
currentCheckpoint = new ChangeTrackingCheckpoint(lockObject); currentCheckpoint = new ChangeTrackingCheckpoint(lockObject);
checkpoint = currentCheckpoint; checkpoint = currentCheckpoint;
return new RopeTextSource(rope.Clone()); return new RopeTextSource(rope, currentCheckpoint);
} }
} }
@ -927,6 +929,7 @@ namespace ICSharpCode.AvalonEdit.Document
var container = new ServiceContainer(); var container = new ServiceContainer();
container.AddService(typeof(IDocument), this); container.AddService(typeof(IDocument), this);
container.AddService(typeof(TextDocument), this); container.AddService(typeof(TextDocument), this);
serviceProvider = container;
} }
return serviceProvider; return serviceProvider;
} }

6
src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs

@ -2,19 +2,15 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.Editor;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion; using ICSharpCode.SharpDevelop.Editor.CodeCompletion;

30
src/Main/Base/Project/Src/Project/CompilableProject.cs

@ -10,6 +10,9 @@ using System.Linq;
using System.Runtime.InteropServices.ComTypes; using System.Runtime.InteropServices.ComTypes;
using System.Xml.Linq; using System.Xml.Linq;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project.Converter; using ICSharpCode.SharpDevelop.Project.Converter;
using ICSharpCode.SharpDevelop.Util; using ICSharpCode.SharpDevelop.Util;
@ -403,6 +406,10 @@ namespace ICSharpCode.SharpDevelop.Project
void Reparse(bool references, bool code) void Reparse(bool references, bool code)
{ {
lock (SyncRoot) {
if (parseProjectContent == null)
return; // parsing hasn't started yet; no need to re-parse
}
#warning Reparse #warning Reparse
throw new NotImplementedException(); throw new NotImplementedException();
} }
@ -643,5 +650,28 @@ namespace ICSharpCode.SharpDevelop.Project
} }
} }
#endregion #endregion
#region Type System
volatile ParseProjectContent parseProjectContent;
public override IProjectContent ProjectContent {
get {
if (parseProjectContent == null) {
lock (SyncRoot) {
if (parseProjectContent == null) {
parseProjectContent = new ParseProjectContent(this);
}
}
}
return parseProjectContent;
}
}
public override ITypeResolveContext TypeResolveContext {
get {
return new CompositeTypeResolveContext(new ITypeResolveContext[] { this.ProjectContent, MinimalResolveContext.Instance });
}
}
#endregion
} }
} }

255
src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

@ -7,130 +7,114 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Editor;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
/*
namespace ICSharpCode.SharpDevelop.Parser namespace ICSharpCode.SharpDevelop.Parser
{ {
public sealed class ParseProjectContent : DefaultProjectContent public class ParseProjectContent : SimpleProjectContent, IDisposable
{ {
readonly IProject project;
readonly object lockObj = new object();
bool initializing;
bool disposed;
public ParseProjectContent(IProject project) public ParseProjectContent(IProject project)
{ {
if (project == null) if (project == null)
throw new ArgumentNullException("project"); throw new ArgumentNullException("project");
this.project = project; this.project = project;
this.Language = project.LanguageProperties;
this.initializing = true; this.initializing = true;
LoadSolutionProjects.AddJob(Initialize, "Loading " + project.Name + "...", GetInitializationWorkAmount());
} }
readonly IProject project; public void Dispose()
{
public override object Project { lock (lockObj) {
get { ProjectService.ProjectItemAdded -= OnProjectItemAdded;
return project; ProjectService.ProjectItemRemoved -= OnProjectItemRemoved;
disposed = true;
} }
} initializing = false;
public string ProjectName {
get { return project.Name; }
} }
public override string AssemblyName { public override string AssemblyName {
get { return project.AssemblyName; } get { return project.AssemblyName; }
} }
bool initializing;
public override string ToString() public override string ToString()
{ {
return string.Format("[{0}: {1}]", GetType().Name, project.Name); return string.Format("[{0}: {1}]", GetType().Name, project.Name);
} }
internal void Initialize1(IProgressMonitor progressMonitor) int GetInitializationWorkAmount()
{ {
ICollection<ProjectItem> items = project.Items; return project.Items.Count + 15;
ProjectService.ProjectItemAdded += OnProjectItemAdded;
ProjectService.ProjectItemRemoved += OnProjectItemRemoved;
UpdateDefaultImports(items);
// TODO: Translate me
// progressMonitor.TaskName = "Resolving references for " + project.Name + "...";
project.ResolveAssemblyReferences();
foreach (ProjectItem item in items) {
if (!initializing) return; // abort initialization
progressMonitor.CancellationToken.ThrowIfCancellationRequested();
if (ItemType.ReferenceItemTypes.Contains(item.ItemType)) {
ReferenceProjectItem reference = item as ReferenceProjectItem;
if (reference != null) {
// TODO: Translate me
// progressMonitor.TaskName = "Loading " + reference.ShortName + "...";
AddReference(reference, false, progressMonitor.CancellationToken);
}
}
}
UpdateReferenceInterDependencies();
OnReferencedContentsChanged(EventArgs.Empty);
} }
internal void ReInitialize1(IProgressMonitor progressMonitor) void Initialize(IProgressMonitor progressMonitor)
{ {
var mscorlib = AssemblyParserService.GetRegistryForReference(new ReferenceProjectItem(project, "mscorlib")).Mscorlib; ICollection<ProjectItem> projectItems = project.Items;
// don't fetch mscorlib within lock - finding the correct registry might access the project, causing lock (lockObj) {
// a deadlock between IProject.SyncRoot and the ReferencedContents lock if (disposed) {
lock (ReferencedContents) { throw new ObjectDisposedException("ParseProjectContent");
ReferencedContents.Clear(); }
AddReferencedContent(mscorlib); ProjectService.ProjectItemAdded += OnProjectItemAdded;
ProjectService.ProjectItemRemoved += OnProjectItemRemoved;
} }
// prevent adding event handler twice using (IProgressMonitor initReferencesProgressMonitor = progressMonitor.CreateSubTask(15),
ProjectService.ProjectItemAdded -= OnProjectItemAdded; parseProgressMonitor = progressMonitor.CreateSubTask(projectItems.Count))
ProjectService.ProjectItemRemoved -= OnProjectItemRemoved; {
initializing = true; var resolveReferencesTask = ResolveReferencesAsync(projectItems, initReferencesProgressMonitor);
try {
Initialize1(progressMonitor); ParseFiles(projectItems, parseProgressMonitor);
} finally {
initializing = false; resolveReferencesTask.Wait();
} }
} }
void UpdateReferenceInterDependencies() void ParseFiles(ICollection<ProjectItem> projectItems, IProgressMonitor progressMonitor)
{ {
// Use ToArray because the collection could be modified inside the loop ParseableFileContentFinder finder = new ParseableFileContentFinder();
IProjectContent[] referencedContents; var fileContents = (
lock (this.ReferencedContents) { from p in projectItems.AsParallel().WithCancellation(progressMonitor.CancellationToken)
referencedContents = new IProjectContent[this.ReferencedContents.Count]; where !ItemType.NonFileItemTypes.Contains(p.ItemType) && !String.IsNullOrEmpty(p.FileName)
this.ReferencedContents.CopyTo(referencedContents, 0); select FileName.Create(p.FileName)
} ).ToList();
foreach (IProjectContent referencedContent in referencedContents) {
if (referencedContent is ReflectionProjectContent) { object progressLock = new object();
((ReflectionProjectContent)referencedContent).InitializeReferences(); double fileCountInverse = 1.0 / fileContents.Count;
Parallel.ForEach(
fileContents,
new ParallelOptions {
MaxDegreeOfParallelism = Environment.ProcessorCount,
CancellationToken = progressMonitor.CancellationToken
},
fileName => {
// 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 (ParserService.GetParser(fileName) != null) {
ITextSource content = finder.Create(fileName);
if (content != null)
ParserService.ParseFile(this, fileName, content);
}
lock (progressLock) {
progressMonitor.Progress += fileCountInverse;
}
} }
} );
} }
void AddReference(ReferenceProjectItem reference, bool updateInterDependencies, CancellationToken cancellationToken) System.Threading.Tasks.Task ResolveReferencesAsync(ICollection<ProjectItem> projectItems, IProgressMonitor progressMonitor)
{ {
try { return System.Threading.Tasks.Task.Factory.StartNew(
AddReferencedContent(AssemblyParserService.GetProjectContentForReference(reference)); delegate {
if (updateInterDependencies) { project.ResolveAssemblyReferences();
UpdateReferenceInterDependencies(); }, progressMonitor.CancellationToken);
}
OnReferencedContentsChanged(EventArgs.Empty);
// Refresh the reference if required.
// If the user removes the reference and then re-adds it, there might be other references
// in the project depending on it, so we do the refresh after the old reference was added.
AssemblyParserService.RefreshProjectContentForReference(reference);
} catch (OperationCanceledException) {
throw;
} catch (ObjectDisposedException e) {
// ObjectDisposedException can happen if project gets disposed while LoadSolutionProjectsThread is running.
// We will ignore the ObjectDisposedException and throw OperationCanceledException instead.
cancellationToken.ThrowIfCancellationRequested();
MessageService.ShowException(e);
} catch (Exception e) {
MessageService.ShowException(e);
}
} }
// ensure that com references are built serially because we cannot invoke multiple instances of MSBuild // ensure that com references are built serially because we cannot invoke multiple instances of MSBuild
@ -149,13 +133,13 @@ namespace ICSharpCode.SharpDevelop.Parser
project.Save(); // project is not yet saved when ItemAdded fires, so save it here project.Save(); // project is not yet saved when ItemAdded fires, so save it here
TaskService.BuildMessageViewCategory.AppendText("\n${res:MainWindow.CompilerMessages.CreatingCOMInteropAssembly}\n"); TaskService.BuildMessageViewCategory.AppendText("\n${res:MainWindow.CompilerMessages.CreatingCOMInteropAssembly}\n");
BuildCallback afterBuildCallback = delegate { BuildCallback afterBuildCallback = delegate {
ReparseReferences();
lock (callAfterAddComReference) { lock (callAfterAddComReference) {
if (callAfterAddComReference.Count > 0) { if (callAfterAddComReference.Count > 0) {
// run next enqueued action // run next enqueued action
callAfterAddComReference.Dequeue()(); callAfterAddComReference.Dequeue()();
} else { } else {
buildingComReference = false; buildingComReference = false;
ParserService.Reparse(project, true, false);
} }
} }
}; };
@ -173,18 +157,24 @@ namespace ICSharpCode.SharpDevelop.Parser
} }
} }
} else { } else {
ParserService.Reparse(project, true, false); ReparseReferences();
} }
} }
if (e.ProjectItem.ItemType == ItemType.Import) { if (e.ProjectItem.ItemType == ItemType.Import) {
UpdateDefaultImports(project.Items); throw new NotImplementedException();
//UpdateDefaultImports(project.Items);
} else if (e.ProjectItem.ItemType == ItemType.Compile) { } else if (e.ProjectItem.ItemType == ItemType.Compile) {
if (System.IO.File.Exists(e.ProjectItem.FileName)) { if (System.IO.File.Exists(e.ProjectItem.FileName)) {
ParserService.BeginParse(e.ProjectItem.FileName); ParserService.ParseFileAsync(FileName.Create(e.ProjectItem.FileName));
} }
} }
} }
void ReparseReferences()
{
throw new NotImplementedException();
}
void OnProjectItemRemoved(object sender, ProjectItemEventArgs e) void OnProjectItemRemoved(object sender, ProjectItemEventArgs e)
{ {
if (e.Project != project) return; if (e.Project != project) return;
@ -192,25 +182,21 @@ namespace ICSharpCode.SharpDevelop.Parser
ReferenceProjectItem reference = e.ProjectItem as ReferenceProjectItem; ReferenceProjectItem reference = e.ProjectItem as ReferenceProjectItem;
if (reference != null) { if (reference != null) {
try { try {
IProjectContent referencedContent = AssemblyParserService.GetExistingProjectContentForReference(reference); ReparseReferences();
if (referencedContent != null) {
lock (ReferencedContents) {
ReferencedContents.Remove(referencedContent);
}
OnReferencedContentsChanged(EventArgs.Empty);
}
} catch (Exception ex) { } catch (Exception ex) {
MessageService.ShowException(ex); MessageService.ShowException(ex);
} }
} }
if (e.ProjectItem.ItemType == ItemType.Import) { if (e.ProjectItem.ItemType == ItemType.Import) {
UpdateDefaultImports(project.Items); throw new NotImplementedException();
//UpdateDefaultImports(project.Items);
} else if (e.ProjectItem.ItemType == ItemType.Compile) { } else if (e.ProjectItem.ItemType == ItemType.Compile) {
ParserService.ClearParseInformation(e.ProjectItem.FileName); ParserService.ClearParseInformation(FileName.Create(e.ProjectItem.FileName));
} }
} }
/*
int languageDefaultImportCount = -1; int languageDefaultImportCount = -1;
void UpdateDefaultImports(ICollection<ProjectItem> items) void UpdateDefaultImports(ICollection<ProjectItem> items)
@ -233,77 +219,6 @@ namespace ICSharpCode.SharpDevelop.Parser
DefaultImports.Usings.Add(item.Include); DefaultImports.Usings.Add(item.Include);
} }
} }
} }*/
internal int GetInitializationWorkAmount()
{
return project.Items.Count;
}
internal void ReInitialize2(IProgressMonitor progressMonitor)
{
if (initializing) return;
initializing = true;
Initialize2(progressMonitor);
}
internal void Initialize2(IProgressMonitor progressMonitor)
{
if (!initializing) return;
try {
IProjectContent[] referencedContents;
lock (this.ReferencedContents) {
referencedContents = new IProjectContent[this.ReferencedContents.Count];
this.ReferencedContents.CopyTo(referencedContents, 0);
}
foreach (IProjectContent referencedContent in referencedContents) {
if (referencedContent is ReflectionProjectContent) {
((ReflectionProjectContent)referencedContent).InitializeReferences();
}
}
ParseableFileContentFinder finder = new ParseableFileContentFinder();
var fileContents = (
from p in project.Items.AsParallel().WithCancellation(progressMonitor.CancellationToken)
where !ItemType.NonFileItemTypes.Contains(p.ItemType) && !String.IsNullOrEmpty(p.FileName)
select FileName.Create(p.FileName)
).ToList();
object progressLock = new object();
double fileCountInverse = 1.0 / fileContents.Count;
Parallel.ForEach(
fileContents,
new ParallelOptions {
MaxDegreeOfParallelism = Environment.ProcessorCount * 2,
CancellationToken = progressMonitor.CancellationToken
},
fileName => {
// 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 (ParserService.GetParser(fileName) != null) {
ITextBuffer content = finder.Create(fileName);
if (content != null)
ParserService.ParseFile(this, fileName, content);
}
lock (progressLock) {
progressMonitor.Progress += fileCountInverse;
}
}
);
} finally {
initializing = false;
progressMonitor.Progress = 1;
}
}
public override void Dispose()
{
ProjectService.ProjectItemAdded -= OnProjectItemAdded;
ProjectService.ProjectItemRemoved -= OnProjectItemRemoved;
initializing = false;
base.Dispose();
}
} }
} }
*/

3
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -1033,6 +1033,9 @@ namespace ICSharpCode.SharpDevelop.Parser
internal static void OnSolutionLoaded() internal static void OnSolutionLoaded()
{ {
foreach (IProject project in ProjectService.OpenSolution.Projects) {
RegisterProjectContentForAddedProject(project);
}
} }
internal static void OnSolutionClosed() internal static void OnSolutionClosed()

Loading…
Cancel
Save