Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs')
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs458
1 files changed, 256 insertions, 202 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs
index 4a935785de..783044f2b7 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs
@@ -48,6 +48,7 @@ using System.Text;
using ICSharpCode.NRefactory.Completion;
using System.Diagnostics;
using MonoDevelop.Projects.SharedAssetsProjects;
+using Mono.CSharp.Nullable;
namespace MonoDevelop.Ide.TypeSystem
{
@@ -159,7 +160,7 @@ namespace MonoDevelop.Ide.TypeSystem
public static class TypeSystemService
{
- const string CurrentVersion = "1.1.5";
+ const string CurrentVersion = "1.1.8";
static readonly List<TypeSystemParserNode> parsers;
static string[] filesSkippedInParseThread = new string[0];
@@ -255,7 +256,7 @@ namespace MonoDevelop.Ide.TypeSystem
if (project != null)
CheckProjectOutput (project, true);
- pr.Value.ReconnectAssemblyReferences ();
+ pr.Value.referencesConnected = false;
}
}
@@ -269,6 +270,8 @@ namespace MonoDevelop.Ide.TypeSystem
var fileName = project.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration);
var wrapper = GetProjectContentWrapper (project);
+ if (wrapper == null)
+ return;
bool update = wrapper.UpdateTrackedOutputAssembly (fileName);
if (autoUpdate && update) {
wrapper.ReconnectAssemblyReferences ();
@@ -372,7 +375,7 @@ namespace MonoDevelop.Ide.TypeSystem
wrapper = null;
}
if (wrapper != null && (result.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) {
- var oldFile = wrapper.Content.GetFile (fileName);
+ var oldFile = wrapper._content.GetFile (fileName);
wrapper.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile));
UpdateProjectCommentTasks (wrapper, result);
if (oldFile != null)
@@ -387,7 +390,7 @@ namespace MonoDevelop.Ide.TypeSystem
continue;
// Use the project context because file lookup is faster there than in the project class.
var pcnt = cnt.Value;
- var file = pcnt.Content.GetFile (fileName);
+ var file = pcnt._content.GetFile (fileName);
if (file != null) {
var newResult = parser.Parse (false, fileName, new StringReader (content), pcnt.Project);
pcnt.UpdateContent (c => c.AddOrUpdateFiles (newResult.ParsedFile));
@@ -431,7 +434,7 @@ namespace MonoDevelop.Ide.TypeSystem
var result = parser.Parse (true, fileName, content);
lock (projectWrapperUpdateLock) {
if (wrapper != null && (result.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) {
- var oldFile = wrapper.Content.GetFile (fileName);
+ var oldFile = wrapper._content.GetFile (fileName);
wrapper.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile));
UpdateProjectCommentTasks (wrapper, result);
if (oldFile != null)
@@ -943,42 +946,22 @@ namespace MonoDevelop.Ide.TypeSystem
readonly Dictionary<Type, object> extensionObjects = new Dictionary<Type, object> ();
List<ProjectContentWrapper> referencedWrappers = new List<ProjectContentWrapper>();
List<UnresolvedAssemblyProxy> referencedAssemblies = new List<UnresolvedAssemblyProxy>();
- IProjectContent _content;
- bool referencesConnected;
-
- public bool ReferencesConnected {
- get {
- return GetReferencesConnected (this, new HashSet<ProjectContentWrapper> ());
- }
- }
+ internal IProjectContent _content;
+ internal bool referencesConnected;
+ /*
static bool GetReferencesConnected (ProjectContentWrapper pcw, HashSet<ProjectContentWrapper> wrapper)
{
if (wrapper.Contains (pcw))
return true;
wrapper.Add (pcw);
return pcw.referencesConnected && pcw.referencedWrappers.All (w => GetReferencesConnected (w, wrapper));
- }
-
- public bool IsLoaded {
- get {
- return GetIsLoaded (this, new HashSet<ProjectContentWrapper> ());
- }
- }
-
- static bool GetIsLoaded (ProjectContentWrapper pcw, HashSet<ProjectContentWrapper> wrapper)
- {
- if (wrapper.Contains (pcw))
- return true;
- wrapper.Add (pcw);
- return !pcw.InLoad && pcw.referencedWrappers.All (w => GetIsLoaded (w, wrapper));
- }
+ }*/
public IProjectContent Content {
get {
if (!referencesConnected) {
- referencesConnected = true;
- ReconnectAssemblyReferences ();
+ EnsureReferencesAreLoaded ();
}
return _content;
}
@@ -1050,12 +1033,14 @@ namespace MonoDevelop.Ide.TypeSystem
public void RunWhenLoaded (Action<IProjectContent> act)
{
lock (updateContentLock) {
- if (Content is LazyProjectLoader) {
- if (loadActions != null) {
- loadActions.Clear ();
- loadActions.Add (act);
+ var lazyProjectLoader = _content as LazyProjectLoader;
+ if (loadActions != null) {
+ lock (loadActions) {
+ if (lazyProjectLoader != null && !lazyProjectLoader.ContextTask.IsCompleted) {
+ loadActions.Add (act);
+ return;
+ }
}
- return;
}
}
act (Content);
@@ -1073,29 +1058,43 @@ namespace MonoDevelop.Ide.TypeSystem
continue;
cleared.Add (cur);
cur.compilation = null;
- foreach (var project in cur.ReferencedProjects)
- stack.Push (GetProjectContentWrapper (project));
+ foreach (var project in cur.ReferencedProjects) {
+ var projectContentWrapper = GetProjectContentWrapper (project);
+ if (projectContentWrapper != null)
+ stack.Push (projectContentWrapper);
+ }
}
}
readonly object updateContentLock = new object ();
+ void RunLoadActions ()
+ {
+ if (loadActions == null)
+ return;
+ Action<IProjectContent>[] actions;
+ lock (loadActions) {
+ actions = loadActions.ToArray ();
+ loadActions = null;
+ }
+ foreach (var action in actions)
+ action (Content);
+ }
+
public void UpdateContent (Func<IProjectContent, IProjectContent> updateFunc)
{
+ LazyProjectLoader lazyProjectLoader;
lock (updateContentLock) {
- var lazyProjectLoader = Content as LazyProjectLoader;
+ lazyProjectLoader = Content as LazyProjectLoader;
if (lazyProjectLoader != null) {
lazyProjectLoader.ContextTask.Wait ();
- if (loadActions != null) {
- var action = loadActions.FirstOrDefault ();
- loadActions = null;
- if (action != null)
- action (Content);
- }
}
Content = updateFunc (Content);
ClearCachedCompilations ();
WasChanged = true;
+ if (lazyProjectLoader != null && !(Content is LazyProjectLoader)) {
+ RunLoadActions ();
+ }
}
}
@@ -1144,6 +1143,8 @@ namespace MonoDevelop.Ide.TypeSystem
{
lock (loadOperationLocker) {
loadOperationDepth++;
+ if (loadOperationDepth == 1)
+ UpdateLoadState ();
}
}
@@ -1153,13 +1154,15 @@ namespace MonoDevelop.Ide.TypeSystem
if (loadOperationDepth > 0) {
loadOperationDepth--;
}
+ if (loadOperationDepth == 0)
+ UpdateLoadState ();
}
- OnLoad (EventArgs.Empty);
}
- bool inLoad;
- public bool InLoad {
+
+ bool isLoaded;
+ public bool IsLoaded {
get {
- return inLoad;
+ return isLoaded;
}
}
@@ -1174,52 +1177,38 @@ namespace MonoDevelop.Ide.TypeSystem
void UpdateLoadState ()
{
- inLoad = loadOperationDepth > 0 || referencedWrappers.Any (w => w.InLoad) || referencedAssemblies.Any (a => a.InLoad);
+ bool wasLoaded = isLoaded;
+ isLoaded = loadOperationDepth == 0 && referencesConnected && !referencedAssemblies.Any (a => a.InLoad);
+ if (isLoaded && !wasLoaded)
+ OnLoad (EventArgs.Empty);
}
internal void RequestLoad ()
{
- UpdateLoadState ();
- if (!InLoad)
- return;
+ BeginLoadOperation ();
+ EnsureReferencesAreLoaded ();
CancelLoad ();
src = new CancellationTokenSource ();
var token = src.Token;
- Task.Factory.StartNew (delegate {
- var s = new Stack<ProjectContentWrapper> ();
- s.Push (this);
- var w = new HashSet<ProjectContentWrapper> ();
- while (s.Count > 0) {
- var wrapper = s.Pop ();
- if (token.IsCancellationRequested)
- return;
- if (w.Contains (wrapper))
- continue;
- w.Add (wrapper);
-
- foreach (var asm in wrapper.referencedAssemblies.ToArray ()) {
+ //Task.Factory.StartNew (delegate {
+ try {
+ foreach (var asm in referencedAssemblies.ToArray ()) {
if (token.IsCancellationRequested)
- return;
+ break;
var ctxLoader = asm.CtxLoader;
if (ctxLoader != null)
ctxLoader.EnsureAssemblyLoaded ();
}
- foreach (var rw in wrapper.referencedWrappers.ToArray ()) {
- if (token.IsCancellationRequested)
- return;
- s.Push (rw);
- }
+ } finally {
+ EndLoadOperation ();
}
- });
+ //});
}
public event EventHandler Loaded;
protected virtual void OnLoad (EventArgs e)
{
- UpdateLoadState ();
- if (InLoad)
- return;
var handler = Loaded;
if (handler != null)
handler (this, e);
@@ -1244,7 +1233,8 @@ namespace MonoDevelop.Ide.TypeSystem
if (project == null)
throw new ArgumentNullException ("project");
this.Project = project;
- this.Content = new LazyProjectLoader (this);
+ var lazyProjectLoader = new LazyProjectLoader (this);
+ this.Content = lazyProjectLoader;
}
public IEnumerable<Project> ReferencedProjects {
@@ -1263,18 +1253,29 @@ namespace MonoDevelop.Ide.TypeSystem
return contextTask;
}
}
-
+ object contentLock = new object ();
+ IProjectContent contentWithReferences;
public IProjectContent Content {
get {
- if (References != null)
- return contextTask.Result.AddAssemblyReferences (References);
- return contextTask.Result;
+ lock (contentLock) {
+ if (References != null) {
+ return contentWithReferences ?? (contentWithReferences = contextTask.Result.AddAssemblyReferences (References));
+ }
+ return contextTask.Result;
+ }
}
}
+ List<IAssemblyReference> references;
public List<IAssemblyReference> References {
- get;
- set;
+ get {
+ return references;
+ }
+ set {
+ lock (contentLock) {
+ references = value;
+ }
+ }
}
public LazyProjectLoader (ProjectContentWrapper wrapper)
@@ -1504,106 +1505,127 @@ namespace MonoDevelop.Ide.TypeSystem
}
return false;
}
- public void ReconnectAssemblyReferences ()
+
+ List<UnresolvedAssemblyProxy> LoadReferencedAssemblies (DotNetProject netProject)
{
- var netProject = Project as DotNetProject;
- if (netProject == null)
- return;
- CancelLoad ();
+ var newReferencedAssemblies = new List<UnresolvedAssemblyProxy> ();
try {
- var contexts = new List<IAssemblyReference> ();
- var nonCyclicCache = new HashSet<Project> ();
- foreach (var referencedWrapper in referencedWrappers) {
- referencedWrapper.Loaded -= HandleReferencedProjectInLoadChange;
- }
- var newReferencedWrappers = new List<ProjectContentWrapper>();
- foreach (var referencedProject in ReferencedProjects) {
- ProjectContentWrapper wrapper;
- if (projectContents.TryGetValue (referencedProject, out wrapper)) {
- if (HasCyclicRefs (wrapper, nonCyclicCache))
- continue;
- wrapper.Loaded += HandleReferencedProjectInLoadChange;
- newReferencedWrappers.Add (wrapper);
- contexts.Add (new UnresolvedAssemblyDecorator (wrapper));
+ foreach (string file in netProject.GetReferencedAssemblies (IdeApp.IsInitialized ? IdeApp.Workspace.ActiveConfiguration : ConfigurationSelector.Default, false)) {
+ string fileName;
+ if (!Path.IsPathRooted (file)) {
+ fileName = Path.Combine (Path.GetDirectoryName (netProject.FileName), file);
+ }
+ else {
+ fileName = Path.GetFullPath (file);
+ }
+ var ctx = LoadAssemblyContext (fileName);
+ if (ctx != null) {
+ newReferencedAssemblies.Add (ctx);
+ ctx.Loaded += HandleReferencedProjectInLoadChange;
+ }
+ else {
+ LoggingService.LogWarning ("TypeSystemService: Can't load assembly context for:" + file);
}
}
- this.referencedWrappers = newReferencedWrappers;
+ }
+ catch (Exception e) {
+ LoggingService.LogError ("Error while getting assembly references", e);
+ }
+ return newReferencedAssemblies;
+ }
- UnresolvedAssemblyProxy ctx;
- // Add mscorlib reference
+ object assemblyReconnectLock = new object();
- var config = IdeApp.Workspace != null ? netProject.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration : null;
- bool noStdLib = false;
- if (config != null) {
- var parameters = config.CompilationParameters as DotNetConfigurationParameters;
- if (parameters != null) {
- noStdLib = parameters.NoStdLib;
+ public void EnsureReferencesAreLoaded ()
+ {
+ lock (assemblyReconnectLock) {
+ if (referencesConnected)
+ return;
+ compilation = null;
+ referencesConnected = true;
+ var netProject = Project as DotNetProject;
+ if (netProject == null)
+ return;
+ try {
+ var contexts = new List<IAssemblyReference> ();
+ var nonCyclicCache = new HashSet<Project> ();
+ foreach (var referencedWrapper in referencedWrappers) {
+ referencedWrapper.Loaded -= HandleReferencedProjectInLoadChange;
}
- }
-
- if (!noStdLib && netProject.TargetRuntime != null && netProject.TargetRuntime.AssemblyContext != null) {
- var corLibRef = netProject.TargetRuntime.AssemblyContext.GetAssemblyForVersion (
- typeof(object).Assembly.FullName,
- null,
- netProject.TargetFramework
- );
- if (corLibRef != null) {
- ctx = LoadAssemblyContext (corLibRef.Location);
- if (ctx != null)
- contexts.Add (ctx);
+ var newReferencedWrappers = new List<ProjectContentWrapper> ();
+ foreach (var referencedProject in ReferencedProjects) {
+ ProjectContentWrapper wrapper;
+ if (projectContents.TryGetValue (referencedProject, out wrapper)) {
+ if (HasCyclicRefs (wrapper, nonCyclicCache))
+ continue;
+ wrapper.Loaded += HandleReferencedProjectInLoadChange;
+ newReferencedWrappers.Add (wrapper);
+ contexts.Add (new UnresolvedAssemblyDecorator (wrapper));
+ }
}
- }
- // Get the assembly references throught the project, since it may have custom references
- foreach (var asm in referencedAssemblies) {
- asm.Loaded += HandleReferencedProjectInLoadChange;
- }
- var newReferencedAssemblies = new List<UnresolvedAssemblyProxy>();
- try {
- foreach (string file in netProject.GetReferencedAssemblies (IdeApp.IsInitialized ? IdeApp.Workspace.ActiveConfiguration : ConfigurationSelector.Default, false)) {
- string fileName;
- if (!Path.IsPathRooted (file)) {
- fileName = Path.Combine (Path.GetDirectoryName (netProject.FileName), file);
- } else {
- fileName = Path.GetFullPath (file);
+ this.referencedWrappers = newReferencedWrappers;
+ UnresolvedAssemblyProxy ctx;
+ // Add mscorlib reference
+ var config = IdeApp.Workspace != null ? netProject.GetConfiguration (IdeApp.Workspace.ActiveConfiguration) as DotNetProjectConfiguration : null;
+ bool noStdLib = false;
+ if (config != null) {
+ var parameters = config.CompilationParameters as DotNetCompilerParameters;
+ if (parameters != null) {
+ noStdLib = parameters.NoStdLib;
}
- ctx = LoadAssemblyContext (fileName);
- if (ctx != null) {
- newReferencedAssemblies.Add (ctx);
- ctx.Loaded += HandleReferencedProjectInLoadChange;
- contexts.Add (ctx);
- } else {
- LoggingService.LogWarning ("TypeSystemService: Can't load assembly context for:" + file);
+ }
+ if (!noStdLib && netProject.TargetRuntime != null && netProject.TargetRuntime.AssemblyContext != null) {
+ var corLibRef = netProject.TargetRuntime.AssemblyContext.GetAssemblyForVersion (typeof(object).Assembly.FullName, null, netProject.TargetFramework);
+ if (corLibRef != null) {
+ ctx = LoadAssemblyContext (corLibRef.Location);
+ if (ctx != null)
+ contexts.Add (ctx);
}
}
+ // Get the assembly references throught the project, since it may have custom references
+ foreach (var asm in referencedAssemblies) {
+ asm.Loaded += HandleReferencedProjectInLoadChange;
+ }
+ var newReferencedAssemblies = LoadReferencedAssemblies (netProject);
+ contexts.AddRange (newReferencedAssemblies);
+ referencedAssemblies = newReferencedAssemblies;
+ bool changed = WasChanged;
+ var lazyProjectLoader = Content as LazyProjectLoader;
+ if (lazyProjectLoader != null) {
+ lazyProjectLoader.References = contexts;
+ }
+ else {
+ UpdateContent (c => c.RemoveAssemblyReferences (Content.AssemblyReferences).AddAssemblyReferences (contexts));
+ }
+ WasChanged = changed;
} catch (Exception e) {
- LoggingService.LogError ("Error while getting assembly references", e);
- }
- referencedAssemblies = newReferencedAssemblies;
- bool changed = WasChanged;
- var lazyProjectLoader = Content as LazyProjectLoader;
- if (lazyProjectLoader != null) {
- lazyProjectLoader.References = contexts;
- } else {
- UpdateContent (c => c.RemoveAssemblyReferences (Content.AssemblyReferences));
- UpdateContent (c => c.AddAssemblyReferences (contexts));
- }
- WasChanged = changed;
- } catch (Exception e) {
- if (netProject.TargetRuntime == null) {
- LoggingService.LogError ("Target runtime was null: " + Project.Name);
- } else if (netProject.TargetRuntime.AssemblyContext == null) {
- LoggingService.LogError ("Target runtime assembly context was null: " + Project.Name);
+ if (netProject.TargetRuntime == null) {
+ LoggingService.LogError ("Target runtime was null: " + Project.Name);
+ } else if (netProject.TargetRuntime.AssemblyContext == null) {
+ LoggingService.LogError ("Target runtime assembly context was null: " + Project.Name);
+ }
+ LoggingService.LogError ("Error while reloading all references of project: " + Project.Name, e);
+ } finally {
+ UpdateLoadState ();
}
- LoggingService.LogError ("Error while reloading all references of project: " + Project.Name, e);
- } finally {
+ }
+ }
+ object reconnectLock = new object();
+ public void ReconnectAssemblyReferences ()
+ {
+ var netProject = Project as DotNetProject;
+ if (netProject == null)
+ return;
+ lock (reconnectLock) {
+ CancelLoad ();
+ this.referencesConnected = false;
RequestLoad ();
- OnLoad (EventArgs.Empty);
}
}
void HandleReferencedProjectInLoadChange (object sender, EventArgs e)
{
- OnLoad (EventArgs.Empty);
+ UpdateLoadState ();
}
internal void Unload ()
@@ -1643,7 +1665,6 @@ namespace MonoDevelop.Ide.TypeSystem
project.FileRenamedInProject += OnFileRenamed;
project.Modified += OnProjectModified;
-
if (dotNetProject != null) {
StartFrameworkLookup (dotNetProject);
}
@@ -1686,7 +1707,7 @@ namespace MonoDevelop.Ide.TypeSystem
foreach (ProjectFileEventInfo fargs in args) {
var wrapper = projectContents [project];
var fileName = fargs.ProjectFile.Name;
- var file = wrapper.Content.GetFile (fileName);
+ var file = wrapper._content.GetFile (fileName);
if (file == null)
continue;
wrapper.UpdateContent (c => c.RemoveFiles (fileName));
@@ -1703,7 +1724,7 @@ namespace MonoDevelop.Ide.TypeSystem
var project = (Project)sender;
foreach (ProjectFileRenamedEventInfo fargs in args) {
var content = projectContents [project];
- var file = content.Content.GetFile (fargs.OldName);
+ var file = content._content.GetFile (fargs.OldName);
if (file == null)
continue;
content.UpdateContent (c => c.RemoveFiles (fargs.OldName));
@@ -1763,7 +1784,7 @@ namespace MonoDevelop.Ide.TypeSystem
TrackFileChanges = true;
}
- internal static void UnloadProject (Project project)
+ internal static void UnloadProject (Project project, bool skipProjectSerialization = false)
{
if (DecLoadCount (project) != 0)
return;
@@ -1779,7 +1800,8 @@ namespace MonoDevelop.Ide.TypeSystem
return;
projectContents.Remove (project);
}
- StoreProjectCache (project, wrapper);
+ if (!skipProjectSerialization)
+ StoreProjectCache (project, wrapper);
OnProjectUnloaded (new ProjectUnloadEventArgs (project, wrapper));
wrapper.Unload ();
}
@@ -1809,10 +1831,10 @@ namespace MonoDevelop.Ide.TypeSystem
if (project != null) {
var wrapper = LoadProject (project);
if (wrapper != null) {
- wrapper.ReconnectAssemblyReferences ();
var files = wrapper.Project.Files.ToArray ();
Task.Factory.StartNew (delegate {
CheckModifiedFiles (wrapper.Project, files, wrapper);
+ wrapper.RequestLoad ();
});
}
}
@@ -2020,6 +2042,11 @@ namespace MonoDevelop.Ide.TypeSystem
}
#endregion
+
+ public override string ToString ()
+ {
+ return string.Format ("[UnresolvedAssemblyProxy: FileName={0}]", FileName);
+ }
}
internal class LazyAssemblyLoader : IUnresolvedAssembly
@@ -2242,11 +2269,13 @@ namespace MonoDevelop.Ide.TypeSystem
this.cache = cache;
}
+
IUnresolvedAssembly LoadAssembly ()
{
var assemblyPath = cache != null ? Path.Combine (cache, "assembly.data") : null;
+ var assemblyTag = cache != null ? Path.Combine (cache, "assembly.tag") : null;
try {
- if (assemblyPath != null && File.Exists (assemblyPath)) {
+ if (assemblyPath != null && assemblyTag != null && File.Exists (assemblyPath) && File.Exists (assemblyTag)) {
var deserializedAssembly = DeserializeObject <IUnresolvedAssembly> (assemblyPath);
if (deserializedAssembly != null) {
return deserializedAssembly;
@@ -2268,13 +2297,7 @@ namespace MonoDevelop.Ide.TypeSystem
if (cache != null) {
var writeTime = File.GetLastWriteTimeUtc (fileName);
SerializeObject (assemblyPath, result);
- if (File.Exists (assemblyPath)) {
- try {
- File.SetCreationTimeUtc (assemblyPath, writeTime);
- } catch (Exception e) {
- LoggingService.LogError ("Can't set creation time for: " + assemblyPath, e);
- }
- }
+ SerializeObject (assemblyTag, new AssemblyTag (writeTime));
}
return result;
}
@@ -2380,6 +2403,8 @@ namespace MonoDevelop.Ide.TypeSystem
if (project == null)
throw new ArgumentNullException ("project");
var content = GetProjectContentWrapper (project);
+ if (content == null)
+ return null;
return content.Content;
}
@@ -2388,6 +2413,8 @@ namespace MonoDevelop.Ide.TypeSystem
if (project == null)
throw new ArgumentNullException ("project");
var content = GetProjectContentWrapper (project);
+ if (content == null)
+ return null;
return content.Compilation;
}
@@ -2532,7 +2559,12 @@ namespace MonoDevelop.Ide.TypeSystem
ProjectContentWrapper content;
if (projectContents.TryGetValue (project, out content))
return content;
- return new ProjectContentWrapper (project);
+ // in case of outdated projects try to get the most recent project wrapper.
+ foreach (var cnt in projectContents) {
+ if (cnt.Key.FileName == project.FileName)
+ return cnt.Value;
+ }
+ return null;
}
public static IProjectContent GetContext (FilePath file, string mimeType, string text)
@@ -2569,7 +2601,7 @@ namespace MonoDevelop.Ide.TypeSystem
}
class InternalProgressMonitor
- : NullProgressMonitor
+ : ProgressMonitor
{
public InternalProgressMonitor ()
{
@@ -2582,9 +2614,9 @@ namespace MonoDevelop.Ide.TypeSystem
}
}
- internal static IProgressMonitor GetParseProgressMonitor ()
+ internal static ProgressMonitor GetParseProgressMonitor ()
{
- var mon = ParseProgressMonitorFactory != null ? ParseProgressMonitorFactory.CreateProgressMonitor () : new NullProgressMonitor ();
+ var mon = ParseProgressMonitorFactory != null ? ParseProgressMonitorFactory.CreateProgressMonitor () : new ProgressMonitor ();
return new AggregatedProgressMonitor (mon, new InternalProgressMonitor ());
}
@@ -2596,7 +2628,7 @@ namespace MonoDevelop.Ide.TypeSystem
public ProjectContentWrapper Context;
public IEnumerable<ProjectFile> FileList;
// public Action<string, IProgressMonitor> ParseCallback;
- public void Run (IProgressMonitor monitor, CancellationToken token)
+ public void Run (ProgressMonitor monitor, CancellationToken token)
{
TypeSystemParserNode node = null;
TypeSystemParser parser = null;
@@ -2635,7 +2667,7 @@ namespace MonoDevelop.Ide.TypeSystem
tags.UpdateTags (Context.Project, parsedDocument.FileName, parsedDocument.TagComments);
if (token.IsCancellationRequested)
return;
- parsedFiles.Add (Tuple.Create (parsedDocument, Context.Content.GetFile (fileName)));
+ parsedFiles.Add (Tuple.Create (parsedDocument, Context._content.GetFile (fileName)));
}
Context.UpdateContent (c => c.AddOrUpdateFiles (parsedFiles.Select (p => p.Item1.ParsedFile)));
foreach (var file in parsedFiles) {
@@ -2643,11 +2675,12 @@ namespace MonoDevelop.Ide.TypeSystem
return;
if (file.Item2 != null)
Context.InformFileRemoved (new ParsedFileEventArgs (file.Item2));
- Context.InformFileAdded (new ParsedFileEventArgs (file.Item1.ParsedFile));
+ var parsedDocument = file.Item1;
+ if ((parsedDocument.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable)
+ Context.InformFileAdded (new ParsedFileEventArgs (parsedDocument.ParsedFile));
}
} finally {
- if (!token.IsCancellationRequested)
- Context.EndLoadOperation ();
+ Context.EndLoadOperation ();
}
}
}
@@ -2781,28 +2814,31 @@ namespace MonoDevelop.Ide.TypeSystem
static bool IsFileModified (ProjectFile file, IUnresolvedFile parsedFile)
{
- if (parsedFile == null)
+ if (parsedFile == null || !parsedFile.LastWriteTime.HasValue)
return true;
try {
- return File.GetLastWriteTimeUtc (file.FilePath) > parsedFile.LastWriteTime;
+ return File.GetLastWriteTimeUtc (file.FilePath) != parsedFile.LastWriteTime;
} catch (Exception) {
- return false;
+ return true;
}
}
static void CheckModifiedFiles (Project project, ProjectFile[] projectFiles, ProjectContentWrapper content, CancellationToken token = default (CancellationToken))
{
- if (token.IsCancellationRequested)
+ if (token.IsCancellationRequested) {
return;
+ }
+// Console.WriteLine ("add modified file check for :" + project.Name);
content.RunWhenLoaded (delegate(IProjectContent cnt) {
try {
+// Console.WriteLine ("check for " + project.Name);
content.BeginLoadOperation ();
var modifiedFiles = new List<ProjectFile> ();
var oldFileNewFile = new List<Tuple<ProjectFile, IUnresolvedFile>> ();
-
foreach (var file in projectFiles) {
- if (token.IsCancellationRequested)
+ if (token.IsCancellationRequested) {
return;
+ }
if (file.BuildAction == null)
continue;
// if the file is already inside the content a parser exists for it, if not check if it can be parsed.
@@ -2827,8 +2863,9 @@ namespace MonoDevelop.Ide.TypeSystem
// check if file needs to be removed from project content
foreach (var file in cnt.Files) {
- if (token.IsCancellationRequested)
+ if (token.IsCancellationRequested) {
return;
+ }
if (project.GetProjectFile (file.FileName) == null) {
content.UpdateContent (c => c.RemoveFiles (file.FileName));
content.InformFileRemoved (new ParsedFileEventArgs (file));
@@ -2836,37 +2873,54 @@ namespace MonoDevelop.Ide.TypeSystem
tags.RemoveFile (project, file.FileName);
}
}
- if (token.IsCancellationRequested)
+ if (token.IsCancellationRequested) {
return;
- if (modifiedFiles.Count > 0)
+ }
+ if (modifiedFiles.Count > 0) {
QueueParseJob (content, modifiedFiles);
+ WaitForParseJob ();
+ }
} catch (Exception e) {
LoggingService.LogError ("Exception in check modified files.", e);
} finally {
content.EndLoadOperation ();
}
-
});
}
+ /// <summary>
+ /// Used to store meta data information about the assembly.
+ /// </summary>
+ [Serializable]
+ class AssemblyTag
+ {
+ public DateTime LastWriteTimeUTC { get; set; }
+
+ public AssemblyTag (DateTime lastWriteTimeUTC)
+ {
+ this.LastWriteTimeUTC = lastWriteTimeUTC;
+ }
+ }
+
static void CheckModifiedFile (UnresolvedAssemblyProxy context)
{
try {
string cache = GetCacheDirectory (context.FileName);
if (cache == null)
return;
- var assemblyDataDirectory = Path.Combine (cache, "assembly.data");
+ var assemblyDataDirectory = Path.Combine (cache, "assembly.tag");
var writeTime = File.GetLastWriteTimeUtc (context.FileName);
- var cacheTime = File.Exists (assemblyDataDirectory) ? File.GetCreationTimeUtc (assemblyDataDirectory) : writeTime;
- if (writeTime != cacheTime) {
+ var cacheTime = File.Exists (assemblyDataDirectory) ? DeserializeObject<AssemblyTag> (assemblyDataDirectory) : new AssemblyTag (writeTime);
+ if (writeTime != cacheTime.LastWriteTimeUTC) {
cache = GetCacheDirectory (context.FileName);
if (cache != null) {
- context.CtxLoader = new LazyAssemblyLoader (context.FileName, cache);
try {
- // File is reloaded by the lazy loader
+ // Files will be reloaded by the lazy loader
File.Delete (assemblyDataDirectory);
+ File.Delete (Path.Combine (cache, "assembly.data"));
} catch {
}
+ context.CtxLoader = new LazyAssemblyLoader (context.FileName, cache);
}
}
} catch (Exception e) {
@@ -2899,7 +2953,7 @@ namespace MonoDevelop.Ide.TypeSystem
static void ConsumeParsingQueue ()
{
int pending = 0;
- IProgressMonitor monitor = null;
+ ProgressMonitor monitor = null;
var token = loadCancellationSource.Token;
StartParseOperation ();
try {