~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
using System.Threading.Tasks;
47
47
using ICSharpCode.NRefactory.Documentation;
48
48
using ICSharpCode.NRefactory.CSharp;
 
49
using MonoDevelop.Ide.Extensions;
 
50
using MonoDevelop.Core.Assemblies;
 
51
using System.Text;
49
52
 
50
53
namespace MonoDevelop.Ide.TypeSystem
51
54
{
87
90
                                return false;
88
91
                        return member.Attributes.Any (a => a.AttributeType.FullName == "System.ObsoleteAttribute");
89
92
                }
90
 
                
 
93
 
 
94
                public static bool IsObsolete (this IEntity member, out string reason)
 
95
                {
 
96
                        if (member == null) {
 
97
                                reason = null;
 
98
                                return false;
 
99
                        }
 
100
                        var attr = member.Attributes.FirstOrDefault (a => a.AttributeType.FullName == "System.ObsoleteAttribute");
 
101
                        if (attr == null) {
 
102
                                reason = null;
 
103
                                return false;
 
104
                        }
 
105
                        if (attr.PositionalArguments.Count > 0) {
 
106
                                reason = attr.PositionalArguments [0].ConstantValue.ToString ();
 
107
                        } else {
 
108
                                reason = null;
 
109
                        }
 
110
                        return true;
 
111
                }
 
112
 
91
113
                public static IType Resolve (this IUnresolvedTypeDefinition def, Project project)
92
114
                {
93
 
                        var pf = TypeSystemService.GetProjectContext (project).GetFile (def.Region.FileName);
94
 
                        var ctx = pf.GetTypeResolveContext (TypeSystemService.GetCompilation (project), def.Region.Begin);
95
 
                        return def.Resolve (ctx);
 
115
                        var compilation = TypeSystemService.GetCompilation (project);
 
116
                        var ctx = new SimpleTypeResolveContext (compilation.MainAssembly);
 
117
                        var resolvedType = def.Resolve (ctx);
 
118
                        return resolvedType;
96
119
                }
97
120
                
98
121
                [Obsolete("Do not use this method. Use type references to resolve types. Type references from full reflection names can be got from ReflectionHelper.ParseReflectionName.")]
145
168
        
146
169
        public static class TypeSystemService
147
170
        {
148
 
                const string CurrentVersion = "1.0";
 
171
                const string CurrentVersion = "1.1.1";
 
172
 
149
173
                static List<TypeSystemParserNode> parsers;
150
 
                public static readonly HashSet<string> FilesSkippedInParseThread = new HashSet<string> ();
 
174
                static string[] filesSkippedInParseThread = new string[0];
151
175
                static IEnumerable<TypeSystemParserNode> Parsers {
152
176
                        get {
153
177
                                return parsers;
154
178
                        }
155
179
                }
156
 
                
 
180
 
 
181
                public static void RemoveSkippedfile (FilePath fileName)
 
182
                {
 
183
                        filesSkippedInParseThread = filesSkippedInParseThread.Where (f => f != fileName).ToArray ();
 
184
                }
 
185
                public static void AddSkippedFile (FilePath fileName)
 
186
                {
 
187
                        if (filesSkippedInParseThread.Any (f => f == fileName))
 
188
                                return;
 
189
                        filesSkippedInParseThread = filesSkippedInParseThread.Concat (new string[] { fileName }).ToArray ();
 
190
                }
 
191
 
157
192
                static TypeSystemService ()
158
193
                {
159
194
                        parsers = new List<TypeSystemParserNode> ();
167
202
                                        break;
168
203
                                }
169
204
                        });
 
205
 
 
206
                        AddinManager.AddExtensionNodeHandler ("/MonoDevelop/TypeSystem/OutputTracking", delegate (object sender, ExtensionNodeEventArgs args) {
 
207
                                var projectType = ((TypeSystemOutputTrackingNode)args.ExtensionNode).ProjectType;
 
208
                                switch (args.Change) {
 
209
                                case ExtensionChange.Add:
 
210
                                        outputTrackedProjects.Add (projectType);
 
211
                                        break;
 
212
                                case ExtensionChange.Remove:
 
213
                                        outputTrackedProjects.Remove (projectType);
 
214
                                        break;
 
215
                                }
 
216
                        });
 
217
 
170
218
                        FileService.FileChanged += delegate(object sender, FileEventArgs e) {
171
219
                                if (!TrackFileChanges)
172
220
                                        return;
173
221
                                foreach (var file in e) {
174
222
                                        // Open documents are handled by the Document class itself.
175
 
                                        if (IdeApp.Workbench.GetDocument (file.FileName) != null)
 
223
                                        if (IdeApp.Workbench != null && IdeApp.Workbench.GetDocument (file.FileName) != null)
176
224
                                                continue;
177
225
                                        //
178
226
                                        lock (projectWrapperUpdateLock) {
181
229
                                                        if (projectFile != null)
182
230
                                                                QueueParseJob (wrapper, new [] { projectFile });
183
231
                                                }
184
 
                                        }
185
 
                                }
 
232
                                                AssemblyContext ctx;
 
233
                                                if (cachedAssemblyContents.TryGetValue (file.FileName, out ctx))
 
234
                                                        CheckModifiedFile (ctx);
 
235
                                        }
 
236
                                }
 
237
 
 
238
                                foreach (var content in projectContents.Values.ToArray ()) {
 
239
                                        var files = new List<ProjectFile> ();
 
240
                                        foreach (var file in e) {
 
241
                                                var f = content.Project.GetProjectFile (file.FileName);
 
242
                                                if (f == null || f.BuildAction != BuildAction.Compile)
 
243
                                                        continue;
 
244
                                                files.Add (f);
 
245
                                        }
 
246
                                        if (files.Count > 0)
 
247
                                                QueueParseJob (content, files);
 
248
                                }
 
249
 
186
250
                        };
 
251
                        if (IdeApp.ProjectOperations != null) {
 
252
                                IdeApp.ProjectOperations.EndBuild += HandleEndBuild;
 
253
                        }
 
254
                        if (IdeApp.Workspace != null) {
 
255
                                IdeApp.Workspace.ActiveConfigurationChanged += HandleActiveConfigurationChanged;
 
256
                        }
 
257
                }
 
258
 
 
259
                static void HandleActiveConfigurationChanged (object sender, EventArgs e)
 
260
                {
 
261
                        foreach (var pr in projectContents.Keys.ToArray ()) {
 
262
                                var project = pr as DotNetProject;
 
263
                                if (project != null)
 
264
                                        CheckProjectOutput (project, true);
 
265
                        }
 
266
                }
 
267
 
 
268
                static List<string> outputTrackedProjects =new List<string> ();
 
269
                static void CheckProjectOutput (DotNetProject project, bool autoUpdate)
 
270
                {
 
271
                        if (project == null)
 
272
                                throw new ArgumentNullException ("project");
 
273
                        if (outputTrackedProjects.Contains (project.ProjectType, StringComparer.OrdinalIgnoreCase)) {
 
274
                                var fileName = project.GetOutputFileName (IdeApp.Workspace.ActiveConfiguration);
 
275
 
 
276
                                bool update = GetProjectContentWrapper (project).UpdateTrackedOutputAssembly (fileName);
 
277
                                if (autoUpdate && update) {
 
278
                                        ReloadAllReferences (projectContents.Values.ToArray ());
 
279
 
 
280
                                        // update documents
 
281
                                        foreach (var openDocument in IdeApp.Workbench.Documents) {
 
282
                                                openDocument.ReparseDocument ();
 
283
                                        }
 
284
                                }
 
285
                        }
 
286
                }
 
287
 
 
288
                static void HandleEndBuild (object sender, BuildEventArgs args)
 
289
                {
 
290
                        var project = args.SolutionItem as DotNetProject;
 
291
                        if (project == null)
 
292
                                return;
 
293
                        CheckProjectOutput (project, true);
187
294
                }
188
295
                
189
 
                public static ITypeSystemParser GetParser (string mimeType)
 
296
                public static TypeSystemParser GetParser (string mimeType, string buildAction = BuildAction.Compile)
190
297
                {
191
 
                        var provider = Parsers.FirstOrDefault (p => p.CanParse (mimeType));
 
298
                        var provider = Parsers.FirstOrDefault (p => p.CanParse (mimeType, buildAction));
192
299
                        return provider != null ? provider.Parser : null;
193
300
                }
194
301
                
195
 
                static TypeSystemParserNode GetTypeSystemParserNode (string mimeType)
 
302
                static TypeSystemParserNode GetTypeSystemParserNode (string mimeType, string buildAction)
196
303
                {
197
 
                        return Parsers.FirstOrDefault (p => p.CanParse (mimeType));
 
304
                        return Parsers.FirstOrDefault (p => p.CanParse (mimeType, buildAction));
198
305
                }
199
306
                
200
307
                static List<MimeTypeExtensionNode> foldingParsers;
246
353
                        var parser = GetParser (mimeType);
247
354
                        if (parser == null)
248
355
                                return null;
 
356
 
 
357
                        var t = Counters.ParserService.FileParsed.BeginTiming (fileName);
249
358
                        try {
250
359
                                var result = parser.Parse (true, fileName, content, project);
251
360
                                lock (projectWrapperUpdateLock) {
256
365
                                                wrapper = null;
257
366
                                        }
258
367
                                        if (wrapper != null && (result.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) {
259
 
                                                wrapper.UpdateContent (c => c.UpdateProjectContent (c.GetFile (fileName), result.ParsedFile));
260
 
                                                UpdateParsedDocument (wrapper, result);
 
368
                                                var oldFile = wrapper.Content.GetFile (fileName);
 
369
                                                wrapper.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile));
 
370
                                                UpdateProjectCommentTasks (wrapper, result);
 
371
                                                if (oldFile != null)
 
372
                                                        wrapper.InformFileRemoved (new ParsedFileEventArgs (oldFile));
 
373
                                                wrapper.InformFileAdded (new ParsedFileEventArgs (result.ParsedFile));
261
374
                                        }
262
375
 
263
376
                                        // The parsed file could be included in other projects as well, therefore
268
381
                                                // Use the project context because file lookup is faster there than in the project class.
269
382
                                                var file = cnt.Value.Content.GetFile (fileName);
270
383
                                                if (file != null) {
271
 
                                                        cnt.Value.UpdateContent (c => c.UpdateProjectContent (file, result.ParsedFile));
 
384
                                                        cnt.Value.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile));
 
385
                                                        cnt.Value.InformFileRemoved (new ParsedFileEventArgs (file));
 
386
                                                        cnt.Value.InformFileAdded (new ParsedFileEventArgs (result.ParsedFile));
272
387
                                                }
273
388
                                        }
274
389
                                }
275
390
                                return result;
276
391
                        } catch (Exception e) {
277
 
                                LoggingService.LogError ("Exception while parsing :" + e);
 
392
                                LoggingService.LogError ("Exception while parsing: " + e);
278
393
                                return null;
 
394
                        } finally {
 
395
                                t.Dispose ();
279
396
                        }
280
397
                }
281
398
                
301
418
                        var parser = GetParser (mimeType);
302
419
                        if (parser == null)
303
420
                                return null;
 
421
                        var t = Counters.ParserService.FileParsed.BeginTiming (fileName);
304
422
                        try {
305
423
                                var result = parser.Parse (true, fileName, content);
306
424
                                lock (projectWrapperUpdateLock) {
307
425
                                        if (wrapper != null && (result.Flags & ParsedDocumentFlags.NonSerializable) != ParsedDocumentFlags.NonSerializable) {
308
 
                                                wrapper.UpdateContent (c => c.UpdateProjectContent (c.GetFile (fileName), result.ParsedFile));
309
 
                                                UpdateParsedDocument (wrapper, result);
 
426
                                                var oldFile = wrapper.Content.GetFile (fileName);
 
427
                                                wrapper.UpdateContent (c => c.AddOrUpdateFiles (result.ParsedFile));
 
428
                                                UpdateProjectCommentTasks (wrapper, result);
 
429
                                                if (oldFile != null)
 
430
                                                        wrapper.InformFileRemoved (new ParsedFileEventArgs (oldFile));
 
431
                                                wrapper.InformFileAdded (new ParsedFileEventArgs (result.ParsedFile));
310
432
                                        }
311
433
                                }
312
434
                                return result;
313
435
                        } catch (Exception e) {
314
436
                                LoggingService.LogError ("Exception while parsing :" + e);
315
437
                                return null;
 
438
                        } finally {
 
439
                                t.Dispose ();
316
440
                        }
317
441
                }
318
442
                
339
463
                }
340
464
                #region Parser Database Handling
341
465
 
 
466
                static string GetCacheDirectory (TargetFramework framework)
 
467
                {
 
468
                        var derivedDataPath = UserProfile.Current.CacheDir.Combine ("DerivedData");
 
469
 
 
470
                        var name = new StringBuilder ();
 
471
                        foreach (var ch in framework.Name) {
 
472
                                if (char.IsLetterOrDigit (ch)) {
 
473
                                        name.Append (ch);
 
474
                                } else {
 
475
                                        name.Append ('_');
 
476
                                }
 
477
                        }
 
478
 
 
479
                        string result = derivedDataPath.Combine (name.ToString ());
 
480
                        try {
 
481
                                if (!Directory.Exists (result))
 
482
                                        Directory.CreateDirectory (result);
 
483
                        } catch (Exception e) {
 
484
                                LoggingService.LogError ("Error while creating derived data directories.", e);
 
485
                        }
 
486
                        return result;
 
487
                }
342
488
                static string GetCacheDirectory (string filename)
343
489
                {
344
490
                        string result;
361
507
                                                if (CheckCacheDirectoryIsCorrect (filename, subDir, out result))
362
508
                                                        return result;*/
363
509
                                }
364
 
                        } catch (Exception e) {
365
 
                                LoggingService.LogError ("Error while getting derived data directories.", e);
366
 
                        }
 
510
                                } catch (Exception e) {
 
511
                                        LoggingService.LogError ("Error while getting derived data directories.", e);
 
512
                                }
367
513
                        return null;
368
514
                }
369
515
 
385
531
                                
386
532
                                        try {
387
533
                                                if (!File.Exists (dataPath)) {
388
 
                                                                cacheDirectoryCache [candidate] = CacheDirectoryInfo.Empty;
 
534
                                                        cacheDirectoryCache [candidate] = CacheDirectoryInfo.Empty;
389
535
                                                        result = null;
390
536
                                                        return false;
391
537
                                                }
448
594
                
449
595
                static T DeserializeObject<T> (string path) where T : class
450
596
                {
 
597
                        var t = Counters.ParserService.ObjectDeserialized.BeginTiming (path);
451
598
                        try {
452
599
                                using (var fs = new FileStream (path, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) {
453
600
                                        using (var reader = new BinaryReaderWith7BitEncodedInts (fs)) {
458
605
                        } catch (Exception e) {
459
606
                                LoggingService.LogError ("Error while reading type system cache.", e);
460
607
                                return default(T);
 
608
                        } finally {
 
609
                                t.Dispose ();
461
610
                        }
462
611
                }
463
612
                
465
614
                {
466
615
                        if (obj == null)
467
616
                                throw new ArgumentNullException ("obj");
 
617
 
 
618
                        var t = Counters.ParserService.ObjectSerialized.BeginTiming (path);
468
619
                        try {
469
620
                                using (var fs = new FileStream (path, FileMode.Create, FileAccess.Write)) {
470
621
                                        using (var writer = new BinaryWriterWith7BitEncodedInts (fs)) {
476
627
                                Console.WriteLine ("-----------------Serialize stack trace:");
477
628
                                Console.WriteLine (Environment.StackTrace);
478
629
                                LoggingService.LogError ("Error while writing type system cache. (object:" + obj.GetType () + ")", e);
 
630
                        } finally {
 
631
                                t.Dispose ();
479
632
                        }
480
633
                }
481
634
                
574
727
                #region Project loading
575
728
                public static void Load (WorkspaceItem item)
576
729
                {
577
 
                        InternalLoad (item);
578
 
                        CleanupCache ();
 
730
                        using (Counters.ParserService.WorkspaceItemLoaded.BeginTiming ()) {
 
731
                                InternalLoad (item);
 
732
                                CleanupCache ();
 
733
                        }
579
734
                }
580
735
                
581
736
                
590
745
                        } else if (item is Solution) {
591
746
                                var solution = (Solution)item;
592
747
                                Parallel.ForEach (solution.GetAllProjects (), project => LoadProject (project));
593
 
                                Task.Factory.StartNew (delegate {
594
 
                                        ReloadAllReferences ();
595
 
                                });
 
748
                                var contents = projectContents.Values.ToArray ();
 
749
                                ReloadAllReferences (contents);
596
750
 
597
751
                                solution.SolutionItemAdded += OnSolutionItemAdded;
598
752
                                solution.SolutionItemRemoved += OnSolutionItemRemoved;
599
 
                        }
600
 
                }
601
 
                
602
 
                static void ReloadAllReferences ()
603
 
                {
604
 
                        lock (rwLock) {
605
 
                                foreach (var wrapper in projectContents)
606
 
                                        wrapper.Value.ReloadAssemblyReferences (wrapper.Key);
607
 
                        }
 
753
                                OnSolutionLoaded (new SolutionEventArgs (solution));
 
754
                        }
 
755
                }
 
756
 
 
757
                public static event EventHandler<SolutionEventArgs> SolutionLoaded;
 
758
 
 
759
                static void OnSolutionLoaded (SolutionEventArgs e)
 
760
                {
 
761
                        var handler = SolutionLoaded;
 
762
                        if (handler != null)
 
763
                                handler (null, e);
 
764
                }
 
765
 
 
766
                static void ReloadAllReferences (IEnumerable<ProjectContentWrapper> contents)
 
767
                {
 
768
                        foreach (var wrapper in contents)
 
769
                                wrapper.ReconnectAssemblyReferences ();
608
770
                }
609
771
                
610
772
                [Serializable]
614
776
                        
615
777
                        IUnresolvedAssembly assembly {
616
778
                                get {
 
779
                                        if (wrapper.OutputAssembly != null)
 
780
                                                return wrapper.OutputAssembly;
617
781
                                        return wrapper.Compilation.MainAssembly.UnresolvedAssembly;
618
782
                                }
619
783
                        }
629
793
                                        return assembly.AssemblyName;
630
794
                                }
631
795
                        }
 
796
 
 
797
                        public string FullAssemblyName {
 
798
                                get {
 
799
                                        return assembly.FullAssemblyName;
 
800
                                }
 
801
                        }
632
802
                        
633
803
                        public string Location {
634
804
                                get {
635
805
                                        return assembly.Location;
636
806
                                }
637
 
                                set {
638
 
                                        assembly.Location = value;
639
 
                                }
640
807
                        }
641
808
 
642
809
                        public IEnumerable<IUnresolvedAttribute> AssemblyAttributes {
669
836
                [Serializable]
670
837
                public class ProjectContentWrapper
671
838
                {
672
 
                        IProjectContent content;
673
839
                        Dictionary<Type, object> extensionObjects = new Dictionary<Type, object> ();
674
840
                        
 
841
                        IProjectContent _content;
675
842
                        public IProjectContent Content {
676
843
                                get {
677
 
                                        return content;
 
844
                                        return _content;
 
845
                                }
 
846
                                set {
 
847
                                        if (value == null)
 
848
                                                throw new InvalidOperationException ("Project content can't be null");
 
849
                                        _content = value;
678
850
                                }
679
851
                        }
680
852
 
737
909
                        public void UpdateContent (Func<IProjectContent, IProjectContent> updateFunc)
738
910
                        {
739
911
                                lock (this) {
740
 
                                        if (content is LazyProjectLoader) {
741
 
                                                ((LazyProjectLoader)content).ContextTask.Wait ();
 
912
                                        if (Content is LazyProjectLoader) {
 
913
                                                ((LazyProjectLoader)Content).ContextTask.Wait ();
742
914
                                        }
743
 
                                        content = updateFunc (content);
744
 
                                        compilation = null;
 
915
                                        Content = updateFunc (Content);
 
916
                                        // Need to clear this compilation & all compilations that reference this directly or indirectly
 
917
                                        foreach (var wrapper in projectContents.Values)
 
918
                                                wrapper.compilation = null;
745
919
                                        WasChanged = true;
746
920
                                }
747
921
                        }
748
 
                        
 
922
 
 
923
                        public void InformFileRemoved (ParsedFileEventArgs e)
 
924
                        {
 
925
                                var handler = FileRemoved;
 
926
                                if (handler != null)
 
927
                                        handler (this, e);
 
928
                        }
 
929
 
 
930
                        public void InformFileAdded (ParsedFileEventArgs e)
 
931
                        {
 
932
                                var handler = FileAdded;
 
933
                                if (handler != null)
 
934
                                        handler (this, e);
 
935
                        }
 
936
 
 
937
                        public EventHandler<ParsedFileEventArgs> FileAdded;
 
938
                        public EventHandler<ParsedFileEventArgs> FileRemoved;
 
939
 
 
940
 
749
941
                        public bool WasChanged = false;
750
942
                        
751
943
                        [NonSerialized]
752
944
                        ICompilation compilation = null;
753
 
                        
 
945
 
754
946
                        public ICompilation Compilation {
755
947
                                get {
756
 
                                        if (compilation == null) {
757
 
                                                compilation = Content.CreateCompilation ();
 
948
                                        lock (this) {
 
949
                                                if (compilation == null) {
 
950
                                                        compilation = Content.CreateCompilation ();
 
951
                                                }
 
952
                                                return compilation;
758
953
                                        }
759
 
                                        return compilation;
760
954
                                }
761
955
                        }
762
956
                        
764
958
                                get;
765
959
                                private set;
766
960
                        }
 
961
 
 
962
                        bool inLoad;
 
963
                        public bool InLoad {
 
964
                                get {
 
965
                                        return inLoad;
 
966
                                }
 
967
                                set {
 
968
                                        inLoad = value;
 
969
                                        OnInLoadChanged (EventArgs.Empty);
 
970
                                }
 
971
                        }
 
972
 
 
973
                        public event EventHandler InLoadChanged;
 
974
 
 
975
                        protected virtual void OnInLoadChanged (EventArgs e)
 
976
                        {
 
977
                                var handler = InLoadChanged;
 
978
                                if (handler != null)
 
979
                                        handler (this, e);
 
980
                        }
 
981
 
 
982
                        [NonSerialized]
 
983
                        internal LazyAssemblyLoader OutputAssembly = null;
 
984
 
 
985
                        internal bool UpdateTrackedOutputAssembly (FilePath fileName)
 
986
                        {
 
987
                                if (File.Exists (fileName)) {
 
988
                                        OutputAssembly = new LazyAssemblyLoader (fileName, null);
 
989
                                        // a clean operation could remove the assembly, thefore we need to load it.
 
990
                                        OutputAssembly.EnsureAssemblyLoaded ();
 
991
                                        return true;
 
992
                                }
 
993
                                return false;
 
994
                        }
767
995
                        
768
996
                        public ProjectContentWrapper (Project project)
769
997
                        {
770
998
                                if (project == null)
771
999
                                        throw new ArgumentNullException ("project");
772
1000
                                this.Project = project;
773
 
                                this.content = new LazyProjectLoader (this).Content;
 
1001
                                this.Content = new LazyProjectLoader (this);
774
1002
                        }
775
 
                        
 
1003
 
776
1004
                        public IEnumerable<Project> ReferencedProjects {
777
1005
                                get {
778
1006
                                        foreach (var pr in Project.GetReferencedItems (ConfigurationSelector.Default)) {
786
1014
                        class LazyProjectLoader : IProjectContent
787
1015
                        {
788
1016
                                readonly ProjectContentWrapper wrapper;
789
 
                                static ConcurrentDictionary<string, IProjectContent> projectCache = new ConcurrentDictionary<string, IProjectContent> ();
790
1017
                                Task<IProjectContent> contextTask;
791
1018
 
792
1019
                                public Task<IProjectContent> ContextTask {
805
1032
                                {
806
1033
                                        this.wrapper = wrapper;
807
1034
                                        contextTask = Task.Factory.StartNew (delegate {
808
 
        
809
 
                                                if (projectCache.ContainsKey (this.wrapper.Project.FileName))
810
 
                                                        return projectCache [this.wrapper.Project.FileName];
811
 
        
812
1035
                                                var context = LoadProjectCache (this.wrapper.Project);
813
1036
                                                if (context != null) {
814
 
                                                        return context.SetAssemblyName (this.wrapper.Project.Name);
 
1037
                                                        return context.SetAssemblyName (this.wrapper.Project.Name) ?? context;
815
1038
                                                }
816
1039
 
817
 
                                                context = new CSharpProjectContent ();
818
 
                                                context.Location = wrapper.Project.FileName;
 
1040
                                                context = new MonoDevelopProjectContent (this.wrapper.Project);
 
1041
                                                wrapper.InLoad = true;
 
1042
                                                context = context.SetLocation (this.wrapper.Project.FileName);
819
1043
                                                context = context.SetAssemblyName (this.wrapper.Project.Name);
820
1044
                                                QueueParseJob (this.wrapper);
821
1045
                                                return context;
831
1055
                                        
832
1056
                                        TouchCache (cacheDir);
833
1057
                                        var cache = DeserializeObject<IProjectContent> (Path.Combine (cacheDir, "completion.cache"));
834
 
                                        if (projectCache == null) {
835
 
                                                RemoveCache (cacheDir);
836
 
                                        } else {
837
 
                                                projectCache [project.FileName] = cache;
838
 
                                        }
 
1058
                                        if (cache is MonoDevelopProjectContent)
 
1059
                                                ((MonoDevelopProjectContent)cache).Project = project;
839
1060
                                        return cache;
840
1061
                                }
841
1062
 
853
1074
                                        }
854
1075
                                }
855
1076
 
 
1077
                                string IUnresolvedAssembly.FullAssemblyName {
 
1078
                                        get {
 
1079
                                                return Content.FullAssemblyName;
 
1080
                                        }
 
1081
                                }
 
1082
 
856
1083
                                string IUnresolvedAssembly.Location {
857
1084
                                        get {
858
1085
                                                return Content.Location;
859
1086
                                        }
860
 
                                        set {
861
 
                                                Content.Location = value;
862
 
                                        }
863
1087
                                }
864
1088
 
865
1089
                                IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.AssemblyAttributes {
882
1106
                                #endregion
883
1107
 
884
1108
                                #region IProjectContent implementation
885
 
                                IParsedFile IProjectContent.GetFile (string fileName)
 
1109
 
 
1110
                                string IProjectContent.ProjectFileName { get { return Content.ProjectFileName; } }
 
1111
 
 
1112
                                IUnresolvedFile IProjectContent.GetFile (string fileName)
886
1113
                                {
887
1114
                                        return Content.GetFile (fileName);
888
1115
                                }
902
1129
                                        return Content.SetAssemblyName (newAssemblyName);
903
1130
                                }
904
1131
 
 
1132
                                IProjectContent IProjectContent.SetLocation (string newLocation)
 
1133
                                {
 
1134
                                        return Content.SetLocation (newLocation);
 
1135
                                }
 
1136
 
905
1137
                                IProjectContent IProjectContent.AddAssemblyReferences (IEnumerable<IAssemblyReference> references)
906
1138
                                {
907
1139
                                        return Content.AddAssemblyReferences (references);
908
1140
                                }
909
1141
 
 
1142
                                IProjectContent IProjectContent.AddAssemblyReferences (params IAssemblyReference[] references)
 
1143
                                {
 
1144
                                        return Content.AddAssemblyReferences (references);
 
1145
                                }
 
1146
 
910
1147
                                IProjectContent IProjectContent.RemoveAssemblyReferences (IEnumerable<IAssemblyReference> references)
911
1148
                                {
912
1149
                                        return Content.RemoveAssemblyReferences (references);
913
1150
                                }
914
1151
 
915
 
                                IProjectContent IProjectContent.UpdateProjectContent (IParsedFile oldFile, IParsedFile newFile)
 
1152
                                IProjectContent IProjectContent.RemoveAssemblyReferences (params IAssemblyReference[] references)
 
1153
                                {
 
1154
                                        return Content.RemoveAssemblyReferences (references);
 
1155
                                }
 
1156
 
 
1157
#pragma warning disable 618
 
1158
                                IProjectContent IProjectContent.UpdateProjectContent (IUnresolvedFile oldFile, IUnresolvedFile newFile)
916
1159
                                {
917
1160
                                        return Content.UpdateProjectContent (oldFile, newFile);
918
1161
                                }
919
1162
 
920
 
                                public IProjectContent UpdateProjectContent (IEnumerable<IParsedFile> oldFiles, IEnumerable<IParsedFile> newFiles)
 
1163
                                public IProjectContent UpdateProjectContent (IEnumerable<IUnresolvedFile> oldFiles, IEnumerable<IUnresolvedFile> newFiles)
921
1164
                                {
922
1165
                                        return Content.UpdateProjectContent (oldFiles, newFiles);
923
1166
                                }
924
 
 
925
 
                                IEnumerable<IParsedFile> IProjectContent.Files {
 
1167
#pragma warning restore 618
 
1168
 
 
1169
                                public IProjectContent AddOrUpdateFiles (IEnumerable<IUnresolvedFile> newFiles)
 
1170
                                {
 
1171
                                        return Content.AddOrUpdateFiles (newFiles);
 
1172
                                }
 
1173
 
 
1174
                                public IProjectContent AddOrUpdateFiles (params IUnresolvedFile[] newFiles)
 
1175
                                {
 
1176
                                        return Content.AddOrUpdateFiles (newFiles);
 
1177
                                }
 
1178
 
 
1179
                                IEnumerable<IUnresolvedFile> IProjectContent.Files {
926
1180
                                        get {
927
1181
                                                return Content.Files;
928
1182
                                        }
933
1187
                                                return Content.AssemblyReferences;
934
1188
                                        }
935
1189
                                }
 
1190
 
 
1191
                                IProjectContent IProjectContent.SetProjectFileName (string newProjectFileName)
 
1192
                                {
 
1193
                                        return Content.SetProjectFileName (newProjectFileName);
 
1194
                                }
 
1195
 
 
1196
                                IProjectContent IProjectContent.RemoveFiles (IEnumerable<string> fileNames)
 
1197
                                {
 
1198
                                        return Content.RemoveFiles (fileNames);
 
1199
                                }
 
1200
 
 
1201
                                IProjectContent IProjectContent.RemoveFiles (params string[] fileNames)
 
1202
                                {
 
1203
                                        return Content.RemoveFiles (fileNames);
 
1204
                                }
936
1205
                                #endregion
937
1206
 
 
1207
                                object compilerSettings;
 
1208
                                public IProjectContent SetCompilerSettings (object compilerSettings)
 
1209
                                {
 
1210
                                        this.compilerSettings = compilerSettings;
 
1211
                                        return this;
 
1212
                                }
 
1213
 
 
1214
                                public object CompilerSettings {
 
1215
                                        get {
 
1216
                                                return compilerSettings;
 
1217
                                        }
 
1218
                                }
938
1219
                        }
939
1220
 
940
 
                        bool HasCyclicRefs (ProjectContentWrapper wrapper)
 
1221
                        bool HasCyclicRefs (ProjectContentWrapper wrapper, HashSet<Project> nonCyclicCache)
941
1222
                        {
 
1223
                                if (nonCyclicCache.Contains (wrapper.Project))
 
1224
                                        return false;
942
1225
                                foreach (var referencedProject in wrapper.ReferencedProjects) {
943
1226
                                        ProjectContentWrapper w;
944
 
                                        if (referencedProject == Project || projectContents.TryGetValue (referencedProject, out w) && HasCyclicRefs (w)) {
 
1227
                                        if (referencedProject == Project || referencedProject == wrapper.Project || projectContents.TryGetValue (referencedProject, out w) && HasCyclicRefs (w, nonCyclicCache)) {
945
1228
                                                return true;
946
1229
                                        }
947
1230
                                }
 
1231
                                nonCyclicCache.Add (wrapper.Project);
948
1232
                                return false;
949
1233
                        }
950
1234
 
951
 
                        public void ReloadAssemblyReferences (Project project)
 
1235
                        public void ReconnectAssemblyReferences ()
952
1236
                        {
953
 
                                var netProject = project as DotNetProject;
 
1237
                                var netProject = this.Project as DotNetProject;
954
1238
                                if (netProject == null)
955
1239
                                        return;
956
1240
                                try {
957
1241
                                        var contexts = new List<IAssemblyReference> ();
 
1242
                                        var nonCyclicCache =new HashSet<Project> ();
958
1243
                                        foreach (var referencedProject in ReferencedProjects) {
959
1244
                                                ProjectContentWrapper wrapper;
960
1245
                                                if (projectContents.TryGetValue (referencedProject, out wrapper)) {
961
 
                                                        if (HasCyclicRefs (wrapper))
 
1246
                                                        if (HasCyclicRefs (wrapper, nonCyclicCache))
962
1247
                                                                continue;
963
1248
                                                        contexts.Add (new UnresolvedAssemblyDecorator (wrapper));
964
1249
                                                }
988
1273
                                                        fileName = Path.GetFullPath (file);
989
1274
                                                }
990
1275
                                                ctx = LoadAssemblyContext (fileName);
991
 
                                                if (ctx != null)
 
1276
                                                if (ctx != null) {
992
1277
                                                        contexts.Add (ctx);
 
1278
                                                } else {
 
1279
                                                        LoggingService.LogWarning ("TypeSystemService: Can't load assembly context for:" + file);
 
1280
                                                }
993
1281
                                        }
994
1282
                                        bool changed = WasChanged;
995
1283
                                        UpdateContent (c => c.RemoveAssemblyReferences (Content.AssemblyReferences));
1005
1293
                                }
1006
1294
                        }
1007
1295
                }
1008
 
                
 
1296
                static object projectContentLock = new object ();
1009
1297
                static Dictionary<Project, ProjectContentWrapper> projectContents = new Dictionary<Project, ProjectContentWrapper> ();
1010
 
                static Dictionary<Project, int> referenceCounter = new Dictionary<Project, int> ();
1011
1298
 
1012
1299
                public static ProjectContentWrapper LoadProject (Project project)
1013
1300
                {
1014
1301
                        if (IncLoadCount (project) != 1) 
1015
1302
                                return null;
1016
 
                        lock (rwLock) {
 
1303
                        lock (projectContentLock) {
1017
1304
                                if (projectContents.ContainsKey (project))
1018
1305
                                        return null;
1019
1306
                                try {
 
1307
                                        Counters.ParserService.ProjectsLoaded++;
1020
1308
                                        ProjectContentWrapper wrapper;
1021
1309
                                        projectContents [project] = wrapper = new ProjectContentWrapper (project);
1022
 
                                        referenceCounter [project] = 1;
1023
 
                                        OnProjectContentLoaded (new ProjectContentEventArgs (project, wrapper.Content));
 
1310
                                        var dotNetProject = project as DotNetProject;
 
1311
                                        if (dotNetProject != null)
 
1312
                                                CheckProjectOutput (dotNetProject, false);
 
1313
 
1024
1314
                                        project.FileAddedToProject += OnFileAdded;
1025
1315
                                        project.FileRemovedFromProject += OnFileRemoved;
1026
1316
                                        project.FileRenamedInProject += OnFileRenamed;
1027
1317
                                        project.Modified += OnProjectModified;
 
1318
                                        var files = project.Files.ToArray ();
1028
1319
                                        Task.Factory.StartNew (delegate {
1029
 
                                                CheckModifiedFiles (project, wrapper);
 
1320
                                                CheckModifiedFiles (project, files, wrapper);
1030
1321
                                        });
1031
1322
 
 
1323
                                        if (dotNetProject != null) {
 
1324
                                                Task.Factory.StartNew (delegate {
 
1325
                                                        GetFrameworkLookup (dotNetProject);
 
1326
                                                });
 
1327
                                        }
 
1328
 
 
1329
                                        OnProjectContentLoaded (new ProjectContentEventArgs (project, wrapper.Content));
1032
1330
                                        return wrapper;
1033
1331
                                } catch (Exception ex) {
1034
1332
                                        LoggingService.LogError ("Parser database for project '" + project.Name + " could not be loaded", ex);
1067
1365
                        foreach (ProjectFileEventInfo fargs in args) {
1068
1366
                                var wrapper = projectContents [project];
1069
1367
                                var fileName = fargs.ProjectFile.Name;
1070
 
                                wrapper.UpdateContent (c => c.UpdateProjectContent (c.GetFile (fileName), null));
 
1368
                                var file = wrapper.Content.GetFile (fileName);
 
1369
                                if (file == null)
 
1370
                                        continue;
 
1371
                                wrapper.UpdateContent (c => c.RemoveFiles (fileName));
 
1372
                                wrapper.InformFileRemoved (new ParsedFileEventArgs (file));
 
1373
 
1071
1374
                                var tags = wrapper.GetExtensionObject <ProjectCommentTags> ();
1072
1375
                                if (tags != null)
1073
1376
                                        tags.RemoveFile (wrapper.Project, fileName);
1078
1381
                {
1079
1382
                        var project = (Project)sender;
1080
1383
                        foreach (ProjectFileRenamedEventInfo fargs in args) {
1081
 
                                projectContents [project].UpdateContent (c => c.UpdateProjectContent (c.GetFile (fargs.OldName), null));
1082
 
                                QueueParseJob (projectContents [project], new [] { fargs.ProjectFile });
 
1384
                                var content = projectContents [project];
 
1385
                                var file = content.Content.GetFile (fargs.OldName);
 
1386
                                if (file == null)
 
1387
                                        continue;
 
1388
                                content.UpdateContent (c => c.RemoveFiles (fargs.OldName));
 
1389
                                content.InformFileRemoved (new ParsedFileEventArgs (file));
 
1390
 
 
1391
                                QueueParseJob (content, new [] { fargs.ProjectFile });
1083
1392
                        }
1084
1393
                }
1085
1394
                
1087
1396
                {
1088
1397
                        if (!args.Any (x => x is SolutionItemModifiedEventInfo && (((SolutionItemModifiedEventInfo)x).Hint == "TargetFramework" || ((SolutionItemModifiedEventInfo)x).Hint == "References")))
1089
1398
                                return;
1090
 
                        cachedProjectContents = new Dictionary<Project, ITypeResolveContext> ();
1091
1399
                        var project = (Project)sender;
1092
1400
                        
1093
1401
                        ProjectContentWrapper wrapper;
1094
1402
                        projectContents.TryGetValue (project, out wrapper);
1095
1403
                        if (wrapper == null)
1096
1404
                                return;
1097
 
                        ReloadAllReferences ();
 
1405
                        ReloadAllReferences (projectContents.Values.ToArray ());
1098
1406
                }
1099
1407
                #endregion
1100
1408
                
1125
1433
                
1126
1434
                public static void UnloadProject (Project project)
1127
1435
                {
1128
 
                        if (DecLoadCount (project) != 0)
1129
 
                                return;
1130
 
                        if (referenceCounter.ContainsKey (project) && --referenceCounter [project] <= 0) {
 
1436
                        lock (projectWrapperUpdateLock) {
 
1437
                                if (DecLoadCount (project) != 0)
 
1438
                                        return;
 
1439
                                Counters.ParserService.ProjectsLoaded--;
1131
1440
                                project.FileAddedToProject -= OnFileAdded;
1132
1441
                                project.FileRemovedFromProject -= OnFileRemoved;
1133
1442
                                project.FileRenamedInProject -= OnFileRenamed;
1135
1444
                                
1136
1445
                                var wrapper = projectContents [project];
1137
1446
                                projectContents.Remove (project);
1138
 
                                referenceCounter.Remove (project);
 
1447
 
1139
1448
                                StoreProjectCache (project, wrapper);
1140
 
                                
1141
1449
                                OnProjectUnloaded (new ProjectUnloadEventArgs (project, wrapper));
1142
1450
                        }
1143
1451
                }
1166
1474
                        if (args.SolutionItem is Project) {
1167
1475
                                var wrapper = LoadProject ((Project)args.SolutionItem);
1168
1476
                                if (wrapper != null)
1169
 
                                        wrapper.ReloadAssemblyReferences (wrapper.Project);
 
1477
                                        wrapper.ReconnectAssemblyReferences ();
1170
1478
                        }
1171
1479
                }
1172
1480
                
1179
1487
                #endregion
1180
1488
 
1181
1489
                #region Reference Counting
1182
 
                static Dictionary<object,int> loadCount = new Dictionary<object,int> ();
 
1490
                static Dictionary<Project,int> loadCount = new Dictionary<Project,int> ();
1183
1491
                static object rwLock = new object ();
1184
 
                
1185
 
                static int DecLoadCount (object ob)
 
1492
 
 
1493
                static int DecLoadCount (Project ob)
1186
1494
                {
1187
1495
                        lock (rwLock) {
1188
1496
                                int c;
1199
1507
                        }
1200
1508
                }
1201
1509
                
1202
 
                static int IncLoadCount (object ob)
 
1510
                static int IncLoadCount (Project ob)
1203
1511
                {
1204
1512
                        lock (rwLock) {
1205
1513
                                int c;
1234
1542
                                        return result;
1235
1543
                                
1236
1544
                                var name = AssemblyNameReference.Parse (fullName);
 
1545
                                AssemblyDefinition bestFit = null;
1237
1546
                                // need to handle different file extension casings. Some dlls from windows tend to end with .Dll or .DLL rather than '.dll'
1238
1547
                                foreach (string file in Directory.GetFiles (lookupPath, name.Name + ".*")) {
1239
1548
                                        string ext = Path.GetExtension (file);
1242
1551
                                        ext = ext.ToUpper ();
1243
1552
                                        if (ext == ".DLL" || ext == ".EXE") {
1244
1553
                                                result = ReadAssembly (file);
 
1554
                                                if (result.FullName != fullName) {
 
1555
                                                        bestFit = result;
 
1556
                                                        result = null;
 
1557
                                                        continue;
 
1558
                                                }
1245
1559
                                                break;
1246
1560
                                        }
1247
1561
                                }
1255
1569
                                                result = ReadAssembly (location);
1256
1570
                                        }
1257
1571
                                }
 
1572
                                if (result == null)
 
1573
                                        result = bestFit;
1258
1574
                                if (result != null)
1259
1575
                                        cache [fullName] = result;
1260
1576
                                return result;
1289
1605
                                throw new ArgumentNullException ("fileName");
1290
1606
                        ReaderParameters parameters = new ReaderParameters ();
1291
1607
                        parameters.AssemblyResolver = new DefaultAssemblyResolver (); // new SimpleAssemblyResolver (Path.GetDirectoryName (fileName));
1292
 
                        using (var stream = new MemoryStream (File.ReadAllBytes (fileName))) {
1293
 
                                return AssemblyDefinition.ReadAssembly (stream, parameters);
1294
 
                        }
 
1608
                        return AssemblyDefinition.ReadAssembly (fileName, parameters);
1295
1609
                }
1296
1610
                
1297
1611
                static bool GetXml (string baseName, MonoDevelop.Core.Assemblies.TargetRuntime runtime, out FilePath xmlFileName)
1378
1692
                        
1379
1693
                        public IUnresolvedAssembly Ctx {
1380
1694
                                get {
1381
 
                                        return CtxLoader.Assembly;
 
1695
                                        return CtxLoader;
1382
1696
                                }
1383
1697
                        }
1384
1698
 
1389
1703
                                }
1390
1704
                        }
1391
1705
 
 
1706
                        string IUnresolvedAssembly.FullAssemblyName {
 
1707
                                get {
 
1708
                                        return Ctx.FullAssemblyName;
 
1709
                                }
 
1710
                        }
 
1711
 
1392
1712
                        string IUnresolvedAssembly.Location {
1393
1713
                                get {
1394
1714
                                        return Ctx.Location;
1395
1715
                                }
1396
 
                                set {
1397
 
                                        Ctx.Location = value;
1398
 
                                }
1399
1716
                        }
1400
1717
 
1401
1718
                        IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.AssemblyAttributes {
1425
1742
                        #endregion
1426
1743
                }
1427
1744
                
1428
 
                class LazyAssemblyLoader
 
1745
                internal class LazyAssemblyLoader : IUnresolvedAssembly
1429
1746
                {
 
1747
                        class LazyAssembly : IAssembly
 
1748
                        {
 
1749
                                readonly LazyAssemblyLoader loader;
 
1750
                                readonly ITypeResolveContext context;
 
1751
 
 
1752
                                IAssembly assembly;
 
1753
                                IAssembly Assembly {
 
1754
                                        get {
 
1755
                                                lock (loader) {
 
1756
                                                        if (assembly == null) {
 
1757
                                                                loader.EnsureAssemblyLoaded ();
 
1758
                                                                assembly = loader.assembly.Resolve (context);
 
1759
                                                        }
 
1760
                                                        return assembly;
 
1761
                                                }
 
1762
                                        }
 
1763
                                }
 
1764
 
 
1765
                                public LazyAssembly (LazyAssemblyLoader loader, ITypeResolveContext context)
 
1766
                                {
 
1767
                                        this.loader = loader;
 
1768
                                        this.context = context;
 
1769
                                }
 
1770
 
 
1771
 
 
1772
                                #region IAssembly implementation                                
 
1773
                                bool IAssembly.InternalsVisibleTo (IAssembly assembly)
 
1774
                                {
 
1775
                                        return Assembly.InternalsVisibleTo (assembly);
 
1776
                                }                               
 
1777
 
 
1778
                                ITypeDefinition IAssembly.GetTypeDefinition (TopLevelTypeName typeName)
 
1779
                                {
 
1780
                                        return Assembly.GetTypeDefinition (typeName);
 
1781
                                }                               
 
1782
 
 
1783
                                IUnresolvedAssembly IAssembly.UnresolvedAssembly {
 
1784
                                        get {
 
1785
                                                return Assembly.UnresolvedAssembly;
 
1786
                                        }
 
1787
                                }                               
 
1788
 
 
1789
                                bool IAssembly.IsMainAssembly {
 
1790
                                        get {
 
1791
                                                return Assembly.IsMainAssembly;
 
1792
                                        }
 
1793
                                }                               
 
1794
 
 
1795
                                string IAssembly.AssemblyName {
 
1796
                                        get {
 
1797
                                                return Assembly.AssemblyName;
 
1798
                                        }
 
1799
                                }
 
1800
 
 
1801
                                string IAssembly.FullAssemblyName {
 
1802
                                        get {
 
1803
                                                return Assembly.FullAssemblyName;
 
1804
                                        }
 
1805
                                }
 
1806
 
 
1807
                                IList<IAttribute> IAssembly.AssemblyAttributes {
 
1808
                                        get {
 
1809
                                                return Assembly.AssemblyAttributes;
 
1810
                                        }
 
1811
                                }                               
 
1812
 
 
1813
                                IList<IAttribute> IAssembly.ModuleAttributes {
 
1814
                                        get {
 
1815
                                                return Assembly.ModuleAttributes;
 
1816
                                        }
 
1817
                                }                               
 
1818
 
 
1819
                                INamespace IAssembly.RootNamespace {
 
1820
                                        get {
 
1821
                                                return Assembly.RootNamespace;
 
1822
                                        }
 
1823
                                }                               
 
1824
 
 
1825
                                IEnumerable<ITypeDefinition> IAssembly.TopLevelTypeDefinitions {
 
1826
                                        get {
 
1827
                                                return Assembly.TopLevelTypeDefinitions;
 
1828
                                        }
 
1829
                                }                               
 
1830
 
 
1831
                                #endregion
 
1832
                        
 
1833
                                #region ICompilationProvider implementation
 
1834
                                ICompilation ICompilationProvider.Compilation {
 
1835
                                        get {
 
1836
                                                return Assembly.Compilation;
 
1837
                                        }
 
1838
                                }
 
1839
                                #endregion
 
1840
                        }
 
1841
 
 
1842
                        #region IAssemblyReference implementation
 
1843
 
 
1844
                        IAssembly IAssemblyReference.Resolve (ITypeResolveContext context)
 
1845
                        {
 
1846
                                if (assembly != null)
 
1847
                                        return assembly.Resolve (context);
 
1848
                                return new LazyAssembly (this, context);
 
1849
                        }
 
1850
 
 
1851
                        #endregion
 
1852
 
 
1853
                        #region IUnresolvedAssembly implementation
 
1854
 
 
1855
                        string IUnresolvedAssembly.AssemblyName {
 
1856
                                get {
 
1857
                                        lock (this) {
 
1858
                                                EnsureAssemblyLoaded ();
 
1859
                                                return assembly.AssemblyName;
 
1860
                                        }
 
1861
                                }
 
1862
                        }
 
1863
 
 
1864
                        string IUnresolvedAssembly.FullAssemblyName {
 
1865
                                get {
 
1866
                                        lock (this) {
 
1867
                                                EnsureAssemblyLoaded ();
 
1868
                                                return assembly.FullAssemblyName;
 
1869
                                        }
 
1870
                                }
 
1871
                        }
 
1872
 
 
1873
                        string IUnresolvedAssembly.Location {
 
1874
                                get {
 
1875
                                        lock (this) {
 
1876
                                                EnsureAssemblyLoaded ();
 
1877
                                                return assembly.Location;
 
1878
                                        }
 
1879
                                }
 
1880
                        }
 
1881
 
 
1882
                        IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.AssemblyAttributes {
 
1883
                                get {
 
1884
                                        lock (this) {
 
1885
                                                EnsureAssemblyLoaded ();
 
1886
                                                return assembly.AssemblyAttributes;
 
1887
                                        }
 
1888
                                }
 
1889
                        }
 
1890
 
 
1891
                        IEnumerable<IUnresolvedAttribute> IUnresolvedAssembly.ModuleAttributes {
 
1892
                                get {
 
1893
                                        lock (this) {
 
1894
                                                EnsureAssemblyLoaded ();
 
1895
                                                return assembly.ModuleAttributes;
 
1896
                                        }
 
1897
                                }
 
1898
                        }
 
1899
 
 
1900
                        IEnumerable<IUnresolvedTypeDefinition> IUnresolvedAssembly.TopLevelTypeDefinitions {
 
1901
                                get {
 
1902
                                        lock (this) {
 
1903
                                                EnsureAssemblyLoaded ();
 
1904
                                                return assembly.TopLevelTypeDefinitions;
 
1905
                                        }
 
1906
                                }
 
1907
                        }
 
1908
 
 
1909
                        #endregion
 
1910
 
1430
1911
                        string fileName;
1431
1912
                        string cache;
1432
1913
                        
1433
1914
                        IUnresolvedAssembly assembly;
1434
1915
 
1435
 
                        void EnsureAssemblyLoaded ()
 
1916
                        internal void EnsureAssemblyLoaded ()
1436
1917
                        {
1437
 
                                lock (this) {
1438
 
                                        if (assembly != null)
1439
 
                                                return;
1440
 
                                        assembly = LoadAssembly () ?? new DefaultUnresolvedAssembly (fileName);
1441
 
                                }
 
1918
                                if (assembly != null)
 
1919
                                        return;
 
1920
                                assembly = LoadAssembly () ?? new DefaultUnresolvedAssembly (fileName);
1442
1921
                        }
1443
1922
 
1444
 
                        public IUnresolvedAssembly Assembly {
1445
 
                                get {
1446
 
                                        lock (this) {
1447
 
                                                EnsureAssemblyLoaded ();
1448
 
                                                return assembly;
1449
 
                                        }
1450
 
                                }
1451
 
                        }
1452
 
                        
1453
1923
                        public LazyAssemblyLoader (string fileName, string cache)
1454
1924
                        {
1455
1925
                                this.fileName = fileName;
1458
1928
                        
1459
1929
                        IUnresolvedAssembly LoadAssembly ()
1460
1930
                        {
1461
 
                                var assemblyPath = Path.Combine (cache, "assembly.data");
 
1931
                                var assemblyPath = cache != null ? Path.Combine (cache, "assembly.data") : null;
1462
1932
                                try {
1463
 
                                        if (File.Exists (assemblyPath)) {
 
1933
                                        if (assemblyPath != null && File.Exists (assemblyPath)) {
1464
1934
                                                var deserializedAssembly = DeserializeObject <IUnresolvedAssembly> (assemblyPath);
1465
1935
                                                if (deserializedAssembly != null) {
1466
 
                                                        var provider = deserializedAssembly as IDocumentationProviderContainer;
 
1936
                                                /*      var provider = deserializedAssembly as IDocumentationProviderContainer;
1467
1937
                                                        if (provider != null)
1468
 
                                                                provider.DocumentationProvider = new CombinedDocumentationProvider (fileName);
 
1938
                                                                provider.DocumentationProvider = new CombinedDocumentationProvider (fileName);*/
1469
1939
                                                        return deserializedAssembly;
1470
1940
                                                }
1471
1941
                                        }
1481
1951
                                        loader.IncludeInternalMembers = true;
1482
1952
                                        loader.DocumentationProvider = new CombinedDocumentationProvider (fileName);
1483
1953
                                        assembly = loader.LoadAssembly (asm);
1484
 
                                        assembly.Location = fileName;
1485
1954
                                } catch (Exception e) {
1486
1955
                                        LoggingService.LogError ("Can't convert assembly: " + fileName, e);
1487
1956
                                        return null;
1532
2001
                        }
1533
2002
                        #endregion
1534
2003
                }
1535
 
                
 
2004
                static object assemblyContextLock = new object ();
1536
2005
                static AssemblyContext LoadAssemblyContext (string fileName)
1537
2006
                {
1538
2007
                        AssemblyContext loadedContext;
1539
 
                        if (cachedAssemblyContents.TryGetValue (fileName, out loadedContext))
 
2008
                        if (cachedAssemblyContents.TryGetValue (fileName, out loadedContext)) {
 
2009
                                CheckModifiedFile (loadedContext);
1540
2010
                                return loadedContext;
 
2011
                        }
1541
2012
                        if (!File.Exists (fileName))
1542
2013
                                return null;
1543
 
                        string cache = GetCacheDirectory (fileName);
1544
 
                        if (cache != null) {
1545
 
                                TouchCache (cache);
1546
 
                                var deserialized = DeserializeObject <AssemblyContext> (Path.Combine (cache, "assembly.descriptor"));
1547
 
                                if (deserialized != null) {
1548
 
                                        deserialized.CtxLoader = new LazyAssemblyLoader (fileName, cache);
1549
 
                                        cachedAssemblyContents [fileName] = deserialized;
1550
 
                                        return deserialized;
1551
 
                                } else {
1552
 
                                        RemoveCache (cache);
1553
 
                                }
1554
 
                        }
1555
 
                        cache = CreateCacheDirectory (fileName);
1556
 
 
1557
 
                        try {
1558
 
                                var result = new AssemblyContext () {
1559
 
                                        FileName = fileName,
1560
 
                                        LastWriteTimeUtc = File.GetLastWriteTimeUtc (fileName)
1561
 
                                };
1562
 
                                SerializeObject (Path.Combine (cache, "assembly.descriptor"), result);
1563
 
                                
1564
 
                                result.CtxLoader = new LazyAssemblyLoader (fileName, cache);
1565
 
                                cachedAssemblyContents [fileName] = result;
1566
 
                                return result;
1567
 
                        } catch (Exception ex) {
1568
 
                                LoggingService.LogError ("Error loading assembly " + fileName, ex);
1569
 
                                return null;
1570
 
                        }
 
2014
                        lock (assemblyContextLock) {
 
2015
                                if (cachedAssemblyContents.TryGetValue (fileName, out loadedContext)) {
 
2016
                                        CheckModifiedFile (loadedContext);
 
2017
                                        return loadedContext;
 
2018
                                }
 
2019
 
 
2020
                                string cache = GetCacheDirectory (fileName);
 
2021
                                if (cache != null) {
 
2022
                                        TouchCache (cache);
 
2023
                                        var deserialized = DeserializeObject <AssemblyContext> (Path.Combine (cache, "assembly.descriptor"));
 
2024
                                        if (deserialized != null) {
 
2025
                                                deserialized.CtxLoader = new LazyAssemblyLoader (fileName, cache);
 
2026
                                                CheckModifiedFile (deserialized);
 
2027
                                                var newcachedAssemblyContents = new Dictionary<string, AssemblyContext> (cachedAssemblyContents);
 
2028
                                                newcachedAssemblyContents [fileName] = deserialized;
 
2029
                                                cachedAssemblyContents = newcachedAssemblyContents;
 
2030
                                                OnAssemblyLoaded (new AssemblyLoadedEventArgs (deserialized.CtxLoader));
 
2031
                                                return deserialized;
 
2032
                                        } else {
 
2033
                                                RemoveCache (cache);
 
2034
                                        }
 
2035
                                }
 
2036
                                cache = CreateCacheDirectory (fileName);
 
2037
 
 
2038
                                try {
 
2039
                                        var result = new AssemblyContext () {
 
2040
                                                FileName = fileName,
 
2041
                                                LastWriteTimeUtc = File.GetLastWriteTimeUtc (fileName)
 
2042
                                        };
 
2043
                                        SerializeObject (Path.Combine (cache, "assembly.descriptor"), result);
 
2044
                                        
 
2045
                                        result.CtxLoader = new LazyAssemblyLoader (fileName, cache);
 
2046
                                        var newcachedAssemblyContents = new Dictionary<string, AssemblyContext> (cachedAssemblyContents);
 
2047
                                        newcachedAssemblyContents [fileName] = result;
 
2048
                                        cachedAssemblyContents = newcachedAssemblyContents;
 
2049
                                        OnAssemblyLoaded (new AssemblyLoadedEventArgs (result.CtxLoader));
 
2050
                                        return result;
 
2051
                                } catch (Exception ex) {
 
2052
                                        LoggingService.LogError ("Error loading assembly " + fileName, ex);
 
2053
                                        return null;
 
2054
                                }
 
2055
                        }
 
2056
                }
 
2057
 
 
2058
 
 
2059
                internal static event EventHandler<AssemblyLoadedEventArgs> AssemblyLoaded;
 
2060
 
 
2061
                static  void OnAssemblyLoaded (AssemblyLoadedEventArgs e)
 
2062
                {
 
2063
                        var handler = AssemblyLoaded;
 
2064
                        if (handler != null)
 
2065
                                handler (null, e);
1571
2066
                }
1572
2067
 
1573
2068
                public static IUnresolvedAssembly LoadAssemblyContext (MonoDevelop.Core.Assemblies.TargetRuntime runtime, MonoDevelop.Core.Assemblies.TargetFramework fx, string fileName)
1595
2090
                        var content = GetProjectContentWrapper (project);
1596
2091
                        return content.Compilation;
1597
2092
                }
1598
 
                
 
2093
 
 
2094
                public static ICompilation GetCompilation (SystemAssembly assembly, ICompilation compilation)
 
2095
                {
 
2096
                        var ctx = LoadAssemblyContext (assembly.Location);
 
2097
                        var list = compilation.ReferencedAssemblies.Select (r => r.UnresolvedAssembly).ToList ();
 
2098
                        list.Add (compilation.MainAssembly.UnresolvedAssembly);
 
2099
                        var     result = new SimpleCompilation (ctx, list);
 
2100
                        return result;
 
2101
                }
 
2102
 
 
2103
                public static readonly Version FrameworkLookupVersion = new Version (1, 0, 0);
 
2104
 
 
2105
                [Serializable]
 
2106
                public class FrameworkLookup 
 
2107
                {
 
2108
                        public Version Version {
 
2109
                                get;
 
2110
                                set;
 
2111
                        }
 
2112
 
 
2113
                        Dictionary<string, List<AssemblyLookup>> typeLookup = new Dictionary<string, List<AssemblyLookup>>  ();
 
2114
                        Dictionary<string, List<AssemblyLookup>> extensionMethodLookup = new Dictionary<string, List<AssemblyLookup>>  ();
 
2115
 
 
2116
                        public int ItemCount {
 
2117
                                get {
 
2118
                                        return typeLookup.Count + extensionMethodLookup.Count;
 
2119
                                }
 
2120
                        }
 
2121
 
 
2122
                        public FrameworkLookup ()
 
2123
                        {
 
2124
                                this.Version = FrameworkLookupVersion;
 
2125
                        }
 
2126
 
 
2127
                        void AddExtensionMethodlookup(IUnresolvedMethod method, SystemAssembly assembly)
 
2128
                        {
 
2129
                                List<AssemblyLookup> list;
 
2130
                                if (!extensionMethodLookup.TryGetValue (method.Name, out list)) {
 
2131
                                        list = new List<AssemblyLookup> ();
 
2132
                                        extensionMethodLookup [method.Name] = list;
 
2133
                                }
 
2134
                                var assemblyLookup = new AssemblyLookup (assembly, method.DeclaringTypeDefinition.Namespace);
 
2135
                                if (!list.Any (a => a.Equals (assemblyLookup))) {
 
2136
                                        list.Add (assemblyLookup);
 
2137
                                }
 
2138
 
 
2139
                        }
 
2140
 
 
2141
                        public IEnumerable<AssemblyLookup> LookupExtensionMethod (string identifier)
 
2142
                        {
 
2143
                                List<AssemblyLookup> list;
 
2144
                                if (!extensionMethodLookup.TryGetValue (identifier, out list)) 
 
2145
                                        return Enumerable.Empty<AssemblyLookup> ();
 
2146
                                return list;
 
2147
                        }
 
2148
 
 
2149
                        public void AddLookup (IUnresolvedTypeDefinition type, SystemAssembly assembly)
 
2150
                        {
 
2151
                                List<AssemblyLookup> list;
 
2152
                                var id = GetIdentifier (type.Name, type.TypeParameters.Count);
 
2153
                                if (!typeLookup.TryGetValue (id, out list)) {
 
2154
                                        list = new List<AssemblyLookup> ();
 
2155
                                        typeLookup [id] = list;
 
2156
                                }
 
2157
                                var assemblyLookup = new AssemblyLookup (assembly, type.Namespace);
 
2158
                                if (!list.Any (a => a.Equals (assemblyLookup))) {
 
2159
                                        list.Add (assemblyLookup);
 
2160
 
 
2161
                                        if (type.IsSealed || type.IsStatic) {
 
2162
                                                foreach (var method in type.Methods) {
 
2163
                                                        var m = method as DefaultUnresolvedMethod;
 
2164
                                                        if (m == null || !m.IsExtensionMethod)
 
2165
                                                                continue;
 
2166
                                                        AddExtensionMethodlookup (method, assembly);
 
2167
                                                }
 
2168
                                        }
 
2169
                                }
 
2170
                        }
 
2171
 
 
2172
                        static string GetIdentifier (string identifier, int tc)
 
2173
                        {
 
2174
                                if (tc == 0)
 
2175
                                        return identifier;
 
2176
                                return identifier + "`" + tc;
 
2177
                        }
 
2178
 
 
2179
                        public IEnumerable<AssemblyLookup> LookupIdentifier (string name, int typeParameterCount)
 
2180
                        {
 
2181
                                var identifier = GetIdentifier (name, typeParameterCount);
 
2182
                                List<AssemblyLookup> list;
 
2183
                                if (!typeLookup.TryGetValue (identifier, out list)) 
 
2184
                                        return Enumerable.Empty<AssemblyLookup> ();
 
2185
                                return list;
 
2186
                        }
 
2187
 
 
2188
                        [Serializable]
 
2189
                        public class AssemblyLookup
 
2190
                        {
 
2191
                                public string Namespace { get; set; }
 
2192
                                public string FullName { get; set; }
 
2193
                                public string Package { get; set; }
 
2194
                        
 
2195
                                public AssemblyLookup (SystemAssembly assembly, string ns)
 
2196
                                {
 
2197
                                        FullName = assembly.FullName;
 
2198
                                        Package = assembly.Package.Name;
 
2199
                                        Namespace = ns;
 
2200
                                }
 
2201
 
 
2202
                                public override string ToString ()
 
2203
                                {
 
2204
                                        return string.Format ("[AssemblyLookup: Namespace={0}, FullName={1}, Package={2}]", Namespace, FullName, Package);
 
2205
                                }
 
2206
 
 
2207
                                public override bool Equals (object obj)
 
2208
                                {
 
2209
                                        if (obj == null)
 
2210
                                                return false;
 
2211
                                        if (ReferenceEquals (this, obj))
 
2212
                                                return true;
 
2213
                                        if (obj.GetType () != typeof(AssemblyLookup))
 
2214
                                                return false;
 
2215
                                        AssemblyLookup other = (AssemblyLookup)obj;
 
2216
                                        return Namespace == other.Namespace && FullName == other.FullName && Package == other.Package;
 
2217
                                }
 
2218
                                
 
2219
                                public override int GetHashCode ()
 
2220
                                {
 
2221
                                        unchecked {
 
2222
                                                return (Namespace != null ? Namespace.GetHashCode () : 0) ^ (FullName != null ? FullName.GetHashCode () : 0) ^ (Package != null ? Package.GetHashCode () : 0);
 
2223
                                        }
 
2224
                                }
 
2225
                        }
 
2226
                }
 
2227
 
 
2228
                static IEnumerable<SystemAssembly> GetFrameworkAssemblies (DotNetProject netProject)
 
2229
                {
 
2230
                        var assemblies = new Dictionary<string, SystemAssembly> ();
 
2231
                        foreach (var systemPackage in netProject.AssemblyContext.GetPackages ()) {
 
2232
                                foreach (var assembly in systemPackage.Assemblies) {
 
2233
                                        SystemAssembly existing;
 
2234
                                        if (assemblies.TryGetValue (assembly.Name, out existing)) {
 
2235
                                                Version v1, v2;
 
2236
                                                if (!Version.TryParse (existing.Version, out v1))
 
2237
                                                        continue;
 
2238
                                                if (!Version.TryParse (assembly.Version, out v2))
 
2239
                                                        continue;
 
2240
                                                if (v1 > v2)
 
2241
                                                        continue;
 
2242
                                        }
 
2243
                                        assemblies [assembly.Name] = assembly;
 
2244
                                }
 
2245
                        }
 
2246
                        return assemblies.Values;
 
2247
                }
 
2248
 
 
2249
                readonly static Dictionary<string, FrameworkLookup> frameworkLookup = new Dictionary<string, FrameworkLookup> ();
 
2250
                public static FrameworkLookup GetFrameworkLookup (DotNetProject netProject)
 
2251
                {
 
2252
                        FrameworkLookup result;
 
2253
                        string fileName;
 
2254
                        lock (frameworkLookup) {
 
2255
                                if (frameworkLookup.TryGetValue (netProject.TargetFramework.Name, out result)) 
 
2256
                                        return result;
 
2257
                                var cache = GetCacheDirectory (netProject.TargetFramework);
 
2258
                                fileName = Path.Combine (cache, "FrameworkLookup_" + FrameworkLookupVersion + ".dat");
 
2259
                                try {
 
2260
                                        if (File.Exists (fileName)) {
 
2261
                                                result = DeserializeObject<FrameworkLookup> (fileName);
 
2262
                                                if (result.ItemCount > 0) {
 
2263
                                                        frameworkLookup [netProject.TargetFramework.Name] = result;
 
2264
                                                        if (result.Version == FrameworkLookupVersion)
 
2265
                                                                return result;
 
2266
                                                }
 
2267
                                        }
 
2268
                                } catch (Exception e) {
 
2269
                                        LoggingService.LogWarning ("Can't read framework cache - recreating...", e);
 
2270
                                }
 
2271
                                result = new FrameworkLookup ();
 
2272
                                frameworkLookup [netProject.TargetFramework.Name] = result;
 
2273
                                foreach (var assembly in GetFrameworkAssemblies (netProject)) {
 
2274
                                        var ctx = LoadAssemblyContext (assembly.Location);
 
2275
                                        foreach (var type in ctx.Ctx.GetAllTypeDefinitions ()) {
 
2276
                                                if (!type.IsPublic)
 
2277
                                                        continue;
 
2278
                                                result.AddLookup (type, assembly);
 
2279
                                        }
 
2280
                                }
 
2281
                                SerializeObject (fileName, result);
 
2282
                                return result;
 
2283
                        }
 
2284
                }
 
2285
 
1599
2286
                public static ProjectContentWrapper GetProjectContentWrapper (Project project)
1600
2287
                {
1601
2288
                        if (project == null)
1602
2289
                                throw new ArgumentNullException ("project");
1603
2290
                        ProjectContentWrapper content;
1604
2291
                        if (projectContents.TryGetValue (project, out content)) {
1605
 
                                if (content.Content != null)
1606
 
                                        content.Content.Location = project.FileName;
1607
2292
                                return content;
1608
2293
                        }
1609
2294
                        return new ProjectContentWrapper (project);
1615
2300
                                var parsedDocument = ParseFile (file, mimeType, reader);
1616
2301
                                
1617
2302
                                var content = new ICSharpCode.NRefactory.CSharp.CSharpProjectContent ();
1618
 
                                return content.UpdateProjectContent (null, parsedDocument.ParsedFile);
 
2303
                                return content.AddOrUpdateFiles (parsedDocument.ParsedFile);
1619
2304
                        }
1620
2305
                }
1621
2306
                
1622
 
                static Dictionary<Project, ITypeResolveContext> cachedProjectContents = new Dictionary<Project, ITypeResolveContext> ();
1623
2307
                static Dictionary<string, AssemblyContext> cachedAssemblyContents = new Dictionary<string, AssemblyContext> ();
1624
2308
                
1625
2309
                public static void ForceUpdate (ProjectContentWrapper context)
1671
2355
                        public void Run (IProgressMonitor monitor)
1672
2356
                        {
1673
2357
                                TypeSystemParserNode node = null;
1674
 
                                ITypeSystemParser parser = null;
1675
 
                                lock (FilesSkippedInParseThread) {
 
2358
                                TypeSystemParser parser = null;
 
2359
                                var tags = Context.GetExtensionObject <ProjectCommentTags> ();
 
2360
                                Context.InLoad = true;
 
2361
                                try {
1676
2362
                                        foreach (var file in (FileList ?? Context.Project.Files)) {
1677
 
                                                if (!string.Equals (file.BuildAction, "compile", StringComparison.OrdinalIgnoreCase)) 
1678
 
                                                        continue;
1679
2363
                                                var fileName = file.FilePath;
1680
 
                                                if (FilesSkippedInParseThread.Contains (fileName))
 
2364
                                                if (filesSkippedInParseThread.Any (f => f == fileName))
1681
2365
                                                        continue;
1682
 
                                                if (node == null || !node.CanParse (fileName)) {
1683
 
                                                        node = TypeSystemService.GetTypeSystemParserNode (DesktopService.GetMimeTypeForUri (fileName));
 
2366
                                                if (node == null || !node.CanParse (fileName, file.BuildAction)) {
 
2367
                                                        node = TypeSystemService.GetTypeSystemParserNode (DesktopService.GetMimeTypeForUri (fileName), file.BuildAction);
1684
2368
                                                        parser = node != null ? node.Parser : null;
1685
2369
                                                }
1686
2370
                                                if (parser == null)
1687
2371
                                                        continue;
1688
 
                                                using (var stream = new System.IO.StreamReader (fileName)) {
1689
 
                                                        var parsedDocument = parser.Parse (false, fileName, stream, Context.Project);
1690
 
                                                        UpdateParsedDocument (Context, parsedDocument);
1691
 
                                                        Context.UpdateContent (c => c.UpdateProjectContent (c.GetFile (fileName), parsedDocument.ParsedFile));
1692
 
                                                }
 
2372
                                                var parsedDocument = parser.Parse (false, fileName, Context.Project);
 
2373
                                                if (tags != null)
 
2374
                                                        tags.UpdateTags (Context.Project, parsedDocument.FileName, parsedDocument.TagComments);
 
2375
                                                var oldFile = Context.Content.GetFile (fileName);
 
2376
                                                Context.UpdateContent (c => c.AddOrUpdateFiles (parsedDocument.ParsedFile));
 
2377
                                                if (oldFile != null)
 
2378
                                                        Context.InformFileRemoved (new ParsedFileEventArgs (oldFile));
 
2379
                                                Context.InformFileAdded (new ParsedFileEventArgs (parsedDocument.ParsedFile));
1693
2380
                                        }
 
2381
                                } finally {
 
2382
                                        Context.InLoad = false;
1694
2383
                                }
1695
2384
                        }
1696
2385
                }
1697
2386
 
1698
 
                static void UpdateParsedDocument (ProjectContentWrapper context, ParsedDocument parsedDocument)
 
2387
                static void UpdateProjectCommentTasks (ProjectContentWrapper context, ParsedDocument parsedDocument)
1699
2388
                {
1700
2389
                        var tags = context.GetExtensionObject <ProjectCommentTags> ();
1701
 
                        if (tags == null) {
1702
 
                                tags = new ProjectCommentTags ();
1703
 
                                context.UpdateExtensionObject (tags);
1704
 
                                tags.Update (context.Project);
1705
 
                        }
1706
 
                        tags.UpdateTags (context.Project, parsedDocument.FileName, parsedDocument.TagComments);
 
2390
                        if (tags != null) // When tags are not there they're updated first time the tasks are requested.
 
2391
                                tags.UpdateTags (context.Project, parsedDocument.FileName, parsedDocument.TagComments);
1707
2392
                }
1708
2393
 
1709
 
                public static event EventHandler<ProjectFileEventArgs> FileParsed;
 
2394
//              public static event EventHandler<ProjectFileEventArgs> FileParsed;
1710
2395
 
1711
2396
                static object parseQueueLock = new object ();
1712
2397
                static AutoResetEvent parseEvent = new AutoResetEvent (false);
1799
2484
                                foreach (var pj in parseQueue) {
1800
2485
                                        if (pj.Context == context) {
1801
2486
                                                parseQueueIndex.Remove (pj.Context);
 
2487
                                                pj.Context.InLoad = false;
1802
2488
                                        }
1803
2489
                                }
1804
2490
                        }
1837
2523
                        }
1838
2524
                }
1839
2525
 
1840
 
                static bool IsFileModified (ProjectFile file, IParsedFile parsedFile)
 
2526
                static bool IsFileModified (ProjectFile file, IUnresolvedFile parsedFile)
1841
2527
                {
1842
2528
                        if (parsedFile == null)
1843
2529
                                return true;
1844
 
                        return System.IO.File.GetLastWriteTimeUtc (file.FilePath) > parsedFile.LastWriteTime;
 
2530
                        try {
 
2531
                                return System.IO.File.GetLastWriteTimeUtc (file.FilePath) > parsedFile.LastWriteTime;
 
2532
                        } catch (Exception) {
 
2533
                                return false;
 
2534
                        }
1845
2535
                }
1846
2536
 
1847
 
                static void CheckModifiedFiles (Project project, ProjectContentWrapper content)
 
2537
                static void CheckModifiedFiles (Project project, ProjectFile[] projectFiles, ProjectContentWrapper content)
1848
2538
                {
1849
 
                        List<ProjectFile> modifiedFiles = null;
1850
 
                        foreach (var file in project.Files) {
1851
 
                                if (!string.Equals (file.BuildAction, "compile", StringComparison.OrdinalIgnoreCase)) 
1852
 
                                        continue;
1853
 
                                var fileName = file.Name;
1854
 
                                // if the file is already inside the content a parser exists for it, if not check if it can be parsed.
1855
 
                                var oldFile = content.Content.GetFile (fileName);
1856
 
                                if (oldFile == null) {
1857
 
                                        var parser = TypeSystemService.GetParser (DesktopService.GetMimeTypeForUri (fileName));
1858
 
                                        if (parser == null)
1859
 
                                                continue;
1860
 
                                }
1861
 
                                if (!IsFileModified (file, oldFile))
1862
 
                                        continue;
1863
 
                                if (modifiedFiles == null)
1864
 
                                        modifiedFiles = new List<ProjectFile> ();
1865
 
                                modifiedFiles.Add (file);
1866
 
                        }
1867
 
                        
1868
 
                        // check if file needs to be removed from project content 
1869
 
                        foreach (var file in content.Content.Files) {
1870
 
                                if (project.GetProjectFile (file.FileName) == null)
1871
 
                                        content.UpdateContent (c => c.UpdateProjectContent (file, null));
1872
 
                        }
1873
 
                        
1874
 
                        if (modifiedFiles == null)
1875
 
                                return;
1876
 
                        QueueParseJob (content, modifiedFiles);
 
2539
                        try {
 
2540
                                var modifiedFiles = new List<ProjectFile> ();
 
2541
                                var oldFileNewFile = new List<Tuple<ProjectFile, IUnresolvedFile>> ();
 
2542
 
 
2543
                                lock (projectWrapperUpdateLock) {
 
2544
                                        foreach (var file in projectFiles) {
 
2545
                                                if (file.BuildAction == null) 
 
2546
                                                        continue;
 
2547
                                                // if the file is already inside the content a parser exists for it, if not check if it can be parsed.
 
2548
                                                var oldFile = content.Content.GetFile (file.Name);
 
2549
                                                oldFileNewFile.Add (Tuple.Create (file, oldFile));
 
2550
                                        }
 
2551
                                }
 
2552
 
 
2553
                                // This is disk intensive and slow
 
2554
                                oldFileNewFile.RemoveAll (t => !IsFileModified (t.Item1, t.Item2));
 
2555
 
 
2556
                                lock (projectWrapperUpdateLock) {
 
2557
                                        foreach (var v in oldFileNewFile) {
 
2558
                                                var file = v.Item1;
 
2559
                                                var oldFile = v.Item2;
 
2560
                                                if (oldFile == null) {
 
2561
                                                        var parser = TypeSystemService.GetParser (DesktopService.GetMimeTypeForUri (file.Name), file.BuildAction);
 
2562
                                                        if (parser == null)
 
2563
                                                                continue;
 
2564
                                                }
 
2565
                                                modifiedFiles.Add (file);
 
2566
                                        }
 
2567
                                        
 
2568
                                        // check if file needs to be removed from project content 
 
2569
                                        foreach (var file in content.Content.Files) {
 
2570
                                                if (project.GetProjectFile (file.FileName) == null) {
 
2571
                                                        content.UpdateContent (c => c.RemoveFiles (file.FileName));
 
2572
                                                        content.InformFileRemoved (new ParsedFileEventArgs (file));
 
2573
                                                }
 
2574
                                        }
 
2575
                                        
 
2576
                                        if (modifiedFiles.Count > 0)
 
2577
                                                QueueParseJob (content, modifiedFiles);
 
2578
                                }
 
2579
                        } catch (Exception e) {
 
2580
                                LoggingService.LogError ("Exception in check modified files.", e);
 
2581
                        }
1877
2582
                }
1878
2583
 
1879
2584
                static void CheckModifiedFile (AssemblyContext context)
1884
2589
                                        string cache = GetCacheDirectory (context.FileName);
1885
2590
                                        context.LastWriteTimeUtc = writeTime;
1886
2591
                                        if (cache != null) {
 
2592
                                                context.CtxLoader = new LazyAssemblyLoader (context.FileName, cache);
1887
2593
                                                SerializeObject (Path.Combine (cache, "assembly.descriptor"), context);
1888
 
                                                context.CtxLoader = new LazyAssemblyLoader (context.FileName, cache);
1889
2594
                                                try {
1890
2595
                                                        // File is reloaded by the lazy loader
1891
2596
                                                        File.Delete (Path.Combine (cache, "assembly.data"));
1897
2602
                                LoggingService.LogError ("Error while updating assembly " + context.FileName, e);
1898
2603
                        }
1899
2604
                }
1900
 
                
 
2605
 
1901
2606
                static void CheckModifiedFiles ()
1902
2607
                {
1903
2608
                        Queue<KeyValuePair<Project, ProjectContentWrapper>> list;
1904
 
                        
1905
 
                        lock (rwLock) {
 
2609
 
 
2610
                        lock (projectContentLock) {
1906
2611
                                list = new Queue<KeyValuePair<Project, ProjectContentWrapper>> (projectContents);
1907
2612
                        }
1908
 
                        
 
2613
 
1909
2614
                        while (list.Count > 0) {
1910
2615
                                var readydb = list.Dequeue ();
1911
 
                                CheckModifiedFiles (readydb.Key, readydb.Value);
1912
 
                        }
1913
 
                        
1914
 
                        Queue<KeyValuePair<string, AssemblyContext>> assemblyList;
1915
 
                        
1916
 
                        lock (rwLock) {
1917
 
                                assemblyList = new Queue<KeyValuePair<string, AssemblyContext>> (cachedAssemblyContents);
1918
 
                        }
1919
 
                        
 
2616
                                var files = readydb.Key.Files.ToArray ();
 
2617
                                CheckModifiedFiles (readydb.Key, files, readydb.Value);
 
2618
                        }
 
2619
                        
 
2620
                        var assemblyList = new Queue<KeyValuePair<string, AssemblyContext>> (cachedAssemblyContents);
 
2621
 
1920
2622
                        while (assemblyList.Count > 0) {
1921
2623
                                var readydb = assemblyList.Dequeue ();
1922
2624
                                CheckModifiedFile (readydb.Value);
1956
2658
                }
1957
2659
                #endregion
1958
2660
        }
1959
 
        
 
2661
 
 
2662
        internal sealed class AssemblyLoadedEventArgs : EventArgs
 
2663
        {
 
2664
                public readonly TypeSystemService.LazyAssemblyLoader Assembly;
 
2665
 
 
2666
                public AssemblyLoadedEventArgs (TypeSystemService.LazyAssemblyLoader assembly)
 
2667
                {
 
2668
                        this.Assembly = assembly;
 
2669
                }
 
2670
        }
 
2671
 
1960
2672
        public sealed class ProjectUnloadEventArgs : EventArgs
1961
2673
        {
1962
2674
                public readonly Project Project;
1970
2682
        }
1971
2683
}
1972
2684
 
 
2685