[MonoDevelop] Code Completion Database - The big patch

Lluis Sanchez lluis@ximian.com
Tue, 25 May 2004 03:41:46 +0200


--=-r+QCz1sSqgvIGOdPecXD
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Hi!

I finally found some time this weekend to finish this patch that fixes
several problems that the current implementation of the code completion
database has.

My goal for the patch was to make it possible to create a MonoDevelop
project with all files of corlib, consuming a reasonable amount of
memory and with fast startup and operation. With the old implementation,
only a with for corlib would take more than 15 minutes to open and it
would easily take 350Mb of memory.

It seems that I've made it since with the patch I can open a combine
with projects for corlib, System, System.Runtime.Remoting, System.Web
and System.Web.Services (around 3500 files), with a startup time of 10
seconds, and fitting in 70Mb of memory, with full support for code
completion and complete class view tree.

Issues with the old implementation
----------------------------------

The two big problems of the old implementation are the following:

1) Project files are parsed every time the project is opened, and parse
information is kept all in memory. This is unacceptable if you have a
combine with 3500 files.

2) The class tree is fully loaded with all class data. For corlib that
means around 25.000 tree nodes. It takes a lot of time and memory to
build such a tree.

The fix
-------

There are a lot of changes. I'm sorry because the patch is really big. I
hope the following notes can help in understanding what the changes are
about:

* Class information parsed from project files is now stored in a data
file, so it is not necessary to parse again all project files every time
a project is opened.

* Each project and each assembly has its own class information database.
The project database is stored in the same folder as the project.
Assembly databases are stored in the MonoDevelop code completion folder
and shared among all projects that reference them. The lifetime of those
databases is automatically managed by the Parser Service (i.e. if an
assembly is deleted, the corresponding shared database will also be
deleted).

* The format of the database is the same for projects and assemblies. It
has three parts: a set of headers (with information such as the version
of the database), an index of the classes stored in the database, and
the class data. When opening a database, only the headers and the index
is loaded in memory. Class information is retrieved from the data
section as it is requested. The old implementation already had something
like this, but the new format is more compact an can be used both for
projects and assemblies.

* The class tree is now loaded under demand. Class information is only
retrieved when the project or namespace node that contains it is
expanded.

* The initial generation of the code completion database is not needed.
Databases for assemblies are generated when needed. The generation is
made in an external process using the new tool dbgen, so it has no
impact on the memory consumed by the main MonoDevelop process.

* The parser service thread now keeps track of modified files. It will
update class information of externally modified files (assemblies and
project files). So, no worries when you cvs up.

* Class information is now "project-sensitive". It means that the code
completion window will show only class information taken from the
project to which the file being edited belongs, including all project
references (in other words, ctrl+space will include Gtk classes only if
the project includes a reference to the Gtk assembly). Most of methods
of IParserService now take an IProject as parameter, and this additional
parameter has propagated to many other classes, specially in
Addins/BackendBindings.

Some other info about the implementation:

* Improved the handling of events fired when adding or removing files
and references from a project. Now those events are fired at project
level and propagated to the combine and to the project service.

* Databases are handled by the new CodeCompletionDatabase class. It
keeps in memory the class index data structure and controls the access
to class data (caching that data when needed, and flushing to disk when
too much data is loaded). There are two subclasses:
ProjectCodeCompletionDatabase and AssemblyCodeCompletionDatabase.

* The class persistence layer has also many changes. Methods for reading
and writing class information are now static, which allows for example
to write any IClass, no matter what the implementation class it is. The
implementation has been also simplified by reusing more code from the
AbstractXXX classes.

There is also more information in the ChangeLogs.

The patches
-----------

To ease the review, I've divided the big patch in several small patches.
All of them must be applied for the whole thing to work. You can also
find everything in a single patch here: 

http://primates.ximian.com/~lluis/temp/cdb.diff

The patches are the following:

* changelogs.diff: all ChangeLogs

* parserservice.diff: Changes in the parser service. I also attach
DefaultParserService.cs for clarity, since almost everything changed.

* project.diff: Changes related to the addition of the IProject
parameter to IParserService methods (now class information is
per-project).

* events.diff: Changes related to the new event infrastructure added to
Project and Combine.

* persistence.diff: Changes in the persistence layer of class
information, and also some changes in the implementation layer.

* classscout.diff: Changes in the Class Scout (lazy load tree).

* dbgen.diff: The new database generation tool.

* other.diff: other unrelated fixes.


I'm sorry for the reviewers ;-)
Lluis.


--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=changelogs.diff
Content-Type: text/x-patch; name=changelogs.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: AddIns/DisplayBindings/SourceEditor/ChangeLog
===================================================================
--- AddIns/DisplayBindings/SourceEditor/ChangeLog	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/ChangeLog	(working copy)
@@ -1,3 +1,27 @@
+2004-05-24  Lluis Sanchez Gual  <lluis@ximian.com>
+
+	* Gui/SourceEditorBuffer.cs: Close the files used to read the text.
+	
+	* Gui/SourceEditorView.cs: Provide the project of the current file when
+	  creating the code completion window.
+	  
+	* CodeCompletion/CodeCompletionData.cs: Removed ClassProxy stuff.
+	
+	* CodeCompletion/CompletionWindow.cs: Added project parameter to ctor.
+	
+	* CodeCompletion/ICompletionDataProvider.cs,
+	  CodeCompletion/CommentCompletionDataProvider.cs,
+	  CodeCompletion/TemplateCompletionDataProvider.cs,
+	  CodeCompletion/CodeCompletionDataProvider.cs: Added project parameter
+	  to GenerateCompletionData().
+	  
+	* InsightWindow/MethodInsightDataProvider.cs
+	  InsightWindow/InsightWindow.cs: Added project parameter to constructor.
+	  
+	* InsightWindow/IInsightDataProvider.cs,
+	  InsightWindow/IndexerInsightDataProvider.cs: Added project parameter to
+	  SetupDataProvider.
+
 2004-05-22  Todd Berman  <tberman@sevenl.net>
 
 	* Gui/SourceEditorView.cs: applied patch by Gustav Munkby <grrdev AT
Index: AddIns/BackendBindings/CSharpBinding/ChangeLog
===================================================================
--- AddIns/BackendBindings/CSharpBinding/ChangeLog	(revision 1623)
+++ AddIns/BackendBindings/CSharpBinding/ChangeLog	(working copy)
@@ -1,3 +1,10 @@
+2004-05-24  Lluis Sanchez Gual  <lluis@ximian.com>
+
+	* Parser/Parser.cs: Set the file name to the region of each parsed class.
+	  Added IProject parameter in CtrlSpace and Resolve.
+	* Parser/Resolver.cs: Added IProject parameter where needed. Use new 
+	  methods in IParserService.
+
 2004-05-22  Todd Berman  <tberman@sevenl.net>
 
 	* CSharpBindingCompilerManager.cs: add "s to work around potential
Index: Main/Base/ChangeLog
===================================================================
--- Main/Base/ChangeLog	(revision 1623)
+++ Main/Base/ChangeLog	(working copy)
@@ -1,3 +1,117 @@
+2004-05-24  Lluis Sanchez Gual  <lluis@ximian.com>
+
+	* Commands/ProjectBrowserCommands/ReferenceFolderNodeCommands.cs:
+	  Removed call to IParserService.AddReferenceToCompletionLookup. The parser
+	  service now receives an event when a reference is added.
+	  
+	* Commands/AutostartCommands.cs: Disabled generation of initial code
+	  completion database.
+	  
+	* Services/File/DefaultFileService.cs: In LoadFileWrapper, use IProject
+	  reference instead of project name.
+	
+	* Services/Project/DefaultProjectService.cs: Added ReferenceAddedToProject
+	  and ReferenceRemovedFromProject events. Changed how event are handled.
+	  Now the service just forwards the events received from the open combine.
+	  The file events now use a new ProjectFileEventHandler delegate, which
+	  provide information about the source project in the args.
+	  
+	* Services/Project/IProjectService.cs: Added new reference events.
+	
+	* ParserService/DefaultParserService.cs: Mostly reimplemented. The new
+	  implementation uses a unified data structure for storing information
+	  from projects and assemblies.
+	  
+	* Services/ParserService/AssemblyInformation.cs: Added FileName property.
+	
+	* Services/ParserService/IParserService.cs: Added IProject parameter to
+	  most of methods. Added SearchNamespace, SearchType methods (moved
+	  from AbstractUnit), and GetClassInheritanceTree (moved from 
+	  AbstractClass).
+	  Removed ParseInformationAdded and ParseInformationRemoved, and added a
+	  new ClassInformationChanged event that provides all change information
+	  at once.
+	  
+	* Gui/Workbench/Layouts/SdiWorkspaceLayout.cs: Take the name of the project
+	  from view's IProject property.
+	  
+	* Gui/Workbench/DefaultWorkbench.cs: Added basic support for drag&drop from
+	  file manager.
+	  
+	* Gui/IViewContent.cs: Changed ProjectName property to IProject Project
+	  property.
+	  
+	* Gui/Pads/ClassScout/NodeBuilder/DefaultDotNetClassScoutNodeBuilder.cs
+	* Gui/Pads/ClassScout/ClassScout.cs: Use the new events and data structures
+	  from of parser service. Now, class data is not fully loaded when opening
+	  the project, but it is loaded under demand as project nodes are expanded.
+	  
+	* Gui/Pads/ClassScout/NodeBuilder/IClassScoutNodeBuilder.cs: Use a single
+	  method to update the tree from parse event args.
+	  
+	* Gui/Pads/ProjectBrowser/BrowserNode/ProjectBrowserNode.cs,
+	  Gui/Pads/ProjectBrowser/BrowserNode/CombineBrowserNode.cs:
+	  Use Combine.RemoveEntry to remove projects from a combine.
+	  
+	* Gui/AbstractViewContent.cs: Implement new Project property.
+	
+	* Makefile.am: Added new files: 
+	  Services/ParserService/CodeCompletionDatabase.cs,
+	  Services/ParserService/ClassInformationEventHandler.cs,
+	  Internal/Project/Project/ProjectReferenceEventArgs.cs,
+	  Internal/Project/Project/ProjectFileEventArgs.cs,
+	  Internal/Project/Combine/CombineEntryEventArgs.cs.
+	  
+	* Internal/Project/Project/IProject.cs: Added new events for changes in
+	  files and references.
+	  
+	* Internal/Project/Project/Collections/ProjectReferenceCollection.cs
+	  Internal/Project/Project/Collections/ProjectFileCollection.cs,
+	  AbstractProject.cs,
+	  Internal/Project/Combine/Combine.cs:
+	  Added support for new events.
+	  
+	* Internal/Project/Combine/CombineEntry.cs: Created CombineEntryCollection.
+	
+	* Internal/Parser/PersistenceLayer/PersistentIndexer.cs,
+	  Internal/Parser/PersistenceLayer/PersistentParameter.cs,
+	  Internal/Parser/PersistenceLayer/PersistentMethod.cs,
+	  Internal/Parser/PersistenceLayer/PersistentReturnType.cs,
+	  Internal/Parser/PersistenceLayer/PersistentEvent.cs,
+	  Internal/Parser/PersistenceLayer/PersistentField.cs,
+	  Internal/Parser/PersistenceLayer/PersistentProperty.cs,
+	  Internal/Parser/PersistenceLayer/PersistentClass.cs,
+	  New implementation of read and write methods based on static methods. In
+	  this way it can be used to write instances of any IClass and not only
+	  PersistentClass. Also use new helper methods for writing strings and
+	  object references.
+	  
+	* Internal/Parser/IClass.cs: Moved ClassInheritanceTree to IParserService.
+	
+	* Internal/Parser/ReflectionLayer/ReflectionClass.cs: Added Null check for
+	  MonodocService.
+	  
+	* Internal/Parser/IRegion.cs: Added FileName property.
+	
+	* Internal/Parser/Implementations/AbstractUsing.cs,
+	  Internal/Parser/IUsing.cs: Moved SearchType and SearchNamespace to
+	  IParserService.
+	  
+	* Internal/Parser/Implementations/AbstractDecoration.cs,
+	  Internal/Parser/Implementations/AbstractNamedEntity.cs,
+	  Internal/Parser/Implementations/AbstractReturnType.cs: Fixed usage of
+	  documentation hashtable. GetHashCode() do not return unique values!
+	  
+	* Internal/Parser/Implementations/DefaultRegion.cs: Implemented FileName
+	  property.
+	  
+	* Internal/Parser/Implementations/AbstractClass.cs: 
+	  Moved ClassInheritanceTree to IParserService.
+	  
+	* Internal/Parser/Implementations/AbstractParameter.cs: Added null check.
+	
+	* Internal/Parser/IParser.cs: Added Project parameter to some methods.
+	
 2004-05-22  Todd Berman  <tberman@sevenl.net>
 
 	* Gui/Dialogs/NewProjectDialog.cs: Sort properly.
Index: Libraries/SharpRefactory/ChangeLog
===================================================================
--- Libraries/SharpRefactory/ChangeLog	(revision 1623)
+++ Libraries/SharpRefactory/ChangeLog	(working copy)
@@ -1,3 +1,7 @@
+2004-05-24  Lluis Sanchez Gual  <lluis@ximian.com>
+
+	* src/Parser/AST/AbstractNode.cs: Lazily create children arraylist.
+
 2004-03-29  Todd Berman  <tberman@sevenl.net>
 
 	* src/Parser/Expressions/PrimitiveExpression.cs: stop requiring ICU 

--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=parserservice.diff
Content-Type: text/x-patch; name=parserservice.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: Main/Base/Commands/AutostartCommands.cs
===================================================================
--- Main/Base/Commands/AutostartCommands.cs	(revision 1623)
+++ Main/Base/Commands/AutostartCommands.cs	(working copy)
@@ -54,16 +54,14 @@
 		{
 			PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
 			string path = propertyService.GetProperty ("SharpDevelop.CodeCompletion.DataDirectory", null);
-			string codeCompletionProxyFile = Path.Combine (path, "CodeCompletionProxyDataV02.bin");
+			string codeCompletionProxyFile = Path.Combine (path, "mscorlib.pidb");
 			//Console.WriteLine("checking for existence of {0}", codeCompletionProxyFile);
 
-			if (!File.Exists (codeCompletionProxyFile)) {
+/*			if (!File.Exists (codeCompletionProxyFile)) {
 				generatingCompletionData = true;
 				RunWizard();
-				DefaultParserService parserService = (DefaultParserService)ServiceManager.Services.GetService(typeof(IParserService));
-				parserService.LoadProxyDataFile();
 			}
-		}
+*/		}
 		
 		void RunWizard()
 		{
Index: Main/Base/Services/ParserService/DefaultParserService.cs
===================================================================
--- Main/Base/Services/ParserService/DefaultParserService.cs	(revision 1623)
+++ Main/Base/Services/ParserService/DefaultParserService.cs	(working copy)
@@ -32,54 +32,52 @@
 {
 	public class DefaultParserService : AbstractService, IParserService
 	{
-		Hashtable classes                = new Hashtable();
-		Hashtable caseInsensitiveClasses = new Hashtable();
+		CodeCompletionDatabase coreDatabase;
 		
-		// used to map 'real' namespace hashtable inside case insensitive hashtable
-		const string CaseInsensitiveKey = "__CASE_INSENSITIVE_HASH";
-		Hashtable namespaces                = new Hashtable();
-		Hashtable caseInsensitiveNamespaces = new Hashtable();
+		const int MAX_CACHE_SIZE = 10;
+		const string CoreDB = "Assembly:mscorlib";
+
+		class ParsingCacheEntry
+		{
+			   public ParseInformation ParseInformation;
+			   public string FileName;
+			   public DateTime AccessTime;
+		}
 		
-		Hashtable parsings   = new Hashtable();
+		class ParsingJob
+		{
+			public object Data;
+			public WaitCallback ParseCallback;
+		}
+
+		Hashtable lastUpdateSize = new Hashtable();
+		Hashtable parsings = new Hashtable ();
 		
 		ParseInformation addedParseInformation = new ParseInformation();
 		ParseInformation removedParseInformation = new ParseInformation();
+		CombineEntryEventHandler combineEntryAddedHandler;
+		CombineEntryEventHandler combineEntryRemovedHandler;
 
-//// Alex: this one keeps requests for parsing and is used to start parser (pulsed)
-//// otherwise continuous reparsing of files is causing leaks
-//		public static Queue ParserPulse=new Queue();	// required for monitoring when to restart thread
-//// Alex: end of mod
+		public static Queue parseQueue = new Queue();
+		
+		string codeCompletionPath;
 
-		/// <remarks>
-		/// The keys are the assemblies loaded. This hash table ensures that no
-		/// assembly is loaded twice. I know that strong naming might be better but
-		/// the use case isn't there. No one references 2 differnt files if he references
-		/// the same assembly.
-		/// </remarks>
-		Hashtable loadedAssemblies = new Hashtable();
+		Hashtable databases = new Hashtable();
 		
-		ClassProxyCollection classProxies = new ClassProxyCollection();
 		IParser[] parser;
+		
 		readonly static string[] assemblyList = {
 			"Microsoft.VisualBasic",
-			//"Microsoft.JScript",
 			"mscorlib",
 			"System.Data",
 			"System.Design",
-			"System.DirectoryServices",
 			"System.Drawing.Design",
 			"System.Drawing",
-			"System.EnterpriseServices",
-			"System.Management",
-			"System.Messaging",
 			"System.Runtime.Remoting",
-			"System.Runtime.Serialization.Formatters.Soap",
-
 			"System.Security",
 			"System.ServiceProcess",
 			"System.Web.Services",
 			"System.Web",
-			//"System.Windows.Forms",
 			"System",
 			"System.Xml",
 			"glib-sharp",
@@ -90,48 +88,50 @@
 			"gnome-sharp",
 			"gconf-sharp",
 			"gtkhtml-sharp",
+			//"System.Windows.Forms",
+			//"Microsoft.JScript",
 		};
 		
+		StringNameTable nameTable;
+		
+		string[] sharedNameTable = new string[] {
+			"System.String", "System.Boolean", "System.Int32", "System.Attribute",
+			"System.Delegate", "System.Enum", "System.Exception", "System.MarshalByRefObject",
+			"System.Object", "SerializableAttribtue", "System.Type", "System.ValueType",
+			"System.ICloneable", "System.IDisposable", "System.IConvertible", "System.Bye",
+			"System.Char", "System.DateTime", "System.Decimal", "System.Double", "System.Int16",
+			"System.Int64", "System.IntPtr", "System.SByte", "System.Single", "System.TimeSpan",
+			"System.UInt16", "System.UInt32", "System.UInt64", "System.Void"
+		};
+		
 		public DefaultParserService()
 		{
 			addedParseInformation.DirtyCompilationUnit = new DummyCompilationUnit();
 			removedParseInformation.DirtyCompilationUnit = new DummyCompilationUnit();
+			combineEntryAddedHandler = new CombineEntryEventHandler (OnCombineEntryAdded);
+			combineEntryRemovedHandler = new CombineEntryEventHandler (OnCombineEntryRemoved);
+			nameTable = new StringNameTable (sharedNameTable);
 		}
 		
-		public static string[] AssemblyList {
-			get {
-				return assemblyList;
-			}
-		}
-		
 		public string LoadAssemblyFromGac (string name) {
 			MethodInfo gac_get = typeof (System.Environment).GetMethod ("internalGetGacPath", BindingFlags.Static|BindingFlags.NonPublic);
 			
-			if (gac_get == null)
-				return String.Empty;
-			
-			string use_name = name;
-			string asmb_path;
-			string [] canidates;
-
 			if (name == "mscorlib")
-				return Path.Combine ((string) gac_get.Invoke (null, null), name + ".dll");
-            
-			if (name.EndsWith (".dll"))
-				use_name = name.Substring (0, name.Length - 4);
+				return typeof(object).Assembly.Location;
+				
+			Assembly asm;
+			try {
+				asm = Assembly.Load (name);
+			}
+			catch {
+				asm = Assembly.LoadWithPartialName (name);
+			}
+			if (asm == null) {
+				Console.WriteLine ("Could not find: " + name);
+				return string.Empty;
+			}
 			
-			asmb_path = Path.Combine (Path.Combine (Path.Combine ((string) gac_get.Invoke (null, null), "mono"), "gac"), use_name);
-            
-			if (!Directory.Exists (asmb_path))
-				return String.Empty;
-			
-			canidates = Directory.GetDirectories (asmb_path, GetSysVersion () + "*");
-			if (canidates.Length == 0)
-				canidates = Directory.GetDirectories (asmb_path);
-			if (canidates.Length == 0)
-				return String.Empty;
-			
-			return Path.Combine (canidates [0], use_name + ".dll");
+			return asm.Location;
 		}
 		
 		string sys_version;
@@ -142,49 +142,12 @@
 			return sys_version;
 		}
 		
-		/// <remarks>
-		/// The initialize method writes the location of the code completion proxy
-		/// file to this string.
-		/// </remarks>
-		string codeCompletionProxyFile;
-		string codeCompletionMainFile;
 
-		class ClasstableEntry
-		{
-			IClass           myClass;
-			ICompilationUnit myCompilationUnit;
-			string           myFileName;
-
-			public IClass Class {
-				get {
-					return myClass;
-				}
-			}
-
-			public ICompilationUnit CompilationUnit {
-				get {
-					return myCompilationUnit;
-				}
-			}
-
-			public string FileName {
-				get {
-					return myFileName;
-				}
-			}
-
-			public ClasstableEntry(string fileName, ICompilationUnit compilationUnit, IClass c)
-			{
-				this.myCompilationUnit = compilationUnit;
-				this.myFileName        = fileName;
-				this.myClass           = c;
-			}
-		}
-
 		private bool ContinueWithProcess(IProgressMonitor progressMonitor)
 		{
 			while (Gtk.Application.EventsPending ())
 				Gtk.Application.RunIteration ();
+
 			if (progressMonitor.Canceled)
 				return false;
 			else
@@ -193,172 +156,275 @@
 	
 		public void GenerateCodeCompletionDatabase(string createPath, IProgressMonitor progressMonitor)
 		{
-			SetCodeCompletionFileLocation(createPath);
+			if (progressMonitor != null)
+				progressMonitor.BeginTask(GettextCatalog.GetString ("Generate code completion database"), assemblyList.Length);
 
-			// write all classes and proxies to the disc
-			BinaryWriter classWriter = new BinaryWriter(new BufferedStream(new FileStream(codeCompletionMainFile, FileMode.Create, FileAccess.Write, FileShare.None)));
-			BinaryWriter proxyWriter = new BinaryWriter(new BufferedStream(new FileStream(codeCompletionProxyFile, FileMode.Create, FileAccess.Write, FileShare.None)));
-			if (progressMonitor != null) {
-				progressMonitor.BeginTask(GettextCatalog.GetString ("Generate code completion database"), assemblyList.Length);
-			}
-			
-			// convert all assemblies
-			for (int i = 0; i < assemblyList.Length; ++i) {
+			for (int i = 0; i < assemblyList.Length; ++i)
+			{
 				try {
-					//FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
-					//string path = fileUtilityService.GetDirectoryNameWithSeparator(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory());
+					AssemblyCodeCompletionDatabase db = new AssemblyCodeCompletionDatabase (codeCompletionPath, assemblyList[i], this);
+					db.ParseAll ();
+					db.Write ();
 					
-					AssemblyInformation frameworkAssemblyInformation = new AssemblyInformation();
-					frameworkAssemblyInformation.Load(LoadAssemblyFromGac (assemblyList[i]), false);
-					// create all class proxies
-					foreach (IClass newClass in frameworkAssemblyInformation.Classes) {
-						ClassProxy newProxy = new ClassProxy(newClass);
-						classProxies.Add(newProxy);
-						AddClassToNamespaceList(newProxy);
-
-						PersistentClass pc = new PersistentClass(classProxies, newClass);
-						newProxy.Offset = (uint)classWriter.BaseStream.Position;
-						newProxy.WriteTo(proxyWriter);
-						pc.WriteTo(classWriter);
-					}
-					
-					if (progressMonitor != null) {
+					if (progressMonitor != null)
 						progressMonitor.Worked(i, GettextCatalog.GetString ("Writing class"));
-					}
-					if (!ContinueWithProcess(progressMonitor))
+						
+					if (!ContinueWithProcess (progressMonitor))
 						return;
-				} catch (Exception e) {
-					Console.WriteLine(e.ToString());
 				}
-				System.GC.Collect();
+				catch (Exception ex) {
+					Console.WriteLine (ex);
+				}
 			}
 
-			classWriter.Close();
-			proxyWriter.Close();
 			if (progressMonitor != null) {
 				progressMonitor.Done();
 			}
 		}
 		
-		void SetCodeCompletionFileLocation(string path)
+		public void GenerateAssemblyDatabase (string baseDir, string name)
 		{
-			FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
-			string codeCompletionTemp = fileUtilityService.GetDirectoryNameWithSeparator(path);
-
-			codeCompletionProxyFile = codeCompletionTemp + "CodeCompletionProxyDataV02.bin";
-			codeCompletionMainFile  = codeCompletionTemp + "CodeCompletionMainDataV02.bin";
+			AssemblyCodeCompletionDatabase db = GetDatabase (baseDir, "Assembly:" + name) as AssemblyCodeCompletionDatabase;
+			db.ParseInExternalProcess = false;
+			db.ParseAll ();
+			db.Write ();
 		}
-
+		
 		void SetDefaultCompletionFileLocation()
 		{
 			PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
-			SetCodeCompletionFileLocation(propertyService.GetProperty("SharpDevelop.CodeCompletion.DataDirectory", String.Empty).ToString());
+			string path = (propertyService.GetProperty("SharpDevelop.CodeCompletion.DataDirectory", String.Empty).ToString());
+			FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
+			codeCompletionPath = fileUtilityService.GetDirectoryNameWithSeparator(path);
 		}
 
-		public void LoadProxyDataFile()
+		public override void InitializeService()
 		{
-			if (!File.Exists(codeCompletionProxyFile)) {
-				return;
+			parser = (IParser[])(AddInTreeSingleton.AddInTree.GetTreeNode("/Workspace/Parser").BuildChildItems(this)).ToArray(typeof(IParser));
+			
+			SetDefaultCompletionFileLocation();
+			DeleteObsoleteDatabases ();
+
+			coreDatabase = new AssemblyCodeCompletionDatabase (codeCompletionPath, "mscorlib", this);
+			databases [CoreDB] = coreDatabase;
+			
+			IProjectService projectService = (IProjectService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
+			projectService.CombineOpened += new CombineEventHandler(OnCombineOpened);
+			projectService.CombineClosed += new CombineEventHandler(OnCombineClosed);
+			projectService.FileRemovedFromProject += new ProjectFileEventHandler (OnProjectFilesChanged);
+			projectService.FileAddedToProject += new ProjectFileEventHandler (OnProjectFilesChanged);
+			projectService.ReferenceAddedToProject += new ProjectReferenceEventHandler (OnProjectReferencesChanged);
+			projectService.ReferenceRemovedFromProject += new ProjectReferenceEventHandler (OnProjectReferencesChanged);
+			projectService.ProjectRenamed += new ProjectRenameEventHandler(OnProjectRenamed);
+		}
+		
+		internal CodeCompletionDatabase GetDatabase (string uri)
+		{
+			return GetDatabase (null, uri);
+		}
+		
+		internal ProjectCodeCompletionDatabase GetProjectDatabase (IProject project)
+		{
+			if (project == null) return null;
+			return (ProjectCodeCompletionDatabase) GetDatabase (null, "Project:" + project.Name);
+		}
+		
+		internal CodeCompletionDatabase GetDatabase (string baseDir, string uri)
+		{
+			lock (databases)
+			{
+				if (baseDir == null) baseDir = codeCompletionPath;
+				CodeCompletionDatabase db = (CodeCompletionDatabase) databases [uri];
+				if (db == null) 
+				{
+					// Create/load the database
+						
+					if (uri.StartsWith ("Assembly:"))
+					{
+						string file = uri.Substring (9);
+						db = new AssemblyCodeCompletionDatabase (baseDir, file, this);
+					}
+					else if (uri.StartsWith ("Gac:"))
+					{
+						string file = uri.Substring (4);
+						db = new AssemblyCodeCompletionDatabase (baseDir, file, this);
+					}
+					if (db != null)
+						databases [uri] = db;
+				}
+				return db;
 			}
-			BinaryReader reader = new BinaryReader(new BufferedStream(new FileStream(codeCompletionProxyFile, FileMode.Open, FileAccess.Read, FileShare.Read)));
-			while (true) {
-				try {
-					ClassProxy newProxy = new ClassProxy(reader);
-					classProxies.Add(newProxy);
-					AddClassToNamespaceList(newProxy);
-				} catch (Exception) {
-					break;
+		}
+		
+		void LoadProjectDatabase (IProject project)
+		{
+			lock (databases)
+			{
+				string uri = "Project:" + project.Name;
+				if (databases.Contains (uri)) return;
+				
+				ProjectCodeCompletionDatabase db = new ProjectCodeCompletionDatabase (project, this);
+				databases [uri] = db;
+				
+				foreach (ReferenceEntry re in db.References)
+				{
+					GetDatabase (re.Uri);
 				}
 			}
-			reader.Close();
 		}
 		
-		void LoadThread()
+		void UnloadDatabase (string uri)
 		{
-			SetDefaultCompletionFileLocation();
-			
-			BinaryFormatter formatter = new BinaryFormatter();
-			
-			if (File.Exists(codeCompletionProxyFile)) {
-				LoadProxyDataFile();
+			if (uri == CoreDB) return;
+			lock (databases)
+			{
+				CodeCompletionDatabase db = databases [uri] as CodeCompletionDatabase;
+				if (db != null) {
+					db.Write ();
+					databases.Remove (uri);
+				}
 			}
 		}
 		
-		public override void InitializeService()
+		void UnloadProjectDatabase (IProject project)
 		{
-			parser = (IParser[])(AddInTreeSingleton.AddInTree.GetTreeNode("/Workspace/Parser").BuildChildItems(this)).ToArray(typeof(IParser));
-			
-			Thread myThread = new Thread(new ThreadStart(LoadThread));
-			myThread.IsBackground = true;
-			myThread.Priority = ThreadPriority.Lowest;
-			myThread.Start();
-			
-			IProjectService projectService = (IProjectService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
-			projectService.CombineOpened += new CombineEventHandler(OpenCombine);
+			string uri = "Project:" + project.Name;
+			UnloadDatabase (uri);
 		}
 		
-		public void AddReferenceToCompletionLookup(IProject project, ProjectReference reference)
+		void CleanUnusedDatabases ()
 		{
-			if (reference.ReferenceType != ReferenceType.Project) {
-				string fileName = reference.GetReferencedFileName(project);
-				if (fileName == null || fileName.Length == 0) {
-					return;
-				}
-				foreach (string assemblyName in assemblyList) {
-					if (Path.GetFileNameWithoutExtension(fileName).ToUpper() == assemblyName.ToUpper()) {
-						return;
+			lock (databases)
+			{
+				Hashtable references = new Hashtable ();
+				foreach (CodeCompletionDatabase db in databases.Values)
+				{
+					if (db is ProjectCodeCompletionDatabase) {
+						foreach (ReferenceEntry re in ((ProjectCodeCompletionDatabase)db).References)
+							references [re.Uri] = null;
 					}
 				}
-				// HACK : Don't load references for non C# projects
-				if (project.ProjectType != "C#") {
-					return;
+				
+				ArrayList todel = new ArrayList ();
+				foreach (DictionaryEntry en in databases)
+				{
+					if (!(en.Value is ProjectCodeCompletionDatabase) && !references.Contains (en.Key))
+						todel.Add (en.Key);
 				}
-				if (File.Exists(fileName)) {
-					Thread t = new Thread(new ThreadStart(new AssemblyLoader(this, fileName).LoadAssemblyParseInformations));
-					t.Start();
+				
+				foreach (string uri in todel)
+					UnloadDatabase (uri);
+			}
+		}
+		
+		public void LoadCombineDatabases (Combine combine)
+		{
+			ArrayList projects = Combine.GetAllProjects(combine);
+			foreach (ProjectCombineEntry entry in projects) {
+				LoadProjectDatabase (entry.Project);
+			}
+		}
+		
+		public void UnloadCombineDatabases (Combine combine)
+		{
+			ArrayList projects = Combine.GetAllProjects(combine);
+			foreach (ProjectCombineEntry entry in projects) {
+				UnloadProjectDatabase (entry.Project);
+			}
+		}
+		
+		public void OnCombineOpened(object sender, CombineEventArgs e)
+		{
+			LoadCombineDatabases (e.Combine);
+			e.Combine.EntryAdded += combineEntryAddedHandler;
+			e.Combine.EntryRemoved += combineEntryRemovedHandler;
+		}
+		
+		public void OnCombineClosed (object sender, CombineEventArgs e)
+		{
+			UnloadCombineDatabases (e.Combine);
+			CleanUnusedDatabases ();
+			e.Combine.EntryAdded -= combineEntryAddedHandler;
+			e.Combine.EntryRemoved -= combineEntryRemovedHandler;
+		}
+		
+		void OnProjectRenamed (object sender, ProjectRenameEventArgs args)
+		{
+			ProjectCodeCompletionDatabase db = GetProjectDatabase (args.Project);
+			if (db == null) return;
+			
+			db.Rename (args.NewName);
+			databases.Remove ("Project:" + args.OldName);
+			databases ["Project:" + args.NewName] = db;
+			RefreshProjectDatabases ();
+			CleanUnusedDatabases ();
+		}
+		
+		void OnCombineEntryAdded (object sender, CombineEntryEventArgs args)
+		{
+			if (args.CombineEntry is ProjectCombineEntry)
+				LoadProjectDatabase (((ProjectCombineEntry)args.CombineEntry).Project);
+			else if (args.CombineEntry is CombineCombineEntry)
+				LoadCombineDatabases (((CombineCombineEntry)args.CombineEntry).Combine);
+		}
+		
+		void OnCombineEntryRemoved (object sender, CombineEntryEventArgs args)
+		{
+			if (args.CombineEntry is ProjectCombineEntry)
+				UnloadProjectDatabase (((ProjectCombineEntry)args.CombineEntry).Project);
+			else if (args.CombineEntry is CombineCombineEntry)
+				UnloadCombineDatabases (((CombineCombineEntry)args.CombineEntry).Combine);
+			CleanUnusedDatabases ();
+		}
+		
+		void OnProjectFilesChanged (object sender, ProjectFileEventArgs args)
+		{
+			ProjectCodeCompletionDatabase db = GetProjectDatabase (args.Project);
+			if (db != null) db.UpdateFromProject ();
+		}
+		
+		void OnProjectReferencesChanged (object sender, ProjectReferenceEventArgs args)
+		{
+			ProjectCodeCompletionDatabase db = GetProjectDatabase (args.Project);
+			if (db != null) {
+				db.UpdateFromProject ();
+				foreach (ReferenceEntry re in db.References)
+				{
+					// Make sure the db is loaded
+					GetDatabase (re.Uri);
 				}
 			}
 		}
 		
-		class AssemblyLoader
+		void RefreshProjectDatabases ()
 		{
-			DefaultParserService parserService;
-			string assemblyFileName;
-			
-			public AssemblyLoader(DefaultParserService parserService, string assemblyFileName)
+			foreach (CodeCompletionDatabase db in databases.Values)
 			{
-				this.parserService    = parserService;
-				this.assemblyFileName = assemblyFileName;
+				ProjectCodeCompletionDatabase pdb = db as ProjectCodeCompletionDatabase;
+				if (pdb != null)
+					pdb.UpdateFromProject ();
 			}
-			
-			public void LoadAssemblyParseInformations()
+		}
+		
+		internal void QueueParseJob (WaitCallback callback, object data)
+		{
+			ParsingJob job = new ParsingJob ();
+			job.ParseCallback = callback;
+			job.Data = data;
+			lock (parseQueue)
 			{
-				if (parserService.loadedAssemblies[assemblyFileName] != null) {
-					return;
-				}
-				parserService.loadedAssemblies[assemblyFileName] = true;
-				try {
-					AssemblyInformation assemblyInformation = new AssemblyInformation();
-					assemblyInformation.Load(assemblyFileName, true);
-					foreach (IClass newClass in assemblyInformation.Classes) {
-						parserService.AddClassToNamespaceList(newClass);
-						lock (parserService.classes) {
-							parserService.caseInsensitiveClasses[newClass.FullyQualifiedName.ToLower()] = parserService.classes[newClass.FullyQualifiedName] = new ClasstableEntry(null, null, newClass);
-						}
-					}
-				} catch (Exception e) {
-					Console.WriteLine("Can't add reference : " + e.ToString());
-				}
+				parseQueue.Enqueue (job);
 			}
 		}
 		
-		public void OpenCombine(object sender, CombineEventArgs e)
+		void DeleteObsoleteDatabases ()
 		{
-			ArrayList projects =  Combine.GetAllProjects(e.Combine);
-			foreach (ProjectCombineEntry entry in projects) {
-				foreach (ProjectReference r in entry.Project.ProjectReferences) {
-					AddReferenceToCompletionLookup(entry.Project, r);
-				}
+			string[] files = Directory.GetFiles (codeCompletionPath, "*.pidb");
+			foreach (string file in files)
+			{
+				string name = Path.GetFileNameWithoutExtension (file);
+				string baseDir = Path.GetDirectoryName (file);
+				AssemblyCodeCompletionDatabase.CleanDatabase (baseDir, name);
 			}
 		}
 		
@@ -369,252 +435,329 @@
 			t.Start();
 		}
 		
-		Hashtable lastUpdateSize = new Hashtable();
+		
 		void ParserUpdateThread()
 		{
-// 			string fn=null;
-			while (true) {
-				////Thread.Sleep(1000); // not required
-//// Alex: if some file was pulsed - during editor load and after - get file to reparse
-//				fn = null; // set to null for each repetition
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-//	Mike: Doesn't work with folding marker update --> look at the folding markers
-//  Mike: You can't simply BREAK a feature and say I should fix it ... either bring the folding
-//        markers in a working state or leave this change ... I don't see that your change is a good
-//        alternative ... the current parserthread looks at the text and if it changed it reparses ...
-//        it is better than the old version you fixed 
-// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-//				lock(DefaultParserService.ParserPulse) {
-//					//Console.WriteLine("Pulse got: {0} entries",DefaultParserService.ParserPulse.Count);
-//					Monitor.Wait(DefaultParserService.ParserPulse);
-//					if (DefaultParserService.ParserPulse.Count>0) {
-//						fn = (string)DefaultParserService.ParserPulse.Dequeue();
-//					}
-//				}
-				try {
-					if (WorkbenchSingleton.Workbench.ActiveWorkbenchWindow != null && WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ActiveViewContent != null) {
-						IEditable editable = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ActiveViewContent as IEditable;
-						if (editable != null) {
-							string fileName = null;
-							
-							IViewContent viewContent = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ViewContent;
-							IParseableContent parseableContent = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.ActiveViewContent as IParseableContent;
-							
-							if (parseableContent != null) {
-								fileName = parseableContent.ParseableContentName;
-							} else {
-								fileName = viewContent.IsUntitled ? viewContent.UntitledName : viewContent.ContentName;
-							}
-							
-							if (!(fileName == null || fileName.Length == 0)) {
-//								Thread.Sleep(300); // not required 
-								IParseInformation parseInformation = null;
-								bool updated = false;
-								lock (parsings) {
-									string text = editable.Text;
-									if (text != null) {
-									
-										if (lastUpdateSize[fileName] == null || (int)lastUpdateSize[fileName] != text.GetHashCode()) {
-											parseInformation = ParseFile(fileName, text);
-											lastUpdateSize[fileName] = text.GetHashCode();
-											updated = true;
-										}
-									} 
-								}
-								if (updated) {
-									if (parseInformation != null && editable is IParseInformationListener) {
-										((IParseInformationListener)editable).ParseInformationUpdated(parseInformation);
-									}
-								}
-//								if (fn != null) {
-//									ParseFile(fn); // TODO: this one should update file parsings requested through queue
-//								}
-							}
-						}
-					}
-				} catch (Exception e) {
-					try {
-						Console.WriteLine(e.ToString());
-					} catch {}
-				}
-				Thread.Sleep(500); // not required
-				//System.GC.Collect();
+			int loop = 0;
+			while (true)
+			{
+				Thread.Sleep(500);
+				
+				ParseCurrentFile ();
+				
+				ConsumeParsingQueue ();
+				
+				if (loop % 10 == 0)
+					CheckModifiedFiles ();
+				
+				loop++;
 			}
 		}
 		
-		Hashtable AddClassToNamespaceList(IClass addClass)
+		void CheckModifiedFiles ()
 		{
-			if (addClass.Name == null) {
-				Console.WriteLine (addClass.FullyQualifiedName);
-				return null;
+			ArrayList list = new ArrayList ();
+			lock (databases) {
+				list.AddRange (databases.Values);
 			}
-
-			string nSpace = addClass.Namespace;
-			if (nSpace == null) {
-				nSpace = String.Empty;
-			}
 			
-			string[] path = nSpace.Split('.');
-			
-			lock (namespaces) {
-				Hashtable cur                = namespaces;
-				Hashtable caseInsensitiveCur = caseInsensitiveNamespaces;
+			foreach (CodeCompletionDatabase db in list) 
+				if (!(db is AssemblyCodeCompletionDatabase))
+					db.CheckModifiedFiles ();
+		}
+		
+		void ConsumeParsingQueue ()
+		{
+			int pending;
+			do {
+				ParsingJob job = null;
+				lock (parseQueue)
+				{
+					if (parseQueue.Count > 0)
+						job = (ParsingJob) parseQueue.Dequeue ();
+				}
 				
-				for (int i = 0; i < path.Length; ++i) {
-					if (cur[path[i]] == null) {
-						Hashtable hashTable                = new Hashtable();
-						Hashtable caseInsensitivehashTable = new Hashtable();
-						cur[path[i]] = hashTable;
-						caseInsensitiveCur[path[i].ToLower()] = caseInsensitivehashTable;
-						caseInsensitivehashTable[CaseInsensitiveKey] = hashTable;
-					} else {
-						if (!(cur[path[i]] is Hashtable)) {
-							return null;
+				if (job != null)
+					job.ParseCallback (job.Data);
+				
+				lock (parseQueue)
+					pending = parseQueue.Count;
+				
+			}
+			while (pending > 0);
+		}
+		
+		
+		void ParseCurrentFile()
+		{
+			try {
+				IWorkbenchWindow win = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow;
+				if (win == null || win.ActiveViewContent == null) return;
+				
+				IEditable editable = win.ActiveViewContent as IEditable;
+				if (editable == null) return;
+				
+				string fileName = null;
+				
+				IViewContent viewContent = win.ViewContent;
+				IParseableContent parseableContent = win.ActiveViewContent as IParseableContent;
+				
+				if (parseableContent != null) {
+					fileName = parseableContent.ParseableContentName;
+				} else {
+					fileName = viewContent.IsUntitled ? viewContent.UntitledName : viewContent.ContentName;
+				}
+				
+				if (fileName == null || fileName.Length == 0) return;
+				
+				string text = editable.Text;
+				if (text == null) return;
+					
+				IParseInformation parseInformation = null;
+				bool updated = false;
+				lock (parsings) {
+				
+					if (lastUpdateSize[fileName] == null || (int)lastUpdateSize[fileName] != text.GetHashCode()) {
+						parseInformation = DoParseFile(fileName, text);
+						if (parseInformation == null) return;
+						
+						ProjectCodeCompletionDatabase db = GetProjectDatabase (viewContent.Project);
+						if (db != null) {
+							ICompilationUnit cu = (ICompilationUnit)parseInformation.BestCompilationUnit;
+							ClassUpdateInformation res = db.UpdateClassInformation (cu.Classes, fileName);
+							NotifyParseInfoChange (fileName, res);
 						}
+						lastUpdateSize[fileName] = text.GetHashCode();
+						updated = true;
 					}
-					cur = (Hashtable)cur[path[i]];
-					caseInsensitiveCur = (Hashtable)caseInsensitiveCur[path[i].ToLower()];
 				}
-				caseInsensitiveCur[addClass.Name.ToLower()] = cur[addClass.Name] = addClass;
-				return cur;
+				if (updated && parseInformation != null && editable is IParseInformationListener) {
+					((IParseInformationListener)editable).ParseInformationUpdated(parseInformation);
+				}
+			} catch (Exception e) {
+				try {
+					Console.WriteLine(e.ToString());
+				} catch {}
 			}
 		}
 		
+		
 #region Default Parser Layer dependent functions
-		public IClass GetClass(string typeName)
+
+		public IClass GetClass (IProject project, string typeName)
 		{
-			return GetClass(typeName, true);
+			return GetClass(project, typeName, true);
 		}
-		public IClass GetClass(string typeName, bool caseSensitive)
+		
+		public IClass GetClass (IProject project, string typeName, bool caseSensitive)
 		{
-			if (!caseSensitive) {
-				typeName = typeName.ToLower();
-			}
-			
-			ClasstableEntry entry = (caseSensitive ? classes[typeName] : caseInsensitiveClasses[typeName]) as ClasstableEntry;
-			if (entry != null) {
-				return entry.Class;
-			}
-			
-			// try to load the class from our data file
-			int idx = classProxies.IndexOf(typeName, caseSensitive);
-			if (idx > 0) {
-				BinaryReader reader = new BinaryReader(new BufferedStream(new FileStream(codeCompletionMainFile, FileMode.Open, FileAccess.Read, FileShare.Read)));
-				reader.BaseStream.Seek(classProxies[idx].Offset, SeekOrigin.Begin);
-				IClass c = new PersistentClass(reader, classProxies);
-				reader.Close();
-				lock (classes) {
-					caseInsensitiveClasses[typeName.ToLower()] = classes[typeName] = new ClasstableEntry(null, null, c);
+			CodeCompletionDatabase db = GetProjectDatabase (project);
+			IClass c;
+			if (db != null) {
+				c = db.GetClass (typeName, caseSensitive);
+				if (c != null) return c;
+				foreach (ReferenceEntry re in db.References)
+				{
+					CodeCompletionDatabase cdb = GetDatabase (re.Uri);
+					if (cdb == null) continue;
+					c = cdb.GetClass (typeName, caseSensitive);
+					if (c != null) return c;
 				}
-				return c;
 			}
-			return null;
+			db = GetDatabase (CoreDB);
+			return db.GetClass (typeName, caseSensitive);
 		}
 		
-		public string[] GetNamespaceList(string subNameSpace)
+		public string[] GetNamespaceList (IProject project, string subNameSpace)
 		{
-			return GetNamespaceList(subNameSpace, true);
+			return GetNamespaceList (project, subNameSpace, true);
 		}
-		public string[] GetNamespaceList(string subNameSpace, bool caseSensitive)
+		
+		public string[] GetNamespaceList (IProject project, string subNameSpace, bool caseSensitive)
 		{
-//			Console.WriteLine("GetNamespaceList >{0}<", subNameSpace);
+			ArrayList contents = new ArrayList ();
 			
-			System.Diagnostics.Debug.Assert(subNameSpace != null);
-			if (!caseSensitive) {
-				subNameSpace = subNameSpace.ToLower();
+			CodeCompletionDatabase db = GetProjectDatabase (project);
+			if (db != null) {
+				db.GetNamespaceList (contents, subNameSpace, caseSensitive);
+				foreach (ReferenceEntry re in db.References)
+				{
+					CodeCompletionDatabase cdb = GetDatabase (re.Uri);
+					if (cdb == null) continue;
+					cdb.GetNamespaceList (contents, subNameSpace, caseSensitive);
+				}
 			}
 			
-			string[] path = subNameSpace.Split('.');
-			Hashtable cur = caseSensitive ? namespaces : caseInsensitiveNamespaces;
+			db = GetDatabase (CoreDB);
+			db.GetNamespaceList (contents, subNameSpace, caseSensitive);
 			
-			if (subNameSpace.Length > 0) {
-				for (int i = 0; i < path.Length; ++i) {
-					if (!(cur[path[i]] is Hashtable)) {
-						return null;
+			return (string[]) contents.ToArray (typeof(string));
+		}
+		
+		public ArrayList GetNamespaceContents (IProject project, string namspace, bool includeReferences)
+		{
+			return GetNamespaceContents (project, namspace, includeReferences, true);
+		}
+		
+		public ArrayList GetNamespaceContents (IProject project, string namspace, bool includeReferences, bool caseSensitive)
+		{
+			ArrayList contents = new ArrayList ();
+			
+			CodeCompletionDatabase db = GetProjectDatabase (project);
+			if (db != null) {
+				db.GetNamespaceContents (contents, namspace, caseSensitive);
+				if (includeReferences) {
+					foreach (ReferenceEntry re in db.References)
+					{
+						CodeCompletionDatabase cdb = GetDatabase (re.Uri);
+						if (cdb == null) continue;
+						cdb.GetNamespaceContents (contents, namspace, caseSensitive);
 					}
-					cur = (Hashtable)cur[path[i]];
 				}
 			}
 			
-			if (!caseSensitive) {
-				cur = (Hashtable)cur[CaseInsensitiveKey];
+			if (includeReferences) {
+				db = GetDatabase (CoreDB);
+				db.GetNamespaceContents (contents, namspace, caseSensitive);
 			}
 			
-			ArrayList namespaceList = new ArrayList();
-			foreach (DictionaryEntry entry in cur) {
-				if (entry.Value is Hashtable && entry.Key.ToString().Length > 0) {
-					namespaceList.Add(entry.Key);
-				}
-			}
-			
-			return (string[])namespaceList.ToArray(typeof(string));
+			return contents;
 		}
 		
-		public ArrayList GetNamespaceContents(string subNameSpace)
+		public bool NamespaceExists(IProject project, string name)
 		{
-			return GetNamespaceContents(subNameSpace, true);
+			return NamespaceExists(project, name, true);
 		}
-		public ArrayList GetNamespaceContents(string subNameSpace, bool caseSensitive)
+		
+		public bool NamespaceExists(IProject project, string name, bool caseSensitive)
 		{
-//			Console.WriteLine("GetNamespaceContents >{0}<", subNameSpace);
+			CodeCompletionDatabase db = GetProjectDatabase (project);
+			if (db != null) {
+				if (db.NamespaceExists (name, caseSensitive)) return true;
+				foreach (ReferenceEntry re in db.References)
+				{
+					CodeCompletionDatabase cdb = GetDatabase (re.Uri);
+					if (cdb == null) continue;
+					if (cdb.NamespaceExists (name, caseSensitive)) return true;
+				}
+			}
 			
-			ArrayList namespaceList = new ArrayList();
-			if (subNameSpace == null) {
-				return namespaceList;
+			db = GetDatabase (CoreDB);
+			return db.NamespaceExists (name, caseSensitive);
 			}
-			if (!caseSensitive) {
-				subNameSpace = subNameSpace.ToLower();
+
+		public string SearchNamespace(IProject project, IUsing usin, string partitialNamespaceName)
+		{
+			return SearchNamespace(project, usin, partitialNamespaceName, true);
+		}
+		
+		public string SearchNamespace(IProject project, IUsing usin, string partitialNamespaceName, bool caseSensitive)
+		{
+//			Console.WriteLine("SearchNamespace : >{0}<", partitialNamespaceName);
+			if (NamespaceExists(project, partitialNamespaceName, caseSensitive)) {
+				return partitialNamespaceName;
 			}
 			
-			string[] path = subNameSpace.Split('.');
-			Hashtable cur = caseSensitive ? namespaces : caseInsensitiveNamespaces;
-			
-			for (int i = 0; i < path.Length; ++i) {
-				if (!(cur[path[i]] is Hashtable)) {
-					return namespaceList;
+			// search for partitial namespaces
+			string declaringNamespace = (string)usin.Aliases[""];
+			if (declaringNamespace != null) {
+				while (declaringNamespace.Length > 0) {
+					if ((caseSensitive ? declaringNamespace.EndsWith(partitialNamespaceName) : declaringNamespace.ToLower().EndsWith(partitialNamespaceName.ToLower()) ) && NamespaceExists(project, declaringNamespace, caseSensitive)) {
+						return declaringNamespace;
+					}
+					int index = declaringNamespace.IndexOf('.');
+					if (index > 0) {
+						declaringNamespace = declaringNamespace.Substring(0, index);
+					} else {
+						break;
+					}
 				}
-				cur = (Hashtable)cur[path[i]];
 			}
 			
-			if (!caseSensitive) {
-				cur = (Hashtable)cur[CaseInsensitiveKey];
-			}
-			
-			foreach (DictionaryEntry entry in cur)  {
-				if (entry.Value is Hashtable) {
-					namespaceList.Add(entry.Key);
-				} else {
-					namespaceList.Add(entry.Value);
+			// Remember:
+			//     Each namespace has an own using object
+			//     The namespace name is an alias which has the key ""
+			foreach (DictionaryEntry entry in usin.Aliases) {
+				string aliasString = entry.Key.ToString();
+				if (caseSensitive ? partitialNamespaceName.StartsWith(aliasString) : partitialNamespaceName.ToLower().StartsWith(aliasString.ToLower())) {
+					if (aliasString.Length >= 0) {
+						string nsName = nsName = String.Concat(entry.Value.ToString(), partitialNamespaceName.Remove(0, aliasString.Length));
+						if (NamespaceExists (project, nsName, caseSensitive)) {
+							return nsName;
+						}
+					}
 				}
 			}
-			return namespaceList;
+			return null;
 		}
-		
-		public bool NamespaceExists(string name)
+
+		public IClass SearchType(IProject project, IUsing iusing, string partitialTypeName)
 		{
-			return NamespaceExists(name, true);
+			return SearchType(project, iusing, partitialTypeName, true);
 		}
-		public bool NamespaceExists(string name, bool caseSensitive)
+		
+		public IClass SearchType(IProject project, IUsing iusing, string partitialTypeName, bool caseSensitive)
 		{
-//			Console.WriteLine("NamespaceExists >{0}<", name);
-			if (name == null) {
-				return false;
+//			Console.WriteLine("Search type : >{0}<", partitialTypeName);
+			IClass c = GetClass(project, partitialTypeName, caseSensitive);
+			if (c != null) {
+				return c;
 			}
-			if (!caseSensitive) {
-				name = name.ToLower();
+			
+			foreach (string str in iusing.Usings) {
+				string possibleType = String.Concat(str, ".", partitialTypeName);
+//				Console.WriteLine("looking for " + possibleType);
+				c = GetClass(project, possibleType, caseSensitive);
+				if (c != null) {
+//					Console.WriteLine("Found!");
+					return c;
+				}
 			}
-			string[] path = name.Split('.');
-			Hashtable cur = caseSensitive ? namespaces : caseInsensitiveNamespaces;
 			
-			for (int i = 0; i < path.Length; ++i) {
-				if (!(cur[path[i]] is Hashtable)) {
-					return false;
+			// search class in partitial namespaces
+			string declaringNamespace = (string)iusing.Aliases[""];
+			if (declaringNamespace != null) {
+				while (declaringNamespace.Length > 0) {
+					string className = String.Concat(declaringNamespace, ".", partitialTypeName);
+//					Console.WriteLine("looking for " + className);
+					c = GetClass(project, className, caseSensitive);
+					if (c != null) {
+//						Console.WriteLine("Found!");
+						return c;
+					}
+					int index = declaringNamespace.IndexOf('.');
+					if (index > 0) {
+						declaringNamespace = declaringNamespace.Substring(0, index);
+					} else {
+						break;
+					}
 				}
-				cur = (Hashtable)cur[path[i]];
 			}
-			return true;
+			
+			foreach (DictionaryEntry entry in iusing.Aliases) {
+				string aliasString = entry.Key.ToString();
+				if (caseSensitive ? partitialTypeName.StartsWith(aliasString) : partitialTypeName.ToLower().StartsWith(aliasString.ToLower())) {
+					string className = null;
+					if (aliasString.Length > 0) {
+						className = String.Concat(entry.Value.ToString(), partitialTypeName.Remove(0, aliasString.Length));
+//						Console.WriteLine("looking for " + className);
+						c = GetClass(project, className, caseSensitive);
+						if (c != null) {
+//							Console.WriteLine("Found!");
+							return c;
+						}
+					}
+				}
+			}
+			
+			return null;
 		}
+		
+		public IEnumerable GetClassInheritanceTree (IProject project, IClass cls)
+		{
+			return new ClassInheritanceEnumerator (this, project, cls);
+		}
+		
 #endregion
 		
 		public IParseInformation ParseFile(string fileName)
@@ -622,8 +765,14 @@
 			return ParseFile(fileName, null);
 		}
 		
-		public IParseInformation ParseFile(string fileName, string fileContent)
+		public IParseInformation ParseFile (string fileName, string fileContent)
 		{
+			return DoParseFile (fileName, fileContent);
+		}
+		
+		public IParseInformation DoParseFile (string fileName, string fileContent)
+		{
+			Console.WriteLine ("PARSING " + fileName);
 			IParser parser = GetParser(fileName);
 			
 			if (parser == null) {
@@ -652,26 +801,14 @@
 				parserOutput = parser.Parse(fileName);
 			}
 			
-			ParseInformation parseInformation = parsings[fileName] as ParseInformation;
+			ParseInformation parseInformation = GetCachedParseInformation (fileName);
+			bool newInfo = false;
 			
-			int itemsAdded = 0;
-			int itemsRemoved = 0;
-			
 			if (parseInformation == null) {
 				parseInformation = new ParseInformation();
-			} else {
-				itemsAdded = GetAddedItems(
-				                           (ICompilationUnit)parseInformation.MostRecentCompilationUnit,
-				                           (ICompilationUnit)parserOutput,
-				                           (ICompilationUnit)addedParseInformation.DirtyCompilationUnit
-				                           );
-				
-				itemsRemoved = GetRemovedItems(
-				                               (ICompilationUnit)parseInformation.MostRecentCompilationUnit,
-				                               (ICompilationUnit)parserOutput,
-				                               (ICompilationUnit)removedParseInformation.DirtyCompilationUnit
-				                               );
+				newInfo = true;
 			}
+			
 			if (parserOutput.ErrorsDuringCompile) {
 				parseInformation.DirtyCompilationUnit = parserOutput;
 			} else {
@@ -679,43 +816,51 @@
 				parseInformation.DirtyCompilationUnit = null;
 			}
 			
-			parsings[fileName] = parseInformation;
-			
-			if (parseInformation.BestCompilationUnit is ICompilationUnit) {
-				ICompilationUnit cu = (ICompilationUnit)parseInformation.BestCompilationUnit;
-				foreach (IClass c in cu.Classes) {
-					AddClassToNamespaceList(c);
-					lock (classes) {
-						caseInsensitiveClasses[c.FullyQualifiedName.ToLower()] = classes[c.FullyQualifiedName] = new ClasstableEntry(fileName, cu, c);
-					}
-				}
-			} else {
-//				Console.WriteLine("SKIP!");
+			if (newInfo) {
+				AddToCache (parseInformation, fileName);
 			}
 			
-			OnParseInformationChanged(new ParseInformationEventArgs(fileName, parseInformation));
-			
-			if (itemsRemoved > 0) {
-				OnParseInformationRemoved (new ParseInformationEventArgs (fileName, removedParseInformation));
-			}
-			if(itemsAdded > 0) {
-				OnParseInformationAdded(new ParseInformationEventArgs(fileName, addedParseInformation));
-			}
-			//if(itemsRemoved > 0) {
-			//	OnParseInformationRemoved(new ParseInformationEventArgs(fileName, removedParseInformation));
-			//}
+			OnParseInformationChanged (new ParseInformationEventArgs (fileName, parseInformation));
 			return parseInformation;
 		}
 		
-		void RemoveClasses(ICompilationUnit cu)
+		ParseInformation GetCachedParseInformation (string fileName)
 		{
-			if (cu != null) {
-				lock (classes) {
-					foreach (IClass c in cu.Classes) {
-							classes.Remove(c.FullyQualifiedName);
-							caseInsensitiveClasses.Remove(c.FullyQualifiedName.ToLower());
+			lock (parsings) 
+			{
+				ParsingCacheEntry en = parsings [fileName] as ParsingCacheEntry;
+				if (en != null) {
+					en.AccessTime = DateTime.Now;
+					return en.ParseInformation;
+				}
+				else
+					return null;
+			}
+		}
+		
+		void AddToCache (ParseInformation info, string fileName)
+		{
+			lock (parsings) 
+			{
+				if (parsings.Count >= MAX_CACHE_SIZE)
+				{
+					DateTime tim = DateTime.MaxValue;
+					string toDelete = null;
+					foreach (DictionaryEntry pce in parsings)
+					{
+						DateTime ptim = ((ParsingCacheEntry)pce.Value).AccessTime;
+						if (ptim < tim) {
+							tim = ptim;
+							toDelete = pce.Key.ToString();
+						}
 					}
+					parsings.Remove (toDelete);
 				}
+				
+				ParsingCacheEntry en = new ParsingCacheEntry();
+				en.ParseInformation = info;
+				en.AccessTime = DateTime.Now;
+				parsings [fileName] = en;
 			}
 		}
 
@@ -724,11 +869,10 @@
 			if (fileName == null || fileName.Length == 0) {
 				return null;
 			}
-			object cu = parsings[fileName];
-			if (cu == null) {
-				return ParseFile(fileName);
-			}
-			return (IParseInformation)cu;
+			
+			IParseInformation info = GetCachedParseInformation (fileName);
+			if (info != null) return info;
+			else return ParseFile(fileName);
 		}
 		
 		public IExpressionFinder GetExpressionFinder(string fileName)
@@ -753,38 +897,13 @@
 			return null;
 		}
 		
-		int GetAddedItems(ICompilationUnit original, ICompilationUnit changed, ICompilationUnit result)
-		{
-			int count = 0;
-			//result.LookUpTable.Clear();
-			//result.Usings.Clear();
-			//result.Attributes.Clear();
-			result.Classes.Clear();
-			//result.MiscComments.Clear();
-			//result.DokuComments.Clear();
-			//result.TagComments.Clear();
-			
-			//count += DiffUtility.GetAddedItems(original.LookUpTable,  changed.LookUpTable,  result.LookUpTable);
-			//count += DiffUtility.GetAddedItems(original.Usings,       changed.Usings,       result.Usings);
-			//count += DiffUtility.GetAddedItems(original.Attributes,   changed.Attributes,   result.Attributes);
-			count += DiffUtility.GetAddedItems(original.Classes,      changed.Classes,      result.Classes);
-			//count += DiffUtility.GetAddedItems(original.MiscComments, changed.MiscComments, result.MiscComments);
-			//count += DiffUtility.GetAddedItems(original.DokuComments, changed.DokuComments, result.DokuComments);
-			//count += DiffUtility.GetAddedItems(original.TagComments,  changed.TagComments,  result.TagComments);
-			return count;
-		}
-		
-		int GetRemovedItems(ICompilationUnit original, ICompilationUnit changed, ICompilationUnit result) {
-			return GetAddedItems(changed, original, result);
-		}
-		
 		////////////////////////////////////
 		
-		public ArrayList CtrlSpace(IParserService parserService, int caretLine, int caretColumn, string fileName)
+		public ArrayList CtrlSpace(IParserService parserService, IProject project, int caretLine, int caretColumn, string fileName)
 		{
 			IParser parser = GetParser(fileName);
 			if (parser != null) {
-				return parser.CtrlSpace(parserService, caretLine, caretColumn, fileName);
+				return parser.CtrlSpace(parserService, project, caretLine, caretColumn, fileName);
 			}
 			return null;
 		}
@@ -802,7 +921,8 @@
 			}
 		}
 		
-		public ResolveResult Resolve(string expression,
+		public ResolveResult Resolve(IProject project,
+									 string expression, 
 		                             int caretLineNumber,
 		                             int caretColumn,
 		                             string fileName,
@@ -814,14 +934,22 @@
 				IParser parser = GetParser(fileName);
 				//Console.WriteLine("Parse info : " + GetParseInformation(fileName).MostRecentCompilationUnit.Tag);
 				if (parser != null) {
-					return parser.Resolve(this, expression, caretLineNumber, caretColumn, fileName, fileContent);
+					return parser.Resolve(this, project, expression, caretLineNumber, caretColumn, fileName, fileContent);
 				}
 				return null;
 			} catch {
 				return null;
 			}
 		}
+		
+		internal INameEncoder DefaultNameEncoder {
+			get { return nameTable; }
+		}
 
+		internal INameDecoder DefaultNameDecoder {
+			get { return nameTable; }
+		}
+		
 		public string MonodocResolver (string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent)
 		{
 			try {
@@ -834,20 +962,13 @@
 				return null;
 			}
 		}
-
-		protected void OnParseInformationAdded(ParseInformationEventArgs e)
+		
+		public void NotifyParseInfoChange (string file, ClassUpdateInformation res)
 		{
-			if (ParseInformationAdded != null) {
-				ParseInformationAdded(this, e);
-			}
+			ClassInformationEventArgs args = new ClassInformationEventArgs (file, res);
+			OnClassInformationChanged (args);
 		}
 
-		protected void OnParseInformationRemoved(ParseInformationEventArgs e)
-		{
-			if (ParseInformationRemoved != null) {
-				ParseInformationRemoved(this, e);
-			}
-		}
 		protected virtual void OnParseInformationChanged(ParseInformationEventArgs e)
 		{
 			if (ParseInformationChanged != null) {
@@ -855,9 +976,15 @@
 			}
 		}
 		
-		public event ParseInformationEventHandler ParseInformationAdded;
-		public event ParseInformationEventHandler ParseInformationRemoved;
+		protected virtual void OnClassInformationChanged(ClassInformationEventArgs e)
+		{
+			if (ClassInformationChanged != null) {
+				ClassInformationChanged(this, e);
+			}
+		}
+		
 		public event ParseInformationEventHandler ParseInformationChanged;
+		public event ClassInformationEventHandler ClassInformationChanged;
 	}
 	
 	[Serializable]
@@ -885,4 +1012,104 @@
 			}
 		}
 	}
+	
+	public class ClassInheritanceEnumerator : IEnumerator, IEnumerable
+	{
+		IParserService parserService;
+		IClass topLevelClass;
+		IClass currentClass  = null;
+		Queue  baseTypeQueue = new Queue();
+		IProject project;
+
+		public ClassInheritanceEnumerator(IParserService parserService, IProject project, IClass topLevelClass)
+		{
+			this.parserService = parserService;
+			this.project = project;
+			this.topLevelClass = topLevelClass;
+			baseTypeQueue.Enqueue(topLevelClass.FullyQualifiedName);
+			PutBaseClassesOnStack(topLevelClass);
+			baseTypeQueue.Enqueue("System.Object");
+		}
+		public IEnumerator GetEnumerator()
+		{
+			return this;
+		}
+
+		void PutBaseClassesOnStack(IClass c)
+		{
+			foreach (string baseTypeName in c.BaseTypes) {
+				baseTypeQueue.Enqueue(baseTypeName);
+			}
+		}
+
+		public IClass Current {
+			get {
+				return currentClass;
+			}
+		}
+
+		object IEnumerator.Current {
+			get {
+				return currentClass;
+			}
+		}
+
+		public bool MoveNext()
+		{
+			if (baseTypeQueue.Count == 0) {
+				return false;
+			}
+			string baseTypeName = baseTypeQueue.Dequeue().ToString();
+
+			IClass baseType = parserService.GetClass(project, baseTypeName);
+			if (baseType == null) {
+				ICompilationUnit unit = currentClass == null ? null : currentClass.CompilationUnit;
+				if (unit != null) {
+					foreach (IUsing u in unit.Usings) {
+						baseType = parserService.SearchType(project, u, baseTypeName);
+						if (baseType != null) {
+							break;
+						}
+					}
+				}
+			}
+
+			if (baseType != null) {
+				currentClass = baseType;
+				PutBaseClassesOnStack(currentClass);
+			}
+
+			return baseType != null;
+		}
+
+		public void Reset()
+		{
+			baseTypeQueue.Clear();
+			baseTypeQueue.Enqueue(topLevelClass.FullyQualifiedName);
+			PutBaseClassesOnStack(topLevelClass);
+			baseTypeQueue.Enqueue("System.Object");
+		}
+	}	
+	
+	public class ClassUpdateInformation
+	{
+		ClassCollection added = new ClassCollection ();
+		ClassCollection removed = new ClassCollection ();
+		ClassCollection modified = new ClassCollection ();
+		
+		public ClassCollection Added
+		{
+			get { return added; }
+		}
+		
+		public ClassCollection Removed
+		{
+			get { return removed; }
+		}
+		
+		public ClassCollection Modified
+		{
+			get { return modified; }
+		}
+	}
 }
Index: Main/Base/Services/ParserService/AssemblyInformation.cs
===================================================================
--- Main/Base/Services/ParserService/AssemblyInformation.cs	(revision 1623)
+++ Main/Base/Services/ParserService/AssemblyInformation.cs	(working copy)
@@ -31,6 +31,7 @@
 	public class AssemblyInformation : MarshalByRefObject
 	{
 		ClassCollection classes = new ClassCollection();
+		string fileName;
 		
 		/// <value>
 		/// A <code>ClassColection</code> that contains all loaded classes.
@@ -41,6 +42,11 @@
 			}
 		}
 		
+		public string FileName
+		{
+			get { return fileName; }
+		}
+		
 		public AssemblyInformation()
 		{
 		}
@@ -97,6 +103,9 @@
 			//FIXME: Re-enable this code when the mono bug goes away, 0.32
 			//hopefully
 			//System.Reflection.Assembly asm = nonLocking ? Assembly.Load(GetBytes(fileName)) : Assembly.LoadFrom(fileName);
+			
+			this.fileName = fileName;
+			
 			Assembly asm = null;		
 			try {
 				asm = Assembly.LoadFrom (fileName);
Index: Main/Base/Services/ParserService/IParserService.cs
===================================================================
--- Main/Base/Services/ParserService/IParserService.cs	(revision 1623)
+++ Main/Base/Services/ParserService/IParserService.cs	(working copy)
@@ -48,34 +48,40 @@
 		IExpressionFinder GetExpressionFinder(string fileName);
 		
 		// Default Parser Layer dependent functions
-		IClass    GetClass(string typeName);
-		string[]  GetNamespaceList(string subNameSpace);
-		ArrayList GetNamespaceContents(string subNameSpace);
-		bool      NamespaceExists(string name);
+		IClass    GetClass(IProject project, string typeName);
+		string[]  GetNamespaceList(IProject project, string subNameSpace);
+		ArrayList GetNamespaceContents(IProject project, string subNameSpace, bool includeReferences);
+		bool      NamespaceExists(IProject project, string name);
+		string    SearchNamespace(IProject project, IUsing iusing, string partitialNamespaceName);
+		IClass    SearchType(IProject project, IUsing iusing, string partitialTypeName);
 		
-		IClass    GetClass(string typeName, bool caseSensitive);
-		string[]  GetNamespaceList(string subNameSpace, bool caseSensitive);
-		ArrayList GetNamespaceContents(string subNameSpace, bool caseSensitive);
-		bool      NamespaceExists(string name, bool caseSensitive);
+		IClass    GetClass(IProject project, string typeName, bool caseSensitive);
+		string[]  GetNamespaceList(IProject project, string subNameSpace, bool caseSensitive);
+		ArrayList GetNamespaceContents(IProject project, string subNameSpace, bool includeReferences, bool caseSensitive);
+		bool      NamespaceExists(IProject project, string name, bool caseSensitive);
+		string    SearchNamespace(IProject project, IUsing iusing, string partitialNamespaceName, bool caseSensitive);
+		IClass    SearchType(IProject project, IUsing iusing, string partitialTypeName, bool caseSensitive);
+		
+		IEnumerable GetClassInheritanceTree (IProject project, IClass cls);
+		
 		////////////////////////////////////////////
 
 		/// <summary>
 		/// Resolves an expression.
 		/// The caretLineNumber and caretColumn is 1 based.
 		/// </summary>
-		ResolveResult Resolve(string expression,
+		ResolveResult Resolve(IProject project,
+							  string expression,
 		                      int caretLineNumber,
 		                      int caretColumn,
 		                      string fileName,
 		                      string fileContent);
 		string MonodocResolver (string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent);
 		ArrayList IsAsResolve (string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent);
-		ArrayList CtrlSpace(IParserService parserService, int caretLine, int caretColumn, string fileName);
-		void AddReferenceToCompletionLookup(IProject project, ProjectReference reference);
+		ArrayList CtrlSpace(IParserService parserService, IProject project, int caretLine, int caretColumn, string fileName);
 		string LoadAssemblyFromGac (string name);
 
-		event ParseInformationEventHandler ParseInformationAdded;
-		event ParseInformationEventHandler ParseInformationRemoved;
 		event ParseInformationEventHandler ParseInformationChanged;
+		event ClassInformationEventHandler ClassInformationChanged;
 	}
 }
Index: Main/Base/Services/ParserService/CodeCompletionDatabase.cs
===================================================================
--- Main/Base/Services/ParserService/CodeCompletionDatabase.cs	(revision 0)
+++ Main/Base/Services/ParserService/CodeCompletionDatabase.cs	(revision 0)
@@ -0,0 +1,1011 @@
+// <file>
+//     <copyright see="prj:///doc/copyright.txt"/>
+//     <license see="prj:///doc/license.txt"/>
+//     <owner name="Lluis Sanchez Gual" email="lluis@ximian.com"/>
+//     <version value="$version"/>
+// </file>
+
+using System;
+using System.Diagnostics;
+using System.Threading;
+using System.IO;
+using System.Collections;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+
+using MonoDevelop.Core.Properties;
+using MonoDevelop.Core.Services;
+using MonoDevelop.Services;
+using MonoDevelop.Core.AddIns;
+using MonoDevelop.Internal.Project;
+using MonoDevelop.Gui;
+using MonoDevelop.Internal.Parser;
+using System.Reflection;
+
+namespace MonoDevelop.Services
+{
+	internal class CodeCompletionDatabase
+	{
+		static readonly int MAX_ACTIVE_COUNT = 100;
+		static readonly int MIN_ACTIVE_COUNT = 50;
+		static readonly int FORMAT_VERSION = 2;
+		
+		NamespaceEntry rootNamespace;
+		protected ArrayList references;
+		protected Hashtable files;
+		protected DefaultParserService parserService;
+		protected Hashtable headers;
+		
+		BinaryReader datareader;
+		FileStream datafile;
+		int currentGetTime = 0;
+		bool modified;
+		
+		string basePath;
+		string dataFile;
+		
+		protected Object rwlock = new Object ();
+		
+		public CodeCompletionDatabase (DefaultParserService parserService)
+		{
+			this.parserService = parserService;
+			rootNamespace = new NamespaceEntry ();
+			files = new Hashtable ();
+			references = new ArrayList ();
+			headers = new Hashtable ();
+		}
+		
+		protected void SetLocation (string basePath, string name)
+		{
+			dataFile = Path.Combine (basePath, name + ".pidb");
+			this.basePath = basePath;
+		}
+		
+		public void Rename (string name)
+		{
+			lock (rwlock)
+			{
+				Flush ();
+				string oldDataFile = dataFile;
+				dataFile = Path.Combine (basePath, name + ".pidb");
+
+				CloseReader ();
+				
+				if (File.Exists (oldDataFile))
+					File.Move (oldDataFile, dataFile);
+			}
+		}
+		
+		public virtual void Read ()
+		{
+			if (basePath == null)
+				throw new InvalidOperationException ("Location not set");
+				
+			if (!File.Exists (dataFile)) return;
+			
+			lock (rwlock)
+			{
+				FileStream ifile = null;
+				try 
+				{
+					modified = false;
+					currentGetTime = 0;
+					CloseReader ();
+					
+					Console.WriteLine ("Reading " + dataFile);
+					ifile = new FileStream (dataFile, FileMode.Open, FileAccess.Read, FileShare.Read);
+					BinaryFormatter bf = new BinaryFormatter ();
+					
+					// Read the headers
+					headers = (Hashtable) bf.Deserialize (ifile);
+					int ver = (int) headers["Version"];
+					if (ver != FORMAT_VERSION)
+						throw new Exception ("Expected version " + FORMAT_VERSION + ", found version " + ver);
+					
+					// Move to the index offset and read the index
+					BinaryReader br = new BinaryReader (ifile);
+					long indexOffset = br.ReadInt64 ();
+					ifile.Position = indexOffset;
+					
+					object[] data = (object[]) bf.Deserialize (ifile);
+					ifile.Close ();
+					
+					references = (ArrayList) data[0];
+					rootNamespace = (NamespaceEntry) data[1];
+					files = (Hashtable) data[2];
+				}
+				catch (Exception ex)
+				{
+					if (ifile != null) ifile.Close ();
+					Console.WriteLine ("PIDB file '" + dataFile + "' couldn not be loaded: '" + ex.Message + "'. The file will be recreated");
+					rootNamespace = new NamespaceEntry ();
+					files = new Hashtable ();
+					references = new ArrayList ();
+					headers = new Hashtable ();
+				}
+			}
+		}
+		
+		public static Hashtable ReadHeaders (string baseDir, string name)
+		{
+			string file = Path.Combine (baseDir, name + ".pidb");
+			FileStream ifile = new FileStream (file, FileMode.Open, FileAccess.Read, FileShare.Read);
+			BinaryFormatter bf = new BinaryFormatter ();
+			Hashtable headers = (Hashtable) bf.Deserialize (ifile);
+			ifile.Close ();
+			return headers;
+		}
+		
+		public void Write ()
+		{
+			lock (rwlock)
+			{
+				if (!modified) return;
+				modified = false;
+				headers["Version"] = FORMAT_VERSION;
+							
+				Console.WriteLine ("Writing " + dataFile);
+				
+				string tmpDataFile = dataFile + ".tmp";
+				FileStream dfile = new FileStream (tmpDataFile, FileMode.Create, FileAccess.Write, FileShare.Write);
+				
+				BinaryFormatter bf = new BinaryFormatter ();
+				BinaryWriter bw = new BinaryWriter (dfile);
+				
+				// The headers are the first thing to write, so they can be read
+				// without deserializing the whole file.
+				bf.Serialize (dfile, headers);
+				
+				// The position of the index will be written here
+				long indexOffsetPos = dfile.Position;
+				bw.Write ((long)0);
+				
+				// Write all class data
+				foreach (FileEntry fe in files.Values) 
+				{
+					ClassEntry ce = fe.FirstClass;
+					while (ce != null)
+					{
+						IClass c = ce.Class;
+						if (c == null)
+							c = ReadClass (ce);
+							
+						ce.Position = dfile.Position;
+						PersistentClass.WriteTo (c, bw, parserService.DefaultNameEncoder);
+						ce = ce.NextInFile;
+					}
+				}
+				
+				// Write the index
+				long indexOffset = dfile.Position;
+				object[] data = new object[] { references, rootNamespace, files };
+				bf.Serialize (dfile, data);
+				
+				dfile.Position = indexOffsetPos;
+				bw.Write (indexOffset);
+				
+				bw.Close ();
+				dfile.Close ();
+				
+				CloseReader ();
+				
+				if (File.Exists (dataFile))
+					File.Delete (dataFile);
+					
+				File.Move (tmpDataFile, dataFile);
+				
+				Console.WriteLine ("Done Writing " + tmpDataFile);
+			}
+		}
+		
+		void Flush ()
+		{
+			int activeCount = 0;
+			
+			foreach (FileEntry fe in files.Values) {
+				ClassEntry ce = fe.FirstClass;
+				while (ce != null) { 
+					if (ce.Class != null) activeCount++;
+					ce = ce.NextInFile;
+				}
+			}
+			
+			if (activeCount <= MAX_ACTIVE_COUNT) return;
+			
+			Write ();
+			
+			foreach (FileEntry fe in files.Values) {
+				ClassEntry ce = fe.FirstClass;
+				while (ce != null) { 
+					if (ce.LastGetTime < currentGetTime - MIN_ACTIVE_COUNT)
+						ce.Class = null;
+					ce = ce.NextInFile;
+				}
+			}
+		}
+		
+		IClass ReadClass (ClassEntry ce)
+		{
+			if (datareader == null) {
+				datafile = new FileStream (dataFile, FileMode.Open, FileAccess.Read, FileShare.Read);
+				datareader = new BinaryReader (datafile);
+			}
+			datafile.Position = ce.Position;
+			return PersistentClass.Read (datareader, parserService.DefaultNameDecoder);
+		}
+		
+		void CloseReader ()
+		{
+			if (datareader != null) {
+				datareader.Close ();
+				datareader = null;
+			}
+		}
+		
+		public IClass GetClass (string typeName, bool caseSensitive)
+		{
+			lock (rwlock)
+			{
+				string[] path = typeName.Split ('.');
+				int len = path.Length - 1;
+				NamespaceEntry nst = GetNamespaceEntry (path, len, false, caseSensitive);
+				if (nst == null) return null;
+	
+				ClassEntry ce = nst.GetClass (path[len], caseSensitive);
+				if (ce == null) return null;
+				return GetClass (ce);
+			}
+		}
+		
+		IClass GetClass (ClassEntry ce)
+		{
+			ce.LastGetTime = currentGetTime++;
+			if (ce.Class != null) return ce.Class;
+			
+			// Read the class from the file
+			
+			ce.Class = ReadClass (ce);
+			return ce.Class;
+		}		
+		
+		public void CheckModifiedFiles ()
+		{
+			lock (rwlock)
+			{
+				foreach (FileEntry file in files.Values)
+				{
+					if (!File.Exists (file.FileName)) continue;
+					FileInfo fi = new FileInfo (file.FileName);
+					if (fi.LastWriteTime > file.LastParseTime) 
+					{
+						// Change date now, to avoid reparsing if CheckModifiedFiles is called again
+						// before the parse job is executed
+						
+						file.LastParseTime = fi.LastWriteTime;
+						parserService.QueueParseJob (new WaitCallback (ParseCallback), file.FileName);
+					}
+				}
+			}
+		}
+		
+		void ParseCallback (object ob)
+		{
+			lock (rwlock)
+			{
+				ParseFile ((string)ob);
+			}
+		}
+		
+		protected virtual void ParseFile (string fileName)
+		{
+		}
+		
+		public void ParseAll ()
+		{
+			lock (rwlock)
+			{
+				foreach (FileEntry fe in files.Values) 
+					ParseFile (fe.FileName);
+			}
+		}
+		
+		protected void AddReference (string uri)
+		{
+			Console.WriteLine ("AddReference " + uri);
+			lock (rwlock)
+			{
+				ReferenceEntry re = new ReferenceEntry (uri);
+				references.Add (re);
+				modified = true;
+			}
+		}
+		
+		protected void RemoveReference (string uri)
+		{
+			Console.WriteLine ("RemoveReference " + uri);
+			lock (rwlock)
+			{
+				for (int n=0; n<references.Count; n++)
+				{
+					if (((ReferenceEntry)references[n]).Uri == uri) {
+						references.RemoveAt (n);
+						modified = true;
+						return;
+					}
+				}
+			}
+		}
+		
+		public void AddFile (string fileName)
+		{
+			lock (rwlock)
+			{
+				FileEntry fe = new FileEntry (fileName);
+				files [fileName] = fe;
+				modified = true;
+			}
+		}
+		
+		public void RemoveFile (string fileName)
+		{
+			lock (rwlock)
+			{
+				FileEntry fe = files [fileName] as FileEntry;
+				if (fe == null) return;
+				
+				ClassEntry ce = fe.FirstClass;
+				while (ce != null) {
+					ce.NamespaceRef.Remove (ce.Name);
+					ce = ce.NextInFile;
+				}
+				
+				files.Remove (fileName);
+				modified = true;
+			}
+		}
+		
+		protected void AddClass (IClass c, FileEntry fe)
+		{
+			lock (rwlock)
+			{
+				string[] path = c.Namespace.Split ('.');
+				NamespaceEntry nst = GetNamespaceEntry (path, path.Length, true, true);
+				ClassEntry ce = nst.GetClass (c.Name, true);
+				if (ce == null) {
+					ce = new ClassEntry (c, fe, nst);
+					nst.Add (c.Name, ce);
+				}
+				else {
+					ce.Class = CopyClass (c);
+				}
+				
+				if (ce.FileEntry != fe)
+					fe.AddClass (ce);
+	
+				ce.LastGetTime = currentGetTime++;
+				modified = true;
+			}
+		}
+			
+		public ClassUpdateInformation UpdateClassInformation (ClassCollection newClasses, string fileName)
+		{
+			lock (rwlock)
+			{
+				ClassUpdateInformation res = new ClassUpdateInformation ();
+				
+				FileEntry fe = files [fileName] as FileEntry;
+				if (fe == null) return null;
+				
+				bool[] added = new bool [newClasses.Count];
+				NamespaceEntry[] newNss = new NamespaceEntry [newClasses.Count];
+				for (int n=0; n<newClasses.Count; n++) {
+					string[] path = newClasses[n].Namespace.Split ('.');
+					newNss[n] = GetNamespaceEntry (path, path.Length, true, true);
+				}
+				
+				ArrayList newFileClasses = new ArrayList ();
+				
+				if (fe != null)
+				{
+					ClassEntry ce = fe.FirstClass;
+					while (ce != null)
+					{
+						IClass newClass = null;
+						for (int n=0; n<newClasses.Count && newClass == null; n++) {
+							IClass uc = newClasses [n];
+							if (uc.Name == ce.Name && newNss[n] == ce.NamespaceRef) {
+								newClass = uc;
+								added[n] = true;
+							}
+						}
+						
+						if (newClass != null) {
+							// Class found, replace it
+							ce.Class = CopyClass (newClass);
+							ce.LastGetTime = currentGetTime++;
+							newFileClasses.Add (ce);
+							res.Modified.Add (ce.Class);
+						}
+						else {
+							// Class not found, it has to be deleted, unless it has
+							// been added in another file
+							if (ce.FileEntry == fe) {
+								IClass c = ce.Class;
+								if (c == null) c = ReadClass (ce);
+								res.Removed.Add (c);
+								ce.NamespaceRef.Remove (ce.Name);
+							}
+						}
+						ce = ce.NextInFile;
+					}
+				}
+				
+				if (fe == null) {
+					fe = new FileEntry (fileName);
+					files [fileName] = fe;
+				}
+				
+				for (int n=0; n<newClasses.Count; n++) {
+					if (!added[n]) {
+						IClass c = CopyClass (newClasses[n]);
+						ClassEntry ce = new ClassEntry (c, fe, newNss[n]);
+						ce.LastGetTime = currentGetTime++;
+						newNss[n].Add (c.Name, ce);
+						newFileClasses.Add (ce);
+						res.Added.Add (c);
+					}
+				}
+				
+				fe.SetClasses (newFileClasses);
+				rootNamespace.Clean ();
+				fe.LastParseTime = DateTime.Now;
+				modified = true;
+				Flush ();
+				
+				return res;
+			}
+		}
+		
+		public void GetNamespaceContents (ArrayList list, string subNameSpace, bool caseSensitive)
+		{
+			lock (rwlock)
+			{
+				string[] path = subNameSpace.Split ('.');
+				NamespaceEntry tns = GetNamespaceEntry (path, path.Length, false, caseSensitive);
+				if (tns == null) return;
+				
+				foreach (DictionaryEntry en in tns.Contents) {
+					if (en.Value is NamespaceEntry)
+						list.Add (en.Key);
+					else
+						list.Add (GetClass ((ClassEntry)en.Value));
+				}
+			}
+		}
+		
+		public void GetNamespaceList (ArrayList list, string subNameSpace, bool caseSensitive)
+		{
+			lock (rwlock)
+			{
+				string[] path = subNameSpace.Split ('.');
+				NamespaceEntry tns = GetNamespaceEntry (path, path.Length, false, caseSensitive);
+				if (tns == null) return;
+				
+				foreach (DictionaryEntry en in tns.Contents) {
+					if (en.Value is NamespaceEntry)
+						list.Add (en.Key);
+				}
+			}
+		}
+		
+		public bool NamespaceExists (string name, bool caseSensitive)
+		{
+			lock (rwlock)
+			{
+				string[] path = name.Split ('.');
+				NamespaceEntry tns = GetNamespaceEntry (path, path.Length, false, caseSensitive);
+				return tns != null;
+			}
+		}
+		
+		public ICollection References
+		{
+			get { return references; }
+		}
+		
+		IClass CopyClass (IClass cls)
+		{
+			MemoryStream ms = new MemoryStream ();
+			BinaryWriter bw = new BinaryWriter (ms);
+			PersistentClass.WriteTo (cls, bw, parserService.DefaultNameEncoder);
+			bw.Flush ();
+			ms.Position = 0;
+			BinaryReader br = new BinaryReader (ms);
+			return PersistentClass.Read (br, parserService.DefaultNameDecoder);
+		}
+		
+		NamespaceEntry GetNamespaceEntry (string[] path, int length, bool createPath, bool caseSensitive)
+		{
+			NamespaceEntry nst = rootNamespace;
+
+			if (length == 0 || (length == 1 && path[0] == "")) {
+				return nst;
+			}
+			else
+			{
+				for (int n=0; n<length; n++) {
+					NamespaceEntry nh = nst.GetNamespace (path[n], caseSensitive);
+					if (nh == null) {
+						if (!createPath) return null;
+						nh = new NamespaceEntry ();
+						nst.Add (path[n], nh);
+					}
+					nst = nh;
+				}
+				return nst;
+			}
+		}
+	}
+	
+	internal class ProjectCodeCompletionDatabase: CodeCompletionDatabase
+	{
+		IProject project;
+		
+		public ProjectCodeCompletionDatabase (IProject project, DefaultParserService parserService)
+		: base (parserService)
+		{
+			SetLocation (project.BaseDirectory, project.Name);
+			
+			this.project = project;
+			Read ();
+			
+			UpdateFromProject ();
+		}
+		
+		public void UpdateFromProject ()
+		{
+			Hashtable fs = new Hashtable ();
+			foreach (ProjectFile file in project.ProjectFiles)
+			{
+				if (file.BuildAction != BuildAction.Compile) continue;
+				FileEntry fe = files[file.Name] as FileEntry;
+				if (fe == null) AddFile (file.Name);
+				fs [file.Name] = null;
+			}
+			
+			ArrayList keys = new ArrayList ();
+			keys.AddRange (files.Keys);
+			foreach (string file in keys)
+			{
+				if (!fs.Contains (file))
+					RemoveFile (file);
+			}
+			
+			fs.Clear ();
+			foreach (ProjectReference pr in project.ProjectReferences)
+			{
+				string refId = pr.ReferenceType + ":" + pr.Reference;
+				if (pr.ReferenceType == ReferenceType.Gac && refId.ToLower().EndsWith (".dll"))
+					refId = refId.Substring (0, refId.Length - 4);
+
+				fs[refId] = null;
+				bool found = false;
+				for (int n=0; n<references.Count && !found; n++) {
+					ReferenceEntry re = (ReferenceEntry) references[n];
+					found = ((ReferenceEntry) references[n]).Uri == refId;
+				}
+				if (!found)
+					AddReference (refId);
+			}
+			
+			keys.Clear();
+			keys.AddRange (references);
+			foreach (ReferenceEntry re in keys)
+			{
+				if (!fs.Contains (re.Uri))
+					RemoveReference (re.Uri);
+			}
+		}
+		
+		protected override void ParseFile (string fileName)
+		{
+			IParseInformation parserInfo = parserService.DoParseFile ((string)fileName, null);
+			ICompilationUnit cu = (ICompilationUnit)parserInfo.BestCompilationUnit;
+			ClassUpdateInformation res = UpdateClassInformation (cu.Classes, fileName);
+			parserService.NotifyParseInfoChange (fileName, res);
+		}
+	}
+	
+	internal class AssemblyCodeCompletionDatabase: CodeCompletionDatabase
+	{
+		bool useExternalProcess = true;
+		string baseDir;
+		string assemblyName;
+		
+		public AssemblyCodeCompletionDatabase (string baseDir, string assemblyName, DefaultParserService parserService)
+		: base (parserService)
+		{
+			string assemblyFile;
+			string name;
+			
+			this.assemblyName = assemblyName;
+			
+			if (assemblyName == "mscorlib") {
+				name = assemblyName;
+				assemblyFile = typeof(object).Assembly.Location;
+			}
+			else if (assemblyName.ToLower().EndsWith (".dll")) {
+				name = assemblyName.Substring (0, assemblyName.Length - 4);
+				name = name.Replace(',','_').Replace(" ","").Replace('/','_');
+				assemblyFile = assemblyName;
+			}
+			else {
+				assemblyName = GetAssemblyFullName (assemblyName);
+				name = EncodeGacAssemblyName (assemblyName);
+				assemblyFile = GetGacAssemblyLocation (assemblyName);
+			}
+			
+			this.baseDir = baseDir;
+			SetLocation (baseDir, name);
+
+			Read ();
+			
+			if (files [assemblyFile] == null) {
+				AddFile (assemblyFile);
+				headers ["CheckFile"] = assemblyFile;
+			}
+		}
+		
+		string EncodeGacAssemblyName (string assemblyName)
+		{
+			string[] assemblyPieces = assemblyName.Split(',');
+			string res = "";
+			foreach (string item in assemblyPieces) {
+				string[] pieces = item.Trim ().Split (new char[] { '=' }, 2);
+				if(pieces.Length == 1)
+					res += pieces[0];
+				else if (!(pieces[0] == "Culture" && pieces[1] != "Neutral"))
+					res += "_" + pieces[1];
+			}
+			return res;
+		}
+		
+		string GetGacAssemblyLocation (string assemblyName)
+		{
+			Assembly asm;
+			try {
+				asm = Assembly.Load (assemblyName);
+			}
+			catch {
+				asm = Assembly.LoadWithPartialName (assemblyName);
+			}
+			
+			if (asm == null)
+				throw new InvalidOperationException ("Could not find: " + assemblyName);
+
+			return asm.Location;
+		}
+		
+		public string GetAssemblyFullName (string assemblyName)
+		{
+			if (assemblyName.IndexOf (',') == -1) return assemblyName;
+			Assembly asm = Assembly.LoadWithPartialName (assemblyName);
+			return asm.GetName().FullName;
+		}
+		
+		protected override void ParseFile (string fileName)
+		{
+			if (useExternalProcess)
+			{
+				string dbgen = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "dbgen.exe");
+				Console.WriteLine ("Starting " + dbgen);
+				Process proc = Process.Start ("mono " + dbgen, "\"" + baseDir + "\" \"" + assemblyName + "\"");
+				proc.WaitForExit ();
+				Console.WriteLine ("Done " + proc.ExitCode);
+				Read ();
+			}
+			else
+			{
+				Console.WriteLine ("Parsing assembly: " + fileName);
+				AssemblyInformation ainfo = new AssemblyInformation();
+				ainfo.Load (fileName, false);
+				UpdateClassInformation (ainfo.Classes, fileName);
+			}
+		}
+		
+		public bool ParseInExternalProcess
+		{
+			get { return useExternalProcess; }
+			set { useExternalProcess = value; }
+		}
+		
+		public static void CleanDatabase (string baseDir, string name)
+		{
+			// Read the headers of the file without fully loading the database
+			Hashtable headers = ReadHeaders (baseDir, name);
+			string checkFile = (string) headers ["CheckFile"];
+			if (!File.Exists (checkFile)) {
+				string dataFile = Path.Combine (baseDir, name + ".pidb");
+				File.Delete (dataFile);
+				Console.WriteLine ("File not exists: " + checkFile);
+				Console.WriteLine ("Deleted " + dataFile);
+			}
+		}
+	}
+	
+
+	public interface INameEncoder
+	{
+		int GetStringId (string text);
+	}
+	
+	public interface INameDecoder
+	{
+		string GetStringValue (int id);
+	}
+	
+	
+	public class StringNameTable: INameEncoder, INameDecoder
+	{
+		string[] table;
+		
+		public StringNameTable (string[] names)
+		{
+			table = names;
+			Array.Sort (table);
+		}
+		
+		public string GetStringValue (int id)
+		{
+			return table [id];
+		}
+		
+		public int GetStringId (string text)
+		{
+			int i = Array.BinarySearch (table, text);
+			if (i >= 0) return i;
+			else return -1;
+		}
+	}
+	
+	[Serializable]
+	class NamespaceEntry
+	{
+		Hashtable contents = new Hashtable ();
+		
+		// This is the case insensitive version of the hashtable.
+		// It is constructed only when needed.
+		[NonSerialized] Hashtable contents_ci;
+		
+		// All methods with the caseSensitive parameter, first check for an
+		// exact match, and if not found, they try with the case insensitive table.
+		
+		public NamespaceEntry GetNamespace (string ns, bool caseSensitive)
+		{
+			NamespaceEntry ne = contents[ns] as NamespaceEntry;
+			if (ne != null || caseSensitive) return ne;
+			
+			if (contents_ci == null) BuildCaseInsensitiveTable ();
+			return contents_ci[ns] as NamespaceEntry;
+		}
+		
+		public ClassEntry GetClass (string name, bool caseSensitive)
+		{
+			ClassEntry ne = contents[name] as ClassEntry;
+			if (ne != null || caseSensitive) return ne;
+			
+			if (contents_ci == null) BuildCaseInsensitiveTable ();
+			return contents_ci[name] as ClassEntry;
+		}
+		
+		public void Add (string name, object value)
+		{
+			contents [name] = value;
+			if (contents_ci != null)
+				contents_ci [name] = value;
+		}
+		
+		public void Remove (string name)
+		{
+			contents.Remove (name);
+			contents_ci = null;
+		}
+		
+		public ICollection Contents
+		{
+			get { return contents; }
+		}
+		
+		public int ContentCount
+		{
+			get { return contents.Count; }
+		}
+		
+		public void Clean ()
+		{
+			ArrayList todel = new ArrayList ();
+			foreach (DictionaryEntry en in contents)
+			{
+				NamespaceEntry h = en.Value as NamespaceEntry;
+				if (h != null) {
+					h.Clean ();
+					if (h.ContentCount == 0) todel.Add (en.Key);
+				}
+			}
+			
+			if (todel.Count > 0)
+			{
+				contents_ci = null;
+				foreach (string key in todel)
+					contents.Remove (key);
+			}
+		}
+		
+		void BuildCaseInsensitiveTable ()
+		{
+			contents_ci = new Hashtable (CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
+			foreach (DictionaryEntry en in contents)
+				contents_ci.Add (en.Key, en.Value);
+		}
+	}
+
+	[Serializable]
+	class ClassEntry
+	{
+		long position;
+		NamespaceEntry namespaceRef;
+		string name;
+		FileEntry fileEntry;
+		ClassEntry nextInFile;
+		
+		[NonSerialized]
+		int lastGetTime;
+		
+		[NonSerialized]
+		public IClass cls;
+		
+		public ClassEntry (IClass cls, FileEntry fileEntry, NamespaceEntry namespaceRef)
+		{
+			this.cls = cls;
+			this.fileEntry = fileEntry;
+			this.namespaceRef = namespaceRef;
+			this.name = cls.Name;
+			position = -1;
+		}
+		
+		public long Position
+		{
+			get { return position; }
+			set { position = value; }
+		}
+		
+		public IClass Class
+		{
+			get { 
+				return cls; 
+			}
+			set {
+				cls = value; 
+				if (cls != null) {
+					name = cls.Name; 
+					position = -1; 
+				}
+			}
+		}
+		
+		public string Name
+		{
+			get { return name; }
+		}
+		
+		public NamespaceEntry NamespaceRef
+		{
+			get { return namespaceRef; }
+		}
+		
+		public FileEntry FileEntry
+		{
+			get { return fileEntry; }
+			set { fileEntry = value; }
+		}
+		
+		public int LastGetTime
+		{
+			get { return lastGetTime; }
+			set { lastGetTime = value; }
+		}
+		
+		public ClassEntry NextInFile
+		{
+			get { return nextInFile; }
+			set { nextInFile = value; }
+		}
+	}
+	
+	[Serializable]
+	class FileEntry
+	{
+		string filePath;
+		DateTime parseTime;
+		ClassEntry firstClass;
+		
+		public FileEntry (string path)
+		{
+			filePath = path;
+			parseTime = DateTime.MinValue;
+		}
+		
+		public string FileName
+		{
+			get { return filePath; }
+		}
+		
+		public DateTime LastParseTime
+		{
+			get { return parseTime; }
+			set { parseTime = value; }
+		}
+		
+		public ClassEntry FirstClass
+		{
+			get { return firstClass; }
+		}
+		
+		public void SetClasses (ArrayList list)
+		{
+			firstClass = null;
+			foreach (ClassEntry ce in list)
+				AddClass (ce);
+		}
+		
+		public void AddClass (ClassEntry ce)
+		{
+			if (ce.FileEntry != null)
+				ce.FileEntry.RemoveClass (ce);
+				
+			ce.NextInFile = firstClass;
+			firstClass = ce;
+		}
+		
+		public void RemoveClass (ClassEntry ce)
+		{
+			ClassEntry oldent = null;
+			ClassEntry curent = firstClass;
+			
+			while (curent != null && curent != ce) {
+				oldent = curent;
+				curent = curent.NextInFile;
+			}
+			
+			if (curent == null) 
+				return;
+			else if (oldent == null)
+				firstClass = curent.NextInFile;
+			else
+				oldent.NextInFile = curent.NextInFile;
+				
+			ce.FileEntry = null;
+		}
+		
+		public bool IsAssembly
+		{
+			get { return filePath.ToLower().EndsWith (".dll"); }
+		}
+	}
+	
+	[Serializable]
+	class ReferenceEntry
+	{
+		string databaseUri;
+		
+		public ReferenceEntry (string dbUri)
+		{
+			databaseUri = dbUri;
+		}
+		
+		public string Uri
+		{
+			get { return databaseUri; }
+		}
+	}
+}
Index: Main/Base/Makefile.am
===================================================================
--- Main/Base/Makefile.am	(revision 1623)
+++ Main/Base/Makefile.am	(working copy)
@@ -204,11 +204,13 @@
 ./Services/ClassBrowserIcons/ClassBrowserIconsService.cs \
 ./Services/ResourceNotFoundException.cs \
 ./Services/ParserService/DefaultParserService.cs \
+./Services/ParserService/CodeCompletionDatabase.cs \
 ./Services/ParserService/ClassProxyCollection.cs \
 ./Services/ParserService/IParserService.cs \
 ./Services/ParserService/ClassProxy.cs \
 ./Services/ParserService/AssemblyInformation.cs \
 ./Services/ParserService/ParseInformation.cs \
+./Services/ParserService/ClassInformationEventHandler.cs \
 ./Services/ResourceService.cs \
 ./Services/StockIcons.cs \
 ./Services/MessageService.cs \
@@ -338,10 +340,12 @@
 ./Internal/Project/Project/AbstractProjectConfiguration.cs \
 ./Internal/Project/Project/AbstractProject.cs \
 ./Internal/Project/Project/ProjectReference.cs \
+./Internal/Project/Project/ProjectReferenceEventArgs.cs \
 ./Internal/Project/Project/ConvertXml.cs \
 ./Internal/Project/Project/IncludeFilesDialog.cs \
 ./Internal/Project/Project/IConfiguration.cs \
 ./Internal/Project/Project/ProjectFile.cs \
+./Internal/Project/Project/ProjectFileEventArgs.cs \
 ./Internal/Project/Project/AbstractConfiguration.cs \
 ./Internal/Project/Project/IProject.cs \
 ./Internal/Project/Combine/Combine.cs \
@@ -350,6 +354,7 @@
 ./Internal/Project/Combine/CombineConfiguration.cs \
 ./Internal/Project/Combine/NoStartupCombineDefinedException.cs \
 ./Internal/Project/Combine/CombineEntry.cs \
+./Internal/Project/Combine/CombineEntryEventArgs.cs \
 ./Internal/Templates/FileDescriptionTemplate.cs \
 ./Internal/Templates/CodeTemplate.cs \
 ./Internal/Templates/CodeTemplateGroup.cs \

--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=project.diff
Content-Type: text/x-patch; name=project.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorView.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorView.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorView.cs	(working copy)
@@ -181,7 +181,7 @@
 
 			if (triggerIter.Equals (TextIter.Zero)) return;
 			triggerIter.ForwardChar ();
-			completionWindow = new CompletionWindow (this, ParentEditor.DisplayBinding.ContentName, new CodeCompletionDataProvider (true));
+			completionWindow = new CompletionWindow (this, ParentEditor.DisplayBinding.Project, ParentEditor.DisplayBinding.ContentName, new CodeCompletionDataProvider (true));
 			
 			completionWindow.ShowCompletionWindow (triggerChar, triggerIter, true);
 		}
@@ -304,7 +304,7 @@
 			case '.':
 				bool retval = base.OnKeyPressEvent (evnt);
 				if (EnableCodeCompletion) {
-					completionWindow = new CompletionWindow (this, ParentEditor.DisplayBinding.ContentName, new CodeCompletionDataProvider ());
+					completionWindow = new CompletionWindow (this, ParentEditor.DisplayBinding.Project, ParentEditor.DisplayBinding.ContentName, new CodeCompletionDataProvider ());
 					completionWindow.ShowCompletionWindow ((char)key, buf.GetIterAtMark (buf.InsertMark), false);
 				}
 				return retval;
Index: AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionData.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionData.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionData.cs	(working copy)
@@ -85,17 +85,6 @@
 		public string Description
 		{
 			get {
-				// get correct delegate description (when description is requested)
-				// in the classproxies aren't methods saved, therefore delegate methods
-				// must be get through the real class instead out of the proxy
-				//
-				// Mike
-				if (c is ClassProxy && c.ClassType == ClassType.Delegate) {
-					description = ambienceService.CurrentAmbience.Convert(parserService.GetClass(c.FullyQualifiedName));
-					pango_description = PangoAmbience.Convert(parserService.GetClass(c.FullyQualifiedName));
-					c = null;
-				}
-				
 				// don't give a description string, if no documentation or description is provided
 				if (description.Length + documentation.Length == 0) {
 					return null;
@@ -124,17 +113,6 @@
 		public string DescriptionPango
 		{
 			get {
-				// get correct delegate description (when description is requested)
-				// in the classproxies aren't methods saved, therefore delegate methods
-				// must be get through the real class instead out of the proxy
-				//
-				// Mike
-				if (c is ClassProxy && c.ClassType == ClassType.Delegate) {
-					description = ambienceService.CurrentAmbience.Convert(parserService.GetClass(c.FullyQualifiedName));
-					pango_description = PangoAmbience.Convert(parserService.GetClass(c.FullyQualifiedName));
-					c = null;
-				}
-				
 				// don't give a description string, if no documentation or description is provided
 				if (description.Length + documentation.Length == 0) {
 					return null;
Index: AddIns/DisplayBindings/SourceEditor/CodeCompletion/CommentCompletionDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/CodeCompletion/CommentCompletionDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/CodeCompletion/CommentCompletionDataProvider.cs	(working copy)
@@ -17,6 +17,7 @@
 using MonoDevelop.Services;
 
 using MonoDevelop.Internal.Parser;
+using MonoDevelop.Internal.Project;
 using MonoDevelop.SourceEditor.Gui;
 using Stock = MonoDevelop.Gui.Stock;
 
@@ -63,7 +64,7 @@
 			return row >= region.BeginLine && (row <= region.EndLine || region.EndLine == -1);
 		}
 		
-		public ICompletionData[] GenerateCompletionData (string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark triggerMark)
+		public ICompletionData[] GenerateCompletionData (IProject project, string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark triggerMark)
 		{
 			/*caretLineNumber = textArea.Caret.Line;
 			caretColumn     = textArea.Caret.Column;
Index: AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionWindow.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionWindow.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/CodeCompletion/CompletionWindow.cs	(working copy)
@@ -11,6 +11,7 @@
 
 using Gtk;
 using MonoDevelop.SourceEditor.Gui;
+using MonoDevelop.Internal.Project;
 
 namespace MonoDevelop.SourceEditor.CodeCompletion
 {
@@ -28,6 +29,8 @@
 		int origOffset;
 		int num_in = 0;
 		DeclarationViewWindow declarationviewwindow = new DeclarationViewWindow ();
+		string fileName;
+		IProject project;
 		
 		string GetTypedString ()
 		{
@@ -281,8 +284,6 @@
 			//GdkWindow.Move (tx + wx, ty + wy);
 		}
 		
-		string fileName;
-		
 		public static new GLib.GType GType
 		{
 			get
@@ -296,9 +297,10 @@
 		/// <remarks>
 		/// Creates a new Completion window and puts it location under the caret
 		/// </remarks>
-		public CompletionWindow (SourceEditorView control, string fileName, ICompletionDataProvider completionDataProvider) : base (GType)
+		public CompletionWindow (SourceEditorView control, IProject project, string fileName, ICompletionDataProvider completionDataProvider) : base (GType)
 		{
 			this.fileName = fileName;
+			this.project = project;
 			this.completionDataProvider = completionDataProvider;
 			this.control = control;
 
@@ -340,7 +342,7 @@
 		
 		void FillList (bool firstTime, char ch)
 		{
-			ICompletionData[] completionData = completionDataProvider.GenerateCompletionData(fileName, control, ch, triggeringMark);
+			ICompletionData[] completionData = completionDataProvider.GenerateCompletionData(project, fileName, control, ch, triggeringMark);
 			if (completionData == null || completionData.Length == 0) {
 				return;
 			}
Index: AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/CodeCompletion/ICompletionDataProvider.cs	(working copy)
@@ -9,6 +9,7 @@
 using System.Drawing;
 using System.Reflection;
 using System.Collections;
+using MonoDevelop.Internal.Project;
 
 using Gdk;
 
@@ -16,6 +17,6 @@
 
 namespace MonoDevelop.SourceEditor.CodeCompletion {
 	public interface ICompletionDataProvider {
-		ICompletionData[] GenerateCompletionData(string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark mark);
+		ICompletionData[] GenerateCompletionData(IProject project, string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark mark);
 	}
 }
Index: AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/CodeCompletion/CodeCompletionDataProvider.cs	(working copy)
@@ -19,6 +19,7 @@
 using MonoDevelop.Internal.Templates;
 using MonoDevelop.Services;
 using MonoDevelop.Internal.Parser;
+using MonoDevelop.Internal.Project;
 
 using MonoDevelop.SourceEditor.Gui;
 using Stock = MonoDevelop.Gui.Stock;
@@ -55,7 +56,7 @@
 		
 		ArrayList completionData = null;
 		
-		public ICompletionData[] GenerateCompletionData(string fileName, SourceEditorView textArea, char charTyped, TextMark triggerMark)
+		public ICompletionData[] GenerateCompletionData(IProject project, string fileName, SourceEditorView textArea, char charTyped, TextMark triggerMark)
 		{
 			completionData = new ArrayList();
 			this.fileName = fileName;
@@ -81,18 +82,19 @@
 				return (ICompletionData[])completionData.ToArray (typeof (ICompletionData));
 			}
 			if (ctrlspace && charTyped != '.') {
-				AddResolveResults (parserService.CtrlSpace (parserService, caretLineNumber, caretColumn, fileName));
+				AddResolveResults (parserService.CtrlSpace (parserService, project, caretLineNumber, caretColumn, fileName));
 				return (ICompletionData[])completionData.ToArray (typeof (ICompletionData));
 			}
 			if (charTyped == ' ') {
 				if (expression == "using" || expression.EndsWith(" using") || expression.EndsWith("\tusing")|| expression.EndsWith("\nusing")|| expression.EndsWith("\rusing")) {
-					string[] namespaces = parserService.GetNamespaceList("");
+					string[] namespaces = parserService.GetNamespaceList(project, "", true);
 					AddResolveResults(new ResolveResult(namespaces));
 				}
 			} else {
 				//FIXME: I added the null check, #D doesnt need it, why do we?
 				if (fileName != null) {
-					results = parserService.Resolve(expression, 
+					results = parserService.Resolve(project,
+													expression, 
 													caretLineNumber,
 													caretColumn,
 													fileName,
Index: AddIns/DisplayBindings/SourceEditor/CodeCompletion/TemplateCompletionDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/CodeCompletion/TemplateCompletionDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/CodeCompletion/TemplateCompletionDataProvider.cs	(working copy)
@@ -12,6 +12,7 @@
 
 using MonoDevelop.Core.Properties;
 using MonoDevelop.Internal.Templates;
+using MonoDevelop.Internal.Project;
 using MonoDevelop.SourceEditor.Gui;
 using Stock = MonoDevelop.Gui.Stock;
 
@@ -26,7 +27,7 @@
 			}
 		}
 		
-		public ICompletionData[] GenerateCompletionData(string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark triggerMark)
+		public ICompletionData[] GenerateCompletionData(IProject project, string fileName, SourceEditorView textArea, char charTyped, Gtk.TextMark triggerMark)
 		{
 			CodeTemplateGroup templateGroup = CodeTemplateLoader.GetTemplateGroupPerFilename(fileName);
 			if (templateGroup == null) {
Index: AddIns/DisplayBindings/SourceEditor/InsightWindow/MethodInsightDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/InsightWindow/MethodInsightDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/InsightWindow/MethodInsightDataProvider.cs	(working copy)
@@ -15,6 +15,7 @@
 using MonoDevelop.Internal.Templates;
 using MonoDevelop.Services;
 using MonoDevelop.Internal.Parser;
+using MonoDevelop.Internal.Project;
 
 using MonoDevelop.SourceEditor.Gui;
 using MonoDevelop.SourceEditor.CodeCompletion;
@@ -50,7 +51,7 @@
 		}
 		
 		int initialOffset;
-		public void SetupDataProvider(string fileName, SourceEditorView textArea)
+		public void SetupDataProvider(IProject project, string fileName, SourceEditorView textArea)
 		{
 			this.fileName = fileName;
 			this.textArea = textArea;
@@ -87,14 +88,14 @@
 				}
 			}
 			IParserService parserService = (IParserService)ServiceManager.Services.GetService(typeof(IParserService));
-			ResolveResult results = parserService.Resolve(methodObject, caretLineNumber, caretColumn, fileName, text);
+			ResolveResult results = parserService.Resolve(project, methodObject, caretLineNumber, caretColumn, fileName, text);
 			
 			if (results != null && results.Type != null) {
 				if (contructorInsight) {
 					AddConstructors(results.Type);
 				} else {
-					foreach (IClass c in results.Type.ClassInheritanceTree) {
-						AddMethods(c, methodName, false);
+					foreach (IClass c in parserService.GetClassInheritanceTree (project, results.Type)) {
+ 						AddMethods(c, methodName, false);
 					}
 				}
 			}
Index: AddIns/DisplayBindings/SourceEditor/InsightWindow/InsightWindow.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/InsightWindow/InsightWindow.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/InsightWindow/InsightWindow.cs	(working copy)
@@ -15,6 +15,7 @@
 
 using MonoDevelop.SourceEditor.Gui;
 using MonoDevelop.SourceEditor.CodeCompletion;
+using MonoDevelop.Internal.Project;
 
 namespace MonoDevelop.SourceEditor.InsightWindow
 {
@@ -28,6 +29,8 @@
 		Gtk.Label current;
 		Gtk.Label max;
 		string description;
+		string fileName;
+		IProject project;
 
 		StringParserService StringParserService = (StringParserService)ServiceManager.Services.GetService (typeof (StringParserService)); 
 		
@@ -45,7 +48,7 @@
 		
 		public void AddInsightDataProvider(IInsightDataProvider provider)
 		{
-			provider.SetupDataProvider(fileName, control);
+			provider.SetupDataProvider(project, fileName, control);
 			if (provider.InsightDataCount > 0) {
 				insightDataProviderStack.Push(new InsightDataProviderStackElement(provider));
 			}
@@ -105,17 +108,17 @@
 
 			}
 		}
-		string fileName;
 		
 		static InsightWindow ()
 		{
 			type = RegisterGType (typeof (InsightWindow));
 		}
 		
-		public InsightWindow(SourceEditorView control, string fileName) : base (type)
+		public InsightWindow(SourceEditorView control, IProject project, string fileName) : base (type)
 		{
 			this.control             = control;
 			this.fileName = fileName;
+			this.project = project;
 			/*System.Drawing.Point caretPos  = control.ActiveTextAreaControl.TextArea.Caret.Position;
 			System.Drawing.Point visualPos = new System.Drawing.Point(control.ActiveTextAreaControl.TextArea.TextView.GetDrawingXPos(caretPos.Y, caretPos.X) + control.ActiveTextAreaControl.TextArea.TextView.DrawingPosition.X,
 			          (int)((1 + caretPos.Y) * control.ActiveTextAreaControl.TextArea.TextView.FontHeight) - control.ActiveTextAreaControl.TextArea.VirtualTop.Y - 1 + control.ActiveTextAreaControl.TextArea.TextView.DrawingPosition.Y);*/
Index: AddIns/DisplayBindings/SourceEditor/InsightWindow/IInsightDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/InsightWindow/IInsightDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/InsightWindow/IInsightDataProvider.cs	(working copy)
@@ -11,12 +11,13 @@
 using System.Collections;
 
 using MonoDevelop.SourceEditor.Gui;
+using MonoDevelop.Internal.Project;
 
 namespace MonoDevelop.SourceEditor.InsightWindow
 {
 	public interface IInsightDataProvider
 	{
-		void SetupDataProvider(string fileName, SourceEditorView textArea);
+		void SetupDataProvider(IProject project, string fileName, SourceEditorView textArea);
 		
 		bool CaretOffsetChanged();
 		bool CharTyped();
Index: AddIns/DisplayBindings/SourceEditor/InsightWindow/IndexerInsightDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/InsightWindow/IndexerInsightDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/InsightWindow/IndexerInsightDataProvider.cs	(working copy)
@@ -15,6 +15,7 @@
 using MonoDevelop.Internal.Templates;
 using MonoDevelop.Services;
 using MonoDevelop.Internal.Parser;
+using MonoDevelop.Internal.Project;
 
 using MonoDevelop.SourceEditor.Gui;
 using MonoDevelop.SourceEditor.CodeCompletion;
@@ -47,7 +48,7 @@
 		}
 		
 		int initialOffset;
-		public void SetupDataProvider(string fileName, SourceEditorView textArea)
+		public void SetupDataProvider(IProject project, string fileName, SourceEditorView textArea)
 		{
 			this.fileName = fileName;
 			this.textArea = textArea;
@@ -61,10 +62,10 @@
 			int caretLineNumber      = initialIter.Line + 1;
 			int caretColumn          = initialIter.LineOffset + 1;
 			IParserService parserService = (IParserService)ServiceManager.Services.GetService(typeof(IParserService));
-			ResolveResult results = parserService.Resolve(methodObject, caretLineNumber, caretColumn, fileName, textArea.Buffer.Text);
-			Console.WriteLine ("not null");
+			ResolveResult results = parserService.Resolve(project, methodObject, caretLineNumber, caretColumn, fileName, textArea.Buffer.Text);
+			
 			if (results != null && results.Type != null) {
-				foreach (IClass c in results.Type.ClassInheritanceTree) {
+				foreach (IClass c in parserService.GetClassInheritanceTree (project, results.Type)) {
 					foreach (IIndexer indexer in c.Indexer) {
 						methods.Add(indexer);
 					}
Index: AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/CommentCompletionDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/CommentCompletionDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/CommentCompletionDataProvider.cs	(working copy)
@@ -71,7 +71,7 @@
 			return row >= region.BeginLine && (row <= region.EndLine || region.EndLine == -1);
 		}
 		
-		public ICompletionData[] GenerateCompletionData(string fileName, TextArea textArea, char charTyped)
+		public ICompletionData[] GenerateCompletionData(IProject project, string fileName, TextArea textArea, char charTyped)
 		{
 			caretLineNumber = textArea.Caret.Line;
 			caretColumn     = textArea.Caret.Column;
Index: AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/CodeCompletionDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/CodeCompletionDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/CodeCompletionDataProvider.cs	(working copy)
@@ -49,7 +49,7 @@
 		
 		ArrayList completionData = null;
 			
-		public ICompletionData[] GenerateCompletionData(string fileName, TextArea textArea, char charTyped)
+		public ICompletionData[] GenerateCompletionData(IProject project, string fileName, TextArea textArea, char charTyped)
 		{
 			IDocument document =  textArea.Document;
 			Console.WriteLine ("resolve " + document.Language);
Index: AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/TemplateCompletionDataProvider.cs
===================================================================
--- AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/TemplateCompletionDataProvider.cs	(revision 1623)
+++ AddIns/DisplayBindings/TextEditor/Gui/Editor/CompletionWindow/TemplateCompletionDataProvider.cs	(working copy)
@@ -12,6 +12,7 @@
 
 using MonoDevelop.Core.Properties;
 using MonoDevelop.Internal.Templates;
+using MonoDevelop.Internal.Project;
 using MonoDevelop.TextEditor.Document;
 using MonoDevelop.TextEditor;
 using MonoDevelop.TextEditor.Gui.CompletionWindow;
@@ -26,7 +27,7 @@
 			}
 		}
 		
-		public ICompletionData[] GenerateCompletionData(string fileName, TextArea textArea, char charTyped)
+		public ICompletionData[] GenerateCompletionData(IProject project, string fileName, TextArea textArea, char charTyped)
 		{
 			CodeTemplateGroup templateGroup = CodeTemplateLoader.GetTemplateGroupPerFilename(fileName);
 			if (templateGroup == null) {
Index: AddIns/BackendBindings/CSharpBinding/Parser/Parser.cs
===================================================================
--- AddIns/BackendBindings/CSharpBinding/Parser/Parser.cs	(revision 1623)
+++ AddIns/BackendBindings/CSharpBinding/Parser/Parser.cs	(working copy)
@@ -9,6 +9,7 @@
 using System.Collections;
 using MonoDevelop.Services;
 using MonoDevelop.Internal.Parser;
+using MonoDevelop.Internal.Project;
 using CSharpBinding.Parser.SharpDevelopTree;
 using ICSharpCode.SharpRefactory.Parser;
 
@@ -70,6 +71,8 @@
 			visitor.Visit(p.compilationUnit, null);
 			visitor.Cu.ErrorsDuringCompile = p.Errors.count > 0;
 			RetrieveRegions(visitor.Cu, lexer.SpecialTracker);
+			foreach (IClass c in visitor.Cu.Classes)
+				c.Region.FileName = fileName;
 			return visitor.Cu;
 		}
 		
@@ -86,27 +89,29 @@
 			visitor.Cu.Tag = p.compilationUnit;
 			visitor.Cu.ErrorOutput = p.Errors.ErrorOutput;
 			RetrieveRegions(visitor.Cu, lexer.SpecialTracker);
+			foreach (IClass c in visitor.Cu.Classes)
+				c.Region.FileName = fileName;
 			return visitor.Cu;
 		}
 		
-		public ArrayList CtrlSpace(IParserService parserService, int caretLine, int caretColumn, string fileName)
+		public ArrayList CtrlSpace(IParserService parserService, IProject project, int caretLine, int caretColumn, string fileName)
 		{
-			return new Resolver().CtrlSpace(parserService, caretLine, caretColumn, fileName);
+			return new Resolver(project).CtrlSpace(parserService, caretLine, caretColumn, fileName);
 		}
 
 		public ArrayList IsAsResolve (IParserService parserService, string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent)
 		{
-			return new Resolver ().IsAsResolve (parserService, expression, caretLineNumber, caretColumn, fileName, fileContent);
+			return new Resolver (null).IsAsResolve (parserService, expression, caretLineNumber, caretColumn, fileName, fileContent);
 		}
 		
-		public ResolveResult Resolve(IParserService parserService, string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent)
+		public ResolveResult Resolve(IParserService parserService, IProject project, string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent)
 		{
-			return new Resolver().Resolve(parserService, expression, caretLineNumber, caretColumn, fileName, fileContent);
+			return new Resolver(project).Resolve(parserService, expression, caretLineNumber, caretColumn, fileName, fileContent);
 		}
 
 		public string MonodocResolver (IParserService parserService, string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent)
 		{
-			return new Resolver ().MonodocResolver (parserService, expression, caretLineNumber, caretColumn, fileName, fileContent);
+			return new Resolver (null).MonodocResolver (parserService, expression, caretLineNumber, caretColumn, fileName, fileContent);
 		}
 		
 		///////// IParser Interface END
Index: AddIns/BackendBindings/CSharpBinding/Parser/Resolver.cs
===================================================================
--- AddIns/BackendBindings/CSharpBinding/Parser/Resolver.cs	(revision 1623)
+++ AddIns/BackendBindings/CSharpBinding/Parser/Resolver.cs	(working copy)
@@ -11,6 +11,7 @@
 
 using MonoDevelop.Services;
 using MonoDevelop.Internal.Parser;
+using MonoDevelop.Internal.Project;
 using CSharpBinding.Parser.SharpDevelopTree;
 using ICSharpCode.SharpRefactory.Parser.AST;
 using ICSharpCode.SharpRefactory.Parser;
@@ -23,7 +24,13 @@
 		ICompilationUnit cu;
 		IClass callingClass;
 		LookupTableVisitor lookupTableVisitor;
+		IProject project;
 		
+		public Resolver (IProject project)
+		{
+			this.project = project;
+		}
+		
 		public IParserService ParserService {
 			get {
 				return parserService;
@@ -195,7 +202,7 @@
 				}
 				string t = expression.Substring(i + 1);
 //				Console.WriteLine("in Using Statement");
-				string[] namespaces = parserService.GetNamespaceList(t);
+				string[] namespaces = parserService.GetNamespaceList(project, t);
 				if (namespaces == null || namespaces.Length <= 0) {
 					return null;
 				}
@@ -211,14 +218,14 @@
 				if (n == null) {
 					return null;
 				}
-				ArrayList content = parserService.GetNamespaceContents(n);
+				ArrayList content = parserService.GetNamespaceContents(project,n,true);
 				ArrayList classes = new ArrayList();
 				for (int i = 0; i < content.Count; ++i) {
 					if (content[i] is IClass) {
 						classes.Add((IClass)content[i]);
 					}
 				}
-				string[] namespaces = parserService.GetNamespaceList(n);
+				string[] namespaces = parserService.GetNamespaceList(project, n, true);
 				return new ResolveResult(namespaces, classes);
 			}
 			Console.WriteLine("Returning Result!");
@@ -674,7 +681,7 @@
 		/// </remarks>
 		public string SearchNamespace(string name, ICompilationUnit unit)
 		{
-			if (parserService.NamespaceExists(name)) {
+			if (parserService.NamespaceExists(project, name)) {
 				return name;
 			}
 			if (unit == null) {
@@ -683,7 +690,7 @@
 			}
 			foreach (IUsing u in unit.Usings) {
 				if (u != null && (u.Region == null || u.Region.IsInside(caretLine, caretColumn))) {
-					string nameSpace = u.SearchNamespace(name);
+					string nameSpace = parserService.SearchNamespace (project, u, name);
 					if (nameSpace != null) {
 						return nameSpace;
 					}
@@ -704,7 +711,7 @@
 				return null;
 			}
 			IClass c;
-			c = parserService.GetClass(name);
+			c = parserService.GetClass(project, name);
 			if (c != null) {
 //				Console.WriteLine("Found!");
 				return c;
@@ -715,7 +722,7 @@
 				foreach (IUsing u in unit.Usings) {
 					if (u != null && (u.Region == null || u.Region.IsInside(caretLine, caretColumn))) {
 //						Console.WriteLine("In UsingRegion");
-						c = u.SearchType(name);
+						c = parserService.SearchType(project, u, name);
 						if (c != null) {
 //							Console.WriteLine("SearchType Successfull!!!");
 							return c;
@@ -730,7 +737,7 @@
 			string[] namespaces = fullname.Split(new char[] {'.'});
 			string curnamespace = namespaces[0] + '.';
 			for (int i = 1; i < namespaces.Length; ++i) {
-				c = parserService.GetClass(curnamespace + name);
+				c = parserService.GetClass(project, curnamespace + name);
 				if (c != null) {
 					return c;
 				}
@@ -877,7 +884,7 @@
 			if (returnClass == null)
 				return null;
 
-			foreach (IClass iclass in returnClass.ClassInheritanceTree) {
+			foreach (IClass iclass in parserService.GetClassInheritanceTree (project, returnClass)) {
 				if (!result.Contains (iclass))
 					result.Add (iclass);
 			}
@@ -917,11 +924,11 @@
 				result = ListMembers(result, callingClass);
 			}
 			string n = "";
-			result.AddRange(parserService.GetNamespaceContents(n));
+			result.AddRange(parserService.GetNamespaceContents(project, n, true));
 			foreach (IUsing u in cu.Usings) {
 				if (u != null && (u.Region == null || u.Region.IsInside(caretLine, caretColumn))) {
 					foreach (string name in u.Usings) {
-						result.AddRange(parserService.GetNamespaceContents(name));
+						result.AddRange(parserService.GetNamespaceContents(project, name, true));
 					}
 					foreach (string alias in u.Aliases.Keys) {
 						result.Add(alias);
Index: Main/Base/Services/File/DefaultFileService.cs
===================================================================
--- Main/Base/Services/File/DefaultFileService.cs	(revision 1623)
+++ Main/Base/Services/File/DefaultFileService.cs	(working copy)
@@ -51,27 +51,28 @@
 		class LoadFileWrapper
 		{
 			IDisplayBinding binding;
-			string projectname, pathrelativetoproject;
+			IProject project;
+			string pathrelativetoproject;
 			
 			public LoadFileWrapper(IDisplayBinding binding)
 			{
 				this.binding = binding;
 			}
 			
-			public LoadFileWrapper(IDisplayBinding binding, string projectname, string pathrelativetoproject)
+			public LoadFileWrapper(IDisplayBinding binding, IProject project, string pathrelativetoproject)
 			{
 				this.binding = binding;
-				this.projectname = projectname;
+				this.project = project;
 				this.pathrelativetoproject = pathrelativetoproject;
 			}
 			
 			public void Invoke(string fileName)
 			{
 				IViewContent newContent = binding.CreateContentForFile(fileName);
-				if (projectname != null && projectname != "" &&  pathrelativetoproject != null && pathrelativetoproject != "")
-				{ 
+				if (project != null &&  pathrelativetoproject != null && pathrelativetoproject != "")
+				{
 					newContent.HasProject = true;
-					newContent.ProjectName = projectname;
+					newContent.Project = project;
 					newContent.PathRelativeToProject = pathrelativetoproject;
 				}
 				WorkbenchSingleton.Workbench.ShowView(newContent);
@@ -126,7 +127,7 @@
 				
 				if (combine != null && project != null)
 				{
-					if (fileUtilityService.ObservedLoad(new NamedFileOperationDelegate(new LoadFileWrapper(binding, project.Name, pathrelativetoproject).Invoke), fileName) == FileOperationResult.OK) {
+					if (fileUtilityService.ObservedLoad(new NamedFileOperationDelegate(new LoadFileWrapper(binding, project, pathrelativetoproject).Invoke), fileName) == FileOperationResult.OK) {
 						fileService.RecentOpen.AddLastFile(fileName);
 					}
 				}
Index: Main/Base/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs
===================================================================
--- Main/Base/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs	(revision 1623)
+++ Main/Base/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs	(working copy)
@@ -458,7 +458,7 @@
 					}
 					if (ActiveWorkbenchwindow.ViewContent.HasProject)
 					{
-						((Gtk.Window)WorkbenchSingleton.Workbench).Title = ActiveWorkbenchwindow.ViewContent.ProjectName + " - " + ActiveWorkbenchwindow.ViewContent.PathRelativeToProject + post + " - MonoDevelop";
+						((Gtk.Window)WorkbenchSingleton.Workbench).Title = ActiveWorkbenchwindow.ViewContent.Project.Name + " - " + ActiveWorkbenchwindow.ViewContent.PathRelativeToProject + post + " - MonoDevelop";
 					}
 					else
 					{
Index: Main/Base/Gui/IViewContent.cs
===================================================================
--- Main/Base/Gui/IViewContent.cs	(revision 1623)
+++ Main/Base/Gui/IViewContent.cs	(working copy)
@@ -6,6 +6,7 @@
 // </file>
 
 using System;
+using MonoDevelop.Internal.Project;
 
 namespace MonoDevelop.Gui
 {
@@ -94,11 +95,11 @@
 		/// <summary>
 		/// The name of the project the content is attached to
 		/// </summary>
-		string ProjectName {
+		IProject Project {
 			get;
 			set;
 		}
-		
+	
 		/// <summary>
 		/// The path relative to the project
 		/// </summary>
Index: Main/Base/Gui/AbstractViewContent.cs
===================================================================
--- Main/Base/Gui/AbstractViewContent.cs	(revision 1623)
+++ Main/Base/Gui/AbstractViewContent.cs	(working copy)
@@ -8,6 +8,7 @@
 using System;
 
 using MonoDevelop.Services;
+using MonoDevelop.Internal.Project;
 
 namespace MonoDevelop.Gui
 {
@@ -15,7 +16,7 @@
 	{
 		string untitledName = "";
 		string contentName  = null;
-		string projectname = null;
+		IProject project = null;
 		string pathrelativetoproject = null;
 		
 		bool   isDirty  = false;
@@ -101,19 +102,19 @@
 		
 		public abstract void Load(string fileName);
 
-		public string ProjectName
+		public IProject Project
 		{
 			get
 			{
-				return projectname;
+				return project;
 			}
 			set
 			{
-				if (!HasProject && value != null && value != "")
+				if (!HasProject && value != null)
 				{
 					HasProject = true;
 				}
-				projectname = value;
+				project = value;
 			}
 		}
 		
@@ -131,10 +132,6 @@
 					{
 						HasProject = true;
 					}
-					if (ProjectName == null)
-					{
-						ProjectName = "";
-					}
 				}
 				pathrelativetoproject = value;
 			}
Index: Main/Base/Internal/Parser/IParser.cs
===================================================================
--- Main/Base/Internal/Parser/IParser.cs	(revision 1623)
+++ Main/Base/Internal/Parser/IParser.cs	(working copy)
@@ -10,6 +10,7 @@
 using System.Collections.Specialized;
 
 using MonoDevelop.Services;
+using MonoDevelop.Internal.Project;
 
 namespace MonoDevelop.Internal.Parser
 {
@@ -131,6 +132,7 @@
 		/// The caretLineNumber and caretColumn is 1 based.
 		/// </summary>
 		ResolveResult Resolve(IParserService parserService, 
+							  IProject project,
 		                      string expression, 
 		                      int caretLineNumber, 
 		                      int caretColumn, 
@@ -141,6 +143,6 @@
 
 		ArrayList IsAsResolve (IParserService parserService, string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent);
 		
-		ArrayList CtrlSpace(IParserService parserService, int caretLine, int caretColumn, string fileName);
+		ArrayList CtrlSpace(IParserService parserService, IProject project, int caretLine, int caretColumn, string fileName);
 	}
 }
Index: Libraries/ICSharpCode.TextEditor/src/Gui/CompletionWindow/ICompletionDataProvider.cs
===================================================================
--- Libraries/ICSharpCode.TextEditor/src/Gui/CompletionWindow/ICompletionDataProvider.cs	(revision 1623)
+++ Libraries/ICSharpCode.TextEditor/src/Gui/CompletionWindow/ICompletionDataProvider.cs	(working copy)
@@ -22,6 +22,6 @@
 			get;
 		}
 		
-		ICompletionData[] GenerateCompletionData(string fileName, TextArea textArea, char charTyped);
+		ICompletionData[] GenerateCompletionData(IProject project, string fileName, TextArea textArea, char charTyped);
 	}
 }

--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=events.diff
Content-Type: text/x-patch; name=events.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: Main/Base/Commands/ProjectBrowserCommands/ReferenceFolderNodeCommands.cs
===================================================================
--- Main/Base/Commands/ProjectBrowserCommands/ReferenceFolderNodeCommands.cs	(revision 1623)
+++ Main/Base/Commands/ProjectBrowserCommands/ReferenceFolderNodeCommands.cs	(working copy)
@@ -37,7 +37,6 @@
 			
 			if (node != null) {
 				IProject project = ((ProjectBrowserNode)node.Parent).Project;
-				IParserService parserService = (IParserService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IParserService));
 				
 				SelectReferenceDialog selDialog = new SelectReferenceDialog(project);
 				if (selDialog.Run() == (int)Gtk.ResponseType.Ok) {
@@ -45,7 +44,6 @@
 					project.ProjectReferences.Clear ();
 					foreach (ProjectReference refInfo in selDialog.ReferenceInformations) {
 						project.ProjectReferences.Add(refInfo);
-						parserService.AddReferenceToCompletionLookup(project, refInfo);
 					}
 					
 					DefaultDotNetNodeBuilder.InitializeReferences(node, project);
Index: Main/Base/Services/ParserService/ClassInformationEventHandler.cs
===================================================================
--- Main/Base/Services/ParserService/ClassInformationEventHandler.cs	(revision 0)
+++ Main/Base/Services/ParserService/ClassInformationEventHandler.cs	(revision 0)
@@ -0,0 +1,47 @@
+// <file>
+//     <copyright see="prj:///doc/copyright.txt"/>
+//     <license see="prj:///doc/license.txt"/>
+//     <owner name="Lluis Sanchez Gual" email="lluis@ximian.com"/>
+//     <version value="$version"/>
+// </file>
+
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+
+using MonoDevelop.Core.AddIns;
+
+using MonoDevelop.Internal.Parser;
+using MonoDevelop.Internal.Project;
+
+using MonoDevelop.Gui;
+
+namespace MonoDevelop.Services
+{
+	public delegate void ClassInformationEventHandler(object sender, ClassInformationEventArgs e);
+	
+	public class ClassInformationEventArgs : EventArgs
+	{
+		string fileName;
+		ClassUpdateInformation classInformation;
+				
+		public string FileName {
+			get {
+				return fileName;
+			}
+		}
+		
+		public ClassUpdateInformation ClassInformation {
+			get {
+				return classInformation;
+			}
+		}
+		
+		public ClassInformationEventArgs(string fileName, ClassUpdateInformation classInformation)
+		{
+			this.fileName         = fileName;
+			this.classInformation = classInformation;
+		}
+	}
+}
Index: Main/Base/Services/Project/DefaultProjectService.cs
===================================================================
--- Main/Base/Services/Project/DefaultProjectService.cs	(revision 1623)
+++ Main/Base/Services/Project/DefaultProjectService.cs	(working copy)
@@ -170,6 +170,10 @@
 			fileService.RecentOpen.AddLastProject(filename);
 			
 			OnCombineOpened(new CombineEventArgs(openCombine));
+			openCombine.FileAddedToProject += new ProjectFileEventHandler (NotifyFileAddedToProject);
+			openCombine.FileRemovedFromProject += new ProjectFileEventHandler (NotifyFileRemovedFromProject);
+			openCombine.ReferenceAddedToProject += new ProjectReferenceEventHandler (NotifyReferenceAddedToProject);
+			openCombine.ReferenceRemovedFromProject += new ProjectReferenceEventHandler (NotifyReferenceRemovedFromProject);
 			
 			RestoreCombinePreferences(CurrentOpenCombine, openCombineFileName);
 		}
@@ -202,13 +206,11 @@
 			}
 			ProjectFile newFileInformation = new ProjectFile(filename, action);
 			prj.ProjectFiles.Add(newFileInformation);
-			OnFileAddedToProject (new FileEventArgs (filename, false));
 			return newFileInformation;
 		}
 		
 		public void AddFileToProject(IProject prj, ProjectFile projectFile) {
 			prj.ProjectFiles.Add(projectFile);
-			OnFileAddedToProject (new FileEventArgs (projectFile.Name, false));
 		}
 
 		
@@ -462,7 +464,6 @@
 			base.InitializeService();
 			IFileService fileService = (IFileService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IFileService));
 			
-			FileRemovedFromProject += new FileEventHandler(CheckFileRemove);
 			fileService.FileRemoved += new FileEventHandler(CheckFileRemove);
 			fileService.FileRenamed += new FileEventHandler(CheckFileRename);
 		}
@@ -657,11 +658,6 @@
 		
 		public void RemoveFileFromProject(string fileName)
 		{
-			if (Directory.Exists(fileName)) {
-				OnFileRemovedFromProject(new FileEventArgs(fileName, true));
-			} else {
-				OnFileRemovedFromProject(new FileEventArgs(fileName, false));
-			}
 		}
 			
 		public void OnStartBuild()
@@ -684,20 +680,54 @@
 			}
 		}
 		
-		public virtual void OnFileRemovedFromProject (FileEventArgs e)
+		void NotifyFileRemovedFromProject (object sender, ProjectFileEventArgs e)
 		{
+			OnFileRemovedFromProject (e);
+		}
+		
+		void NotifyFileAddedToProject (object sender, ProjectFileEventArgs e)
+		{
+			OnFileAddedToProject (e);
+		}
+		
+		internal void NotifyReferenceAddedToProject (object sender, ProjectReferenceEventArgs e)
+		{
+			OnReferenceRemovedFromProject (e);
+		}
+		
+		internal void NotifyReferenceRemovedFromProject (object sender, ProjectReferenceEventArgs e)
+		{
+			OnReferenceAddedToProject (e);
+		}
+		
+		protected virtual void OnFileRemovedFromProject (ProjectFileEventArgs e)
+		{
 			if (FileRemovedFromProject != null) {
 				FileRemovedFromProject(this, e);
 			}
 		}
 
-		public virtual void OnFileAddedToProject (FileEventArgs e)
+		protected virtual void OnFileAddedToProject (ProjectFileEventArgs e)
 		{
 			if (FileAddedToProject != null) {
 				FileAddedToProject (this, e);
 			}
 		}
 		
+		protected virtual void OnReferenceRemovedFromProject (ProjectReferenceEventArgs e)
+		{
+			if (ReferenceRemovedFromProject != null) {
+				ReferenceRemovedFromProject (this, e);
+			}
+		}
+		
+		protected virtual void OnReferenceAddedToProject (ProjectReferenceEventArgs e)
+		{
+			if (ReferenceAddedToProject != null) {
+				ReferenceAddedToProject (this, e);
+			}
+		}
+
 		public string GetFileName(IProject project)
 		{
 			if (openCombine != null) {
@@ -739,8 +769,8 @@
 			openCombine.GenerateMakefiles ();
 		}
 		
-		public event FileEventHandler FileRemovedFromProject;
-		public event FileEventHandler FileAddedToProject;
+		public event ProjectFileEventHandler FileRemovedFromProject;
+		public event ProjectFileEventHandler FileAddedToProject;
 		public event EventHandler     StartBuild;
 		public event EventHandler     EndBuild;
 		public event EventHandler     BeforeStartProject;
@@ -752,5 +782,8 @@
 		
 		public event ProjectRenameEventHandler ProjectRenamed;
 		public event ProjectEventHandler       CurrentProjectChanged;
+		
+		public event ProjectReferenceEventHandler ReferenceAddedToProject;
+		public event ProjectReferenceEventHandler ReferenceRemovedFromProject;
 	}
 }
Index: Main/Base/Services/Project/IProjectService.cs
===================================================================
--- Main/Base/Services/Project/IProjectService.cs	(revision 1623)
+++ Main/Base/Services/Project/IProjectService.cs	(working copy)
@@ -187,10 +187,16 @@
 		/// <remarks>
 		/// Is called, when a file is removed from and added to a project.
 		/// </remarks>
-		event FileEventHandler FileRemovedFromProject;
-		event FileEventHandler FileAddedToProject;
+		event ProjectFileEventHandler FileRemovedFromProject;
+		event ProjectFileEventHandler FileAddedToProject;
 				
 		/// <remarks>
+		/// Is called, when a reference is removed from and added to a project.
+		/// </remarks>
+		event ProjectReferenceEventHandler ReferenceAddedToProject;
+		event ProjectReferenceEventHandler ReferenceRemovedFromProject;
+		
+		/// <remarks>
 		/// Called before a build run
 		/// </remarks>
 		event EventHandler StartBuild;
Index: Main/Base/Internal/Project/Project/IProject.cs
===================================================================
--- Main/Base/Internal/Project/Project/IProject.cs	(revision 1623)
+++ Main/Base/Internal/Project/Project/IProject.cs	(working copy)
@@ -156,5 +156,9 @@
 		IConfiguration CreateConfiguration();
 		
 		event EventHandler NameChanged;
+		event ProjectFileEventHandler FileRemovedFromProject;
+		event ProjectFileEventHandler FileAddedToProject;
+		event ProjectReferenceEventHandler ReferenceRemovedFromProject;
+		event ProjectReferenceEventHandler ReferenceAddedToProject;
 	}
 }
Index: Main/Base/Internal/Project/Project/ProjectFileEventArgs.cs
===================================================================
--- Main/Base/Internal/Project/Project/ProjectFileEventArgs.cs	(revision 0)
+++ Main/Base/Internal/Project/Project/ProjectFileEventArgs.cs	(revision 0)
@@ -0,0 +1,38 @@
+// <file>
+//     <copyright see="prj:///doc/copyright.txt"/>
+//     <license see="prj:///doc/license.txt"/>
+//     <owner name="Lluis Sanchez Gual" email="lluis@ximian.com"/>
+//     <version value="$version"/>
+// </file>
+
+using System;
+using MonoDevelop.Internal.Project;
+
+namespace MonoDevelop.Internal.Project
+{
+	public delegate void ProjectFileEventHandler(object sender, ProjectFileEventArgs e);
+	
+	public class ProjectFileEventArgs : EventArgs
+	{
+		IProject project;
+		ProjectFile file;
+		
+		public IProject Project {
+			get {
+				return project;
+			}
+		}
+		
+		public ProjectFile ProjectFile {
+			get {
+				return file;
+			}
+		}
+		
+		public ProjectFileEventArgs (IProject project, ProjectFile file)
+		{
+			this.project = project;
+			this.file = file;
+		}
+	}
+}
Index: Main/Base/Internal/Project/Project/AbstractProject.cs
===================================================================
--- Main/Base/Internal/Project/Project/AbstractProject.cs	(revision 1623)
+++ Main/Base/Internal/Project/Project/AbstractProject.cs	(working copy)
@@ -52,7 +52,7 @@
 		protected ProjectFileCollection      projectFiles       = new ProjectFileCollection();
 
 		[XmlSetAttribute(typeof(ProjectReference), "References")]
-		protected ProjectReferenceCollection projectReferencess = new ProjectReferenceCollection();
+		protected ProjectReferenceCollection projectReferences = new ProjectReferenceCollection();
 		
 		protected DeployInformation deployInformation = new DeployInformation();
 		FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
@@ -105,7 +105,7 @@
 		[Browsable(false)]
 		public ProjectReferenceCollection ProjectReferences {
 			get {
-				return projectReferencess;
+				return projectReferences;
 			}
 		}
 		
@@ -172,6 +172,8 @@
 
 		public AbstractProject()
 		{
+			projectFiles.SetProject (this);
+			projectReferences.SetProject (this);
 		}
 
 		public bool IsFileInProject(string filename)
@@ -301,6 +303,9 @@
 			}
 			
 			SearchNewFiles();
+
+			projectFiles.SetProject (this);
+			projectReferences.SetProject (this);
 		}
 
 		void GetXmlAttributes(XmlDocument doc, XmlElement element, object o)
@@ -355,11 +360,13 @@
 							setElement = (XmlElement)element.SelectSingleNode("descendant::" + xmlSetAttributes[0].Name);
 						}
 						
-						IList collection = (IList)fieldInfo.GetValue(o);
-						foreach (XmlNode childNode in setElement.ChildNodes) {
-							object instance = xmlSetAttributes[0].Type.Assembly.CreateInstance(xmlSetAttributes[0].Type.FullName);
-							GetXmlAttributes(doc, (XmlElement)childNode, instance);
-							collection.Add(instance);
+						if (setElement != null) {
+							IList collection = (IList)fieldInfo.GetValue(o);
+							foreach (XmlNode childNode in setElement.ChildNodes) {
+								object instance = xmlSetAttributes[0].Type.Assembly.CreateInstance(xmlSetAttributes[0].Type.FullName);
+								GetXmlAttributes(doc, (XmlElement)childNode, instance);
+								collection.Add(instance);
+							}
 						}
 					} else { // finally try, if the field is from a type which has a XmlNodeName attribute attached
 						
@@ -561,6 +568,26 @@
 			return config;
 		}
 		
+		internal void NotifyFileRemovedFromProject (ProjectFile file)
+		{
+			OnFileRemovedFromProject (new ProjectFileEventArgs (this, file));
+		}
+		
+		internal void NotifyFileAddedToProject (ProjectFile file)
+		{
+			OnFileAddedToProject (new ProjectFileEventArgs (this, file));
+		}
+		
+		internal void NotifyReferenceRemovedFromProject (ProjectReference reference)
+		{
+			OnReferenceRemovedFromProject (new ProjectReferenceEventArgs (this, reference));
+		}
+		
+		internal void NotifyReferenceAddedToProject (ProjectReference reference)
+		{
+			OnReferenceAddedToProject (new ProjectReferenceEventArgs (this, reference));
+		}
+		
 		protected virtual void OnNameChanged(EventArgs e)
 		{
 			if (NameChanged != null) {
@@ -568,7 +595,39 @@
 			}
 		}
 		
+		protected virtual void OnFileRemovedFromProject (ProjectFileEventArgs e)
+		{
+			if (FileRemovedFromProject != null) {
+				FileRemovedFromProject (this, e);
+			}
+		}
+		
+		protected virtual void OnFileAddedToProject (ProjectFileEventArgs e)
+		{
+			if (FileAddedToProject != null) {
+				FileAddedToProject (this, e);
+			}
+		}
+		
+		protected virtual void OnReferenceRemovedFromProject (ProjectReferenceEventArgs e)
+		{
+			if (ReferenceRemovedFromProject != null) {
+				ReferenceRemovedFromProject (this, e);
+			}
+		}
+		
+		protected virtual void OnReferenceAddedToProject (ProjectReferenceEventArgs e)
+		{
+			if (ReferenceAddedToProject != null) {
+				ReferenceAddedToProject (this, e);
+			}
+		}
+		
 		public event EventHandler NameChanged;
+		public event ProjectFileEventHandler FileRemovedFromProject;
+		public event ProjectFileEventHandler FileAddedToProject;
+		public event ProjectReferenceEventHandler ReferenceRemovedFromProject;
+		public event ProjectReferenceEventHandler ReferenceAddedToProject;
 	}
 	
 	public class ProjectActiveConfigurationTypeConverter : TypeConverter
Index: Main/Base/Internal/Project/Project/ProjectReferenceEventArgs.cs
===================================================================
--- Main/Base/Internal/Project/Project/ProjectReferenceEventArgs.cs	(revision 0)
+++ Main/Base/Internal/Project/Project/ProjectReferenceEventArgs.cs	(revision 0)
@@ -0,0 +1,38 @@
+// <file>
+//     <copyright see="prj:///doc/copyright.txt"/>
+//     <license see="prj:///doc/license.txt"/>
+//     <owner name="Lluis Sanchez Gual" email="lluis@ximian.com"/>
+//     <version value="$version"/>
+// </file>
+
+using System;
+using MonoDevelop.Internal.Project;
+
+namespace MonoDevelop.Internal.Project
+{
+	public delegate void ProjectReferenceEventHandler(object sender, ProjectReferenceEventArgs e);
+	
+	public class ProjectReferenceEventArgs : EventArgs
+	{
+		IProject project;
+		ProjectReference reference;
+		
+		public IProject Project {
+			get {
+				return project;
+			}
+		}
+		
+		public ProjectReference ProjectReference {
+			get {
+				return reference;
+			}
+		}
+		
+		public ProjectReferenceEventArgs (IProject project, ProjectReference reference)
+		{
+			this.project = project;
+			this.reference = reference;
+		}
+	}
+}
Index: Main/Base/Internal/Project/Project/Collections/ProjectReferenceCollection.cs
===================================================================
--- Main/Base/Internal/Project/Project/Collections/ProjectReferenceCollection.cs	(revision 1623)
+++ Main/Base/Internal/Project/Project/Collections/ProjectReferenceCollection.cs	(working copy)
@@ -18,39 +18,22 @@
 	[Serializable()]
 	public class ProjectReferenceCollection : CollectionBase {
 		
+		AbstractProject project;
+		
 		/// <summary>
 		///     <para>
 		///       Initializes a new instance of <see cref='.ProjectReferenceCollection'/>.
 		///    </para>
 		/// </summary>
-		public ProjectReferenceCollection() {
+		internal ProjectReferenceCollection() {
 		}
 		
-		/// <summary>
-		///     <para>
-		///       Initializes a new instance of <see cref='.ProjectReferenceCollection'/> based on another <see cref='.ProjectReferenceCollection'/>.
-		///    </para>
-		/// </summary>
-		/// <param name='value'>
-		///       A <see cref='.ProjectReferenceCollection'/> from which the contents are copied
-		/// </param>
-		public ProjectReferenceCollection(ProjectReferenceCollection value) {
-			this.AddRange(value);
+		internal void SetProject (AbstractProject project)
+		{
+			this.project = project;
 		}
 		
 		/// <summary>
-		///     <para>
-		///       Initializes a new instance of <see cref='.ProjectReferenceCollection'/> containing any array of <see cref='.ProjectReference'/> objects.
-		///    </para>
-		/// </summary>
-		/// <param name='value'>
-		///       A array of <see cref='.ProjectReference'/> objects with which to intialize the collection
-		/// </param>
-		public ProjectReferenceCollection(ProjectReference[] value) {
-			this.AddRange(value);
-		}
-		
-		/// <summary>
 		/// <para>Represents the entry at the specified index of the <see cref='.ProjectReference'/>.</para>
 		/// </summary>
 		/// <param name='index'><para>The zero-based index of the entry to locate in the collection.</para></param>
@@ -63,7 +46,9 @@
 				return ((ProjectReference)(List[index]));
 			}
 			set {
+				project.NotifyReferenceRemovedFromProject ((ProjectReference)List[index]);
 				List[index] = value;
+				project.NotifyReferenceAddedToProject (value);
 			}
 		}
 		
@@ -77,7 +62,9 @@
 		/// </returns>
 		/// <seealso cref='.ProjectReferenceCollection.AddRange'/>
 		public int Add(ProjectReference value) {
-			return List.Add(value);
+			int i = List.Add(value);
+			project.NotifyReferenceAddedToProject (value);
+			return i;
 		}
 		
 		/// <summary>
@@ -168,6 +155,7 @@
 		/// <seealso cref='.ProjectReferenceCollection.Add'/>
 		public void Insert(int index, ProjectReference value) {
 			List.Insert(index, value);
+			project.NotifyReferenceAddedToProject (value);
 		}
 		
 		/// <summary>
@@ -189,6 +177,7 @@
 		/// <exception cref='System.ArgumentException'><paramref name='value'/> is not found in the Collection. </exception>
 		public void Remove(ProjectReference value) {
 			List.Remove(value);
+			project.NotifyReferenceRemovedFromProject (value);
 		}
 		
 		public class ProjectReferenceEnumerator : object, IEnumerator {
Index: Main/Base/Internal/Project/Project/Collections/ProjectFileCollection.cs
===================================================================
--- Main/Base/Internal/Project/Project/Collections/ProjectFileCollection.cs	(revision 1623)
+++ Main/Base/Internal/Project/Project/Collections/ProjectFileCollection.cs	(working copy)
@@ -17,40 +17,23 @@
 	/// <seealso cref='.ProjectFileCollection'/>
 	[Serializable()]
 	public class ProjectFileCollection : CollectionBase {
+	
+		AbstractProject project;
 		
 		/// <summary>
 		///     <para>
 		///       Initializes a new instance of <see cref='.ProjectFileCollection'/>.
 		///    </para>
 		/// </summary>
-		public ProjectFileCollection() {
+		public ProjectFileCollection () {
 		}
 		
-		/// <summary>
-		///     <para>
-		///       Initializes a new instance of <see cref='.ProjectFileCollection'/> based on another <see cref='.ProjectFileCollection'/>.
-		///    </para>
-		/// </summary>
-		/// <param name='value'>
-		///       A <see cref='.ProjectFileCollection'/> from which the contents are copied
-		/// </param>
-		public ProjectFileCollection(ProjectFileCollection value) {
-			this.AddRange(value);
+		internal void SetProject (AbstractProject project)
+		{
+			this.project = project;
 		}
 		
 		/// <summary>
-		///     <para>
-		///       Initializes a new instance of <see cref='.ProjectFileCollection'/> containing any array of <see cref='.ProjectFile'/> objects.
-		///    </para>
-		/// </summary>
-		/// <param name='value'>
-		///       A array of <see cref='.ProjectFile'/> objects with which to intialize the collection
-		/// </param>
-		public ProjectFileCollection(ProjectFile[] value) {
-			this.AddRange(value);
-		}
-		
-		/// <summary>
 		/// <para>Represents the entry at the specified index of the <see cref='.ProjectFile'/>.</para>
 		/// </summary>
 		/// <param name='index'><para>The zero-based index of the entry to locate in the collection.</para></param>
@@ -63,7 +46,9 @@
 				return ((ProjectFile)(List[index]));
 			}
 			set {
+				project.NotifyFileRemovedFromProject ((ProjectFile)List[index]);
 				List[index] = value;
+				project.NotifyFileAddedToProject (value);
 			}
 		}
 		
@@ -77,7 +62,9 @@
 		/// </returns>
 		/// <seealso cref='.ProjectFileCollection.AddRange'/>
 		public int Add(ProjectFile value) {
-			return List.Add(value);
+			int i = List.Add(value);
+			project.NotifyFileAddedToProject (value);
+			return i;
 		}
 		
 		/// <summary>
@@ -168,6 +155,7 @@
 		/// <seealso cref='.ProjectFileCollection.Add'/>
 		public void Insert(int index, ProjectFile value) {
 			List.Insert(index, value);
+			project.NotifyFileAddedToProject (value);
 		}
 		
 		/// <summary>
Index: Main/Base/Internal/Project/Combine/Combine.cs
===================================================================
--- Main/Base/Internal/Project/Combine/Combine.cs	(revision 1623)
+++ Main/Base/Internal/Project/Combine/Combine.cs	(working copy)
@@ -34,11 +34,17 @@
 		/// </summary>
 		string startProject  = null;
 		bool   singleStartup = true;
+		bool   eventsAllowed = true;
 		string path          = null;
 		string outputdir     = null;
 		
-		ArrayList entries       = new ArrayList();
+		ProjectFileEventHandler fileAddedToProjectHandler;
+		ProjectFileEventHandler fileRemovedFromProjectHandler;
+		ProjectReferenceEventHandler referenceAddedToProjectHandler;
+		ProjectReferenceEventHandler referenceRemovedFromProjectHandler;
 		
+		CombineEntryCollection entries = new CombineEntryCollection();
+		
 		CombineConfiguration activeConfiguration;
 		
 		Hashtable configurations            = new Hashtable();
@@ -71,7 +77,7 @@
 			}
 		}
 		[Browsable(false)]
-		public ArrayList Entries {
+		public ICombineEntryCollection Entries {
 			get {
 				return entries;
 			}
@@ -162,6 +168,10 @@
 		
 		public Combine()
 		{
+			fileAddedToProjectHandler = new ProjectFileEventHandler (NotifyFileAddedToProject);
+			fileRemovedFromProjectHandler = new ProjectFileEventHandler (NotifyFileRemovedFromProject);
+			referenceAddedToProjectHandler = new ProjectReferenceEventHandler (NotifyReferenceAddedToProject);
+			referenceRemovedFromProjectHandler = new ProjectReferenceEventHandler (NotifyReferenceRemovedFromProject);
 		}
 		
 		public Combine(string filename)
@@ -192,7 +202,6 @@
 			doc.Load(filename);
 			path = Path.GetDirectoryName(filename);
 			
-			
 			XmlElement root = doc.DocumentElement;
 			
 			name          = root.Attributes["name"].InnerText;
@@ -204,10 +213,16 @@
 			XmlNodeList nodes = root["Entries"].ChildNodes;
 			entries.Clear();
 			FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
-			foreach (XmlElement el in nodes) {
-				string abs_path = fileUtilityService.RelativeToAbsolutePath(path, el.Attributes["filename"].InnerText);
-				AddEntry(abs_path);
+			eventsAllowed = false;
+			try {
+				foreach (XmlElement el in nodes) {
+					string abs_path = fileUtilityService.RelativeToAbsolutePath(path, el.Attributes["filename"].InnerText);
+					AddEntry(abs_path);
+				}
 			}
+			finally {
+				eventsAllowed = true;
+			}
 			
 			nodes = root["StartMode"].ChildNodes;
 			combineExecuteDefinitions.Clear();
@@ -378,7 +393,15 @@
 				foreach (DictionaryEntry entry in configurations) {
 					CombineConfiguration conf = (CombineConfiguration)entry.Value;
 					conf.AddEntry(project);
-				}				
+				}
+				if (eventsAllowed)
+					OnEntryAdded (new CombineEntryEventArgs (this, newEntry));
+				
+				newEntry.Project.FileRemovedFromProject += fileAddedToProjectHandler;
+				newEntry.Project.FileAddedToProject += fileRemovedFromProjectHandler;
+				newEntry.Project.ReferenceRemovedFromProject += referenceAddedToProjectHandler;
+				newEntry.Project.ReferenceAddedToProject += referenceRemovedFromProjectHandler;
+				
 				return project;
 			} else {
 				Combine combine = new Combine(filename);
@@ -401,10 +424,41 @@
 					CombineConfiguration conf = (CombineConfiguration)entry.Value;
 					conf.AddEntry(combine);
 				}
+				if (eventsAllowed)
+					OnEntryAdded (new CombineEntryEventArgs (this, newEntry));
+					
+				newEntry.Combine.FileRemovedFromProject += fileAddedToProjectHandler;
+				newEntry.Combine.FileAddedToProject += fileRemovedFromProjectHandler;
+				newEntry.Combine.ReferenceRemovedFromProject += referenceAddedToProjectHandler;
+				newEntry.Combine.ReferenceAddedToProject += referenceRemovedFromProjectHandler;
+				
 				return combine;
 			}
 		}
 		
+		public void RemoveEntry (CombineEntry entry)
+		{
+			ProjectCombineEntry pce = entry as ProjectCombineEntry;
+			if (pce != null) {
+				pce.Project.FileRemovedFromProject -= fileAddedToProjectHandler;
+				pce.Project.FileAddedToProject -= fileRemovedFromProjectHandler;
+				pce.Project.ReferenceRemovedFromProject -= referenceAddedToProjectHandler;
+				pce.Project.ReferenceAddedToProject -= referenceRemovedFromProjectHandler;
+			}
+			else {
+				CombineCombineEntry cce = entry as CombineCombineEntry;
+				if (cce != null) {
+					cce.Combine.FileRemovedFromProject -= fileAddedToProjectHandler;
+					cce.Combine.FileAddedToProject -= fileRemovedFromProjectHandler;
+					cce.Combine.ReferenceRemovedFromProject -= referenceAddedToProjectHandler;
+					cce.Combine.ReferenceAddedToProject -= referenceRemovedFromProjectHandler;
+				}
+			}
+				
+			entries.Remove (entry);
+			OnEntryRemoved (new CombineEntryEventArgs (this, entry));
+		}
+		
 		public void SaveAllProjects()
 		{
 			foreach (CombineEntry entry in entries) {
@@ -460,7 +514,7 @@
 			} else {
 				foreach (CombineExecuteDefinition ced in combineExecuteDefinitions) {
 					if (ced.Type == EntryExecuteType.Execute) {
-						StartProject(Entries.IndexOf(ced.Entry));
+						StartProject(entries.IndexOf(ced.Entry));
 					}
 				}
 			}
@@ -606,6 +660,26 @@
 			stream.Close ();
 		}
 		
+		internal void NotifyFileRemovedFromProject (object sender, ProjectFileEventArgs e)
+		{
+			OnFileRemovedFromProject (e);
+		}
+		
+		internal void NotifyFileAddedToProject (object sender, ProjectFileEventArgs e)
+		{
+			OnFileAddedToProject (e);
+		}
+		
+		internal void NotifyReferenceRemovedFromProject (object sender, ProjectReferenceEventArgs e)
+		{
+			OnReferenceRemovedFromProject (e);
+		}
+		
+		internal void NotifyReferenceAddedToProject (object sender, ProjectReferenceEventArgs e)
+		{
+			OnReferenceAddedToProject (e);
+		}
+		
 		protected virtual void OnStartupPropertyChanged(EventArgs e)
 		{
 			if (StartupPropertyChanged != null) {
@@ -621,8 +695,56 @@
 			}
 		}
 		
+		protected virtual void OnEntryAdded(CombineEntryEventArgs e)
+		{
+			if (EntryAdded != null) {
+				EntryAdded (this, e);
+			}
+		}
+		
+		protected virtual void OnEntryRemoved(CombineEntryEventArgs e)
+		{
+			if (EntryRemoved != null) {
+				EntryRemoved (this, e);
+			}
+		}
+		
+		protected virtual void OnFileRemovedFromProject (ProjectFileEventArgs e)
+		{
+			if (FileRemovedFromProject != null) {
+				FileRemovedFromProject (this, e);
+			}
+		}
+		
+		protected virtual void OnFileAddedToProject (ProjectFileEventArgs e)
+		{
+			if (FileAddedToProject != null) {
+				FileAddedToProject (this, e);
+			}
+		}
+		
+		protected virtual void OnReferenceRemovedFromProject (ProjectReferenceEventArgs e)
+		{
+			if (ReferenceRemovedFromProject != null) {
+				ReferenceRemovedFromProject (this, e);
+			}
+		}
+		
+		protected virtual void OnReferenceAddedToProject (ProjectReferenceEventArgs e)
+		{
+			if (ReferenceAddedToProject != null) {
+				ReferenceAddedToProject (this, e);
+			}
+		}
+
 		public event EventHandler NameChanged;
 		public event EventHandler StartupPropertyChanged;
+		public event CombineEntryEventHandler EntryAdded;
+		public event CombineEntryEventHandler EntryRemoved;
+		public event ProjectFileEventHandler FileAddedToProject;
+		public event ProjectFileEventHandler FileRemovedFromProject;
+		public event ProjectReferenceEventHandler ReferenceAddedToProject;
+		public event ProjectReferenceEventHandler ReferenceRemovedFromProject;
 	}
 	
 	public class CombineActiveConfigurationTypeConverter : TypeConverter
Index: Main/Base/Internal/Project/Combine/CombineEntry.cs
===================================================================
--- Main/Base/Internal/Project/Combine/CombineEntry.cs	(revision 1623)
+++ Main/Base/Internal/Project/Combine/CombineEntry.cs	(working copy)
@@ -266,4 +266,52 @@
 		{
 		}
 	}
+
+	
+	public interface ICombineEntryCollection: IEnumerable
+	{
+		int Count { get; }
+		CombineEntry this [int n] { get; }
+		IEnumerator GetEnumerator ();
+	}
+	
+	public class CombineEntryCollection: ICombineEntryCollection
+	{
+		ArrayList list = new ArrayList ();
+		
+		public int Count
+		{
+			get { return list.Count; }
+		}
+		
+		public CombineEntry this [int n]
+		{
+			get { return (CombineEntry) list[n]; }
+		}
+		
+		public IEnumerator GetEnumerator ()
+		{
+			return list.GetEnumerator ();
+		}
+		
+		public void Add (CombineEntry entry)
+		{
+			list.Add (entry);
+		}
+		
+		public void Remove (CombineEntry entry)
+		{
+			list.Remove (entry);
+		}
+		
+		public int IndexOf (CombineEntry entry)
+		{
+			return list.IndexOf (entry);
+		}
+		
+		public void Clear ()
+		{
+			list.Clear ();
+		}
+	}
 }
 Index: Main/Base/Gui/Pads/ProjectBrowser/BrowserNode/ProjectBrowserNode.cs
===================================================================
--- Main/Base/Gui/Pads/ProjectBrowser/BrowserNode/ProjectBrowserNode.cs	(revision 1623)
+++ Main/Base/Gui/Pads/ProjectBrowser/BrowserNode/ProjectBrowserNode.cs	(working copy)
@@ -125,7 +125,7 @@
 			}
 			
 			Debug.Assert(removeEntry != null);
-			cmb.Entries.Remove(removeEntry);
+			cmb.RemoveEntry (removeEntry);
 			
 			// remove execute definition
 			CombineExecuteDefinition removeExDef = null;
Index: Main/Base/Gui/Pads/ProjectBrowser/BrowserNode/CombineBrowserNode.cs
===================================================================
--- Main/Base/Gui/Pads/ProjectBrowser/BrowserNode/CombineBrowserNode.cs	(revision 1623)
+++ Main/Base/Gui/Pads/ProjectBrowser/BrowserNode/CombineBrowserNode.cs	(working copy)
@@ -118,7 +118,7 @@
 			}
 			
 			Debug.Assert(removeEntry != null);
-			cmbNode.Combine.Entries.Remove(removeEntry);
+			cmbNode.Combine.RemoveEntry (removeEntry);
 			
 			// remove execute definition
 			CombineExecuteDefinition removeExDef = null;

--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=persistence.diff
Content-Type: text/x-patch; name=persistence.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: Main/Base/Internal/Parser/PersistenceLayer/PersistentIndexer.cs
===================================================================
--- Main/Base/Internal/Parser/PersistenceLayer/PersistentIndexer.cs	(revision 1623)
+++ Main/Base/Internal/Parser/PersistenceLayer/PersistentIndexer.cs	(working copy)
@@ -11,56 +11,38 @@
 
 namespace MonoDevelop.Internal.Parser
 {
+	[Serializable]
 	public sealed class PersistentIndexer : AbstractIndexer
 	{
-		public PersistentIndexer(BinaryReader reader, ClassProxyCollection classProxyCollection)
+		public static PersistentIndexer Read (BinaryReader reader, INameDecoder nameTable)
 		{
-			FullyQualifiedName = reader.ReadString();
-			Documentation      = reader.ReadString();
-			modifiers          = (ModifierEnum)reader.ReadUInt32();
+			PersistentIndexer ind = new PersistentIndexer();
+			ind.FullyQualifiedName = PersistentHelper.ReadString (reader, nameTable);
+			ind.Documentation = PersistentHelper.ReadString (reader, nameTable);
+			ind.modifiers = (ModifierEnum)reader.ReadUInt32();
+			ind.returnType = PersistentReturnType.Read (reader, nameTable);
 			
-			returnType         = new PersistentReturnType(reader, classProxyCollection);
-			if (returnType.Name == null) {
-				returnType = null;
-			}
-			
 			uint count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				parameters.Add(new PersistentParameter(reader, classProxyCollection));
+				ind.parameters.Add (PersistentParameter.Read (reader, nameTable));
 			}
+			ind.region = PersistentRegion.Read (reader, nameTable);
+			return ind;
 		}
 		
-		public void WriteTo(BinaryWriter writer)
+		public static void WriteTo (IIndexer ind, BinaryWriter writer, INameEncoder nameTable)
 		{
-			writer.Write(FullyQualifiedName);
-			writer.Write(Documentation);
+			PersistentHelper.WriteString (ind.FullyQualifiedName, writer, nameTable);
+			PersistentHelper.WriteString (ind.Documentation, writer, nameTable);
 			
-			writer.Write((uint)modifiers);
-			((PersistentReturnType)returnType).WriteTo(writer);
+			writer.Write((uint)ind.Modifiers);
+			PersistentReturnType.WriteTo (ind.ReturnType, writer, nameTable);
 			
-			writer.Write((uint)parameters.Count);
-			foreach (PersistentParameter p in parameters) {
-				p.WriteTo(writer);
+			writer.Write ((uint)ind.Parameters.Count);
+			foreach (IParameter p in ind.Parameters) {
+				PersistentParameter.WriteTo (p, writer, nameTable);
 			}
+			PersistentRegion.WriteTo (ind.Region, writer, nameTable);
 		}
-		
-		public PersistentIndexer(ClassProxyCollection classProxyCollection, IIndexer indexer)
-		{
-			FullyQualifiedName = indexer.Name;
-			if (indexer.Documentation != null) {
-				Documentation = indexer.Documentation;
-			} else {
-				Documentation = String.Empty;
-			}
-			modifiers = indexer.Modifiers;
-			returnType         = new PersistentReturnType(classProxyCollection, indexer.ReturnType);
-			
-			foreach (IParameter param in indexer.Parameters) {
-				parameters.Add(new PersistentParameter(classProxyCollection, param));
-			}
-			
-			region = getterRegion = setterRegion = null;
-		}
-		
 	}
 }
Index: Main/Base/Internal/Parser/PersistenceLayer/PersistentParameter.cs
===================================================================
--- Main/Base/Internal/Parser/PersistenceLayer/PersistentParameter.cs	(revision 1623)
+++ Main/Base/Internal/Parser/PersistenceLayer/PersistentParameter.cs	(working copy)
@@ -11,39 +11,25 @@
 
 namespace MonoDevelop.Internal.Parser
 {
+	[Serializable]
 	public sealed class PersistentParameter : AbstractParameter
 	{
-		public PersistentParameter(BinaryReader reader, ClassProxyCollection classProxyCollection)
+		public static PersistentParameter Read (BinaryReader reader, INameDecoder nameTable)
 		{
-			name     = reader.ReadString();
-			documentation      = reader.ReadString();
-
-			modifier = (ParameterModifier)reader.ReadByte();
-						
-			returnType = new PersistentReturnType(reader, classProxyCollection);
-			if (returnType.Name == null) {
-				returnType = null;
-			}
+			PersistentParameter par = new PersistentParameter ();
+			par.name = PersistentHelper.ReadString (reader, nameTable);
+			par.documentation = PersistentHelper.ReadString (reader, nameTable);
+			par.modifier = (ParameterModifier)reader.ReadByte();
+			par.returnType = PersistentReturnType.Read (reader, nameTable);
+			return par;
 		}
 		
-		public void WriteTo(BinaryWriter writer)
+		public static void WriteTo (IParameter p, BinaryWriter writer, INameEncoder nameTable)
 		{
-			writer.Write(name);
-			writer.Write(documentation);
-			writer.Write((byte)modifier);
-			((PersistentReturnType)returnType).WriteTo(writer);
+			PersistentHelper.WriteString (p.Name, writer, nameTable);
+			PersistentHelper.WriteString (p.Documentation, writer, nameTable);
+			writer.Write((byte)p.Modifier);
+			PersistentReturnType.WriteTo (p.ReturnType, writer, nameTable);
 		}
-		
-		public PersistentParameter(ClassProxyCollection classProxyCollection, IParameter param)
-		{
-			name          = param.Name;
-			documentation = param.Documentation;
-			if (documentation == null) {
-				documentation = String.Empty;
-			}
-			
-			returnType = new PersistentReturnType(classProxyCollection, param.ReturnType);
-			modifier   = param.Modifier;
-		}
 	}
 }
Index: Main/Base/Internal/Parser/PersistenceLayer/PersistentMethod.cs
===================================================================
--- Main/Base/Internal/Parser/PersistenceLayer/PersistentMethod.cs	(revision 1623)
+++ Main/Base/Internal/Parser/PersistenceLayer/PersistentMethod.cs	(working copy)
@@ -12,56 +12,39 @@
 
 namespace MonoDevelop.Internal.Parser
 {
+	[Serializable]
 	public sealed class PersistentMethod : AbstractMethod
 	{
-		public PersistentMethod(BinaryReader reader, ClassProxyCollection classProxyCollection)
+		public static PersistentMethod Read (BinaryReader reader, INameDecoder nameTable)
 		{
-			FullyQualifiedName = reader.ReadString();
-			Documentation      = reader.ReadString();
+			PersistentMethod met = new PersistentMethod ();
+			met.FullyQualifiedName = PersistentHelper.ReadString (reader, nameTable);
+			met.Documentation = PersistentHelper.ReadString (reader, nameTable);
 			
-			modifiers          = (ModifierEnum)reader.ReadUInt32();
-			returnType         = new PersistentReturnType(reader, classProxyCollection);
-			if (returnType.Name == null) {
-				returnType = null;
-			}
+			met.modifiers = (ModifierEnum)reader.ReadUInt32();
+			met.returnType = PersistentReturnType.Read (reader, nameTable);
 			
 			uint count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				parameters.Add(new PersistentParameter(reader, classProxyCollection));
+				met.parameters.Add (PersistentParameter.Read (reader, nameTable));
 			}
+			met.region = PersistentRegion.Read (reader, nameTable);
+			return met;
 		}
 		
-		public void WriteTo(BinaryWriter writer)
+		public static void WriteTo (IMethod met, BinaryWriter writer, INameEncoder nameTable)
 		{
-			writer.Write(FullyQualifiedName);
-			writer.Write(Documentation);
-			writer.Write((uint)modifiers);
-			((PersistentReturnType)returnType).WriteTo(writer);
+			PersistentHelper.WriteString (met.FullyQualifiedName, writer, nameTable);
+			PersistentHelper.WriteString (met.Documentation, writer, nameTable);
 			
-			writer.Write((uint)parameters.Count);
-			foreach (PersistentParameter p in parameters) {
-				p.WriteTo(writer);
-			}
-		}
-		
-		public PersistentMethod(ClassProxyCollection classProxyCollection, IMethod method)
-		{
-			FullyQualifiedName = method.Name;
-			if (method.Documentation != null) {
-				Documentation = method.Documentation;
-			} else {
-				Documentation = String.Empty;
-			}
+			writer.Write ((uint)met.Modifiers);
+			PersistentReturnType.WriteTo (met.ReturnType, writer, nameTable);
 			
-			modifiers  = method.Modifiers;
-			returnType = new PersistentReturnType(classProxyCollection, method.ReturnType);
-			
-			foreach (IParameter param in method.Parameters) {
-				parameters.Add(new PersistentParameter(classProxyCollection, param));
+			writer.Write (met.Parameters != null ? (uint)met.Parameters.Count : (uint)0);
+			foreach (IParameter p in met.Parameters) {
+				PersistentParameter.WriteTo (p, writer, nameTable);
 			}
-			
-			region = null;
+			PersistentRegion.WriteTo (met.Region, writer, nameTable);
 		}
-		
 	}
 }
Index: Main/Base/Internal/Parser/PersistenceLayer/PersistentReturnType.cs
===================================================================
--- Main/Base/Internal/Parser/PersistenceLayer/PersistentReturnType.cs	(revision 1623)
+++ Main/Base/Internal/Parser/PersistenceLayer/PersistentReturnType.cs	(working copy)
@@ -10,115 +10,41 @@
 
 namespace MonoDevelop.Internal.Parser
 {
-	public sealed class PersistentReturnType : IReturnType
+	[Serializable]
+	public sealed class PersistentReturnType : AbstractReturnType
 	{
-		string               fullyQualifiedName;
-
-		int                  classProxyIndex;
-		ClassProxyCollection classProxyCollection;
-
-		int   pointerNestingLevel = -1;
-		int[] arrayDimensions     = new int[] {};
-
-		public PersistentReturnType(BinaryReader reader, ClassProxyCollection classProxyCollection)
+		public static PersistentReturnType Read (BinaryReader reader, INameDecoder nameTable)
 		{
-			this.classProxyCollection = classProxyCollection;
-			classProxyIndex      = reader.ReadInt32();
+			if (PersistentHelper.ReadNull (reader)) return null;
+			
+			PersistentReturnType rt = new PersistentReturnType ();
+			rt.FullyQualifiedName = PersistentHelper.ReadString (reader, nameTable);
 
-			if (classProxyIndex < 0) {
-				fullyQualifiedName = reader.ReadString();
-			}
+			rt.pointerNestingLevel = reader.ReadInt32();
 
-			pointerNestingLevel = reader.ReadInt32();
-
 			uint count = reader.ReadUInt32();
-			arrayDimensions = new int[count];
-			for (uint i = 0; i < arrayDimensions.Length; ++i) {
-				arrayDimensions[i] = reader.ReadInt32();
+			rt.arrayDimensions = new int[count];
+			for (uint i = 0; i < rt.arrayDimensions.Length; ++i) {
+				rt.arrayDimensions[i] = reader.ReadInt32();
 			}
+			return rt;
 		}
 
-		public void WriteTo(BinaryWriter writer)
+		public static void WriteTo (IReturnType rt, BinaryWriter writer, INameEncoder nameTable)
 		{
-			writer.Write(classProxyIndex);
-			if (classProxyIndex < 0) {
-				writer.Write(fullyQualifiedName);
-			}
-			writer.Write(pointerNestingLevel);
-			if (arrayDimensions == null) {
+			if (PersistentHelper.WriteNull (rt, writer)) return;
+			
+			PersistentHelper.WriteString (rt.FullyQualifiedName, writer, nameTable);
+
+			writer.Write (rt.PointerNestingLevel);
+			if (rt.ArrayDimensions == null) {
 				writer.Write((uint)0);
 			} else {
-				writer.Write((uint)arrayDimensions.Length);
-				for (uint i = 0; i < arrayDimensions.Length; ++i) {
-					writer.Write(arrayDimensions[i]);
+				writer.Write((uint)rt.ArrayDimensions.Length);
+				for (uint i = 0; i < rt.ArrayDimensions.Length; ++i) {
+					writer.Write (rt.ArrayDimensions[i]);
 				}
 			}
 		}
-
-		public PersistentReturnType(ClassProxyCollection classProxyCollection, IReturnType returnType)
-		{
-			if (returnType == null) {
-				classProxyIndex    = - 1;
-				fullyQualifiedName = String.Empty;
-			} else {
-				this.classProxyCollection = classProxyCollection;
-				this.pointerNestingLevel  = returnType.PointerNestingLevel;
-				this.arrayDimensions      = returnType.ArrayDimensions;
-				classProxyIndex           = classProxyCollection.IndexOf(returnType.FullyQualifiedName, true);
-				fullyQualifiedName        = returnType.FullyQualifiedName;
-			}
-		}
-
-		public string FullyQualifiedName {
-			get {
-				if (classProxyIndex < 0) {
-					return fullyQualifiedName;
-				}
-				return classProxyCollection[classProxyIndex].FullyQualifiedName;
-			}
-		}
-
-		public string Name {
- 			get {
-				string[] name = FullyQualifiedName.Split(new char[] {'.'});
-				return name[name.Length - 1];
-			}
-		}
-
-		public string Namespace {
-			get {
-				int index = FullyQualifiedName.LastIndexOf('.');
-				return index < 0 ? String.Empty : FullyQualifiedName.Substring(0, index);
-			}
-		}
-
-		public int PointerNestingLevel {
-			get {
-				return pointerNestingLevel;
-			}
-		}
-
-		public int ArrayCount {
-			get {
-				return ArrayDimensions.Length;
-			}
-		}
-
-		public int[] ArrayDimensions {
-			get {
-				return arrayDimensions;
-			}
-		}
-
-       int IComparable.CompareTo(object value) {
-          return 0;
-       }
-
-		// stub
-       	public object DeclaredIn {
-       		get {
-       			return null;
-       		}
-       	}
 	}
 }
Index: Main/Base/Internal/Parser/PersistenceLayer/PersistentEvent.cs
===================================================================
--- Main/Base/Internal/Parser/PersistenceLayer/PersistentEvent.cs	(revision 1623)
+++ Main/Base/Internal/Parser/PersistenceLayer/PersistentEvent.cs	(working copy)
@@ -11,39 +11,27 @@
 
 namespace MonoDevelop.Internal.Parser
 {
+	[Serializable]
 	public sealed class PersistentEvent : AbstractEvent
 	{
-		public PersistentEvent(BinaryReader reader, ClassProxyCollection classProxyCollection)
+		public static PersistentEvent Read (BinaryReader reader, INameDecoder nameTable)
 		{
-			FullyQualifiedName = reader.ReadString();
-			Documentation      = reader.ReadString();
-			modifiers          = (ModifierEnum)reader.ReadUInt32();
-
-			returnType         = new PersistentReturnType(reader, classProxyCollection);
-			if (returnType.Name == null) {
-				returnType = null;
-			}
+			PersistentEvent ev = new PersistentEvent();
+			ev.FullyQualifiedName = PersistentHelper.ReadString (reader, nameTable);
+			ev.Documentation = PersistentHelper.ReadString (reader, nameTable);
+			ev.modifiers = (ModifierEnum)reader.ReadUInt32();
+			ev.returnType = PersistentReturnType.Read (reader, nameTable);
+			ev.region = PersistentRegion.Read (reader, nameTable);
+			return ev;
 		}
 
-		public void WriteTo(BinaryWriter writer)
+		public static void WriteTo (IEvent ev, BinaryWriter writer, INameEncoder nameTable)
 		{
-			writer.Write(FullyQualifiedName);
-			writer.Write(Documentation);
-			writer.Write((uint)modifiers);
-			((PersistentReturnType)returnType).WriteTo(writer);
+			PersistentHelper.WriteString (ev.FullyQualifiedName, writer, nameTable);
+			PersistentHelper.WriteString (ev.Documentation, writer, nameTable);
+			writer.Write ((uint)ev.Modifiers);
+			PersistentReturnType.WriteTo (ev.ReturnType, writer, nameTable);
+			PersistentRegion.WriteTo (ev.Region, writer, nameTable);
 		}
-
-		public PersistentEvent(ClassProxyCollection classProxyCollection, IEvent e)
-		{
-			modifiers          = e.Modifiers;
-			FullyQualifiedName = e.Name;
-			if (e.Documentation != null) {
-				Documentation = e.Documentation;
-			} else {
-				Documentation = String.Empty;
-			}
-
-			returnType         = new PersistentReturnType(classProxyCollection, e.ReturnType);
-		}
 	}
 }
Index: Main/Base/Internal/Parser/PersistenceLayer/PersistentField.cs
===================================================================
--- Main/Base/Internal/Parser/PersistenceLayer/PersistentField.cs	(revision 1623)
+++ Main/Base/Internal/Parser/PersistenceLayer/PersistentField.cs	(working copy)
@@ -11,39 +11,27 @@
 
 namespace MonoDevelop.Internal.Parser
 {
+	[Serializable]
 	public sealed class PersistentField : AbstractField
 	{
-		public PersistentField(BinaryReader reader, ClassProxyCollection classProxyCollection)
+		public static PersistentField Read (BinaryReader reader, INameDecoder nameTable)
 		{
-			FullyQualifiedName = reader.ReadString();
-			Documentation      = reader.ReadString();
-			modifiers          = (ModifierEnum)reader.ReadUInt32();
-			
-			returnType         = new PersistentReturnType(reader, classProxyCollection);
-			if (returnType.Name == null) {
-				returnType = null;
-			}
+			PersistentField field = new PersistentField ();
+			field.FullyQualifiedName = PersistentHelper.ReadString (reader, nameTable);
+			field.Documentation = PersistentHelper.ReadString (reader, nameTable);
+			field.modifiers = (ModifierEnum)reader.ReadUInt32();
+			field.returnType = PersistentReturnType.Read (reader, nameTable);
+			field.region = PersistentRegion.Read (reader, nameTable);
+			return field;
 		}
 		
-		public void WriteTo(BinaryWriter writer)
+		public static void WriteTo (IField field, BinaryWriter writer, INameEncoder nameTable)
 		{
-			writer.Write(FullyQualifiedName);
-			writer.Write(Documentation);
-			writer.Write((uint)modifiers);
-			((PersistentReturnType)returnType).WriteTo(writer);
+			PersistentHelper.WriteString (field.FullyQualifiedName, writer, nameTable);
+			PersistentHelper.WriteString (field.Documentation, writer, nameTable);
+			writer.Write ((uint)field.Modifiers);
+			PersistentReturnType.WriteTo (field.ReturnType, writer, nameTable);
+			PersistentRegion.WriteTo (field.Region, writer, nameTable);
 		}
-		
-		public PersistentField(ClassProxyCollection classProxyCollection, IField field)
-		{
-			modifiers          = field.Modifiers;
-			FullyQualifiedName = field.Name;
-			
-			if (field.Documentation != null) {
-				Documentation = field.Documentation;
-			}  else {
-				Documentation = String.Empty;
-			}
-			returnType         = new PersistentReturnType(classProxyCollection, field.ReturnType);
-		}
 	}
 }
Index: Main/Base/Internal/Parser/PersistenceLayer/PersistentProperty.cs
===================================================================
--- Main/Base/Internal/Parser/PersistenceLayer/PersistentProperty.cs	(revision 1623)
+++ Main/Base/Internal/Parser/PersistenceLayer/PersistentProperty.cs	(working copy)
@@ -11,6 +11,7 @@
 
 namespace MonoDevelop.Internal.Parser
 {
+	[Serializable]
 	public sealed class PersistentProperty : AbstractProperty
 	{
 		const uint canGetFlag = (uint)(1 << 29);
@@ -31,45 +32,27 @@
 			}
 		}
 		
-		public PersistentProperty(BinaryReader reader, ClassProxyCollection classProxyCollection)
+		public static PersistentProperty Read (BinaryReader reader, INameDecoder nameTable)
 		{
-			FullyQualifiedName = reader.ReadString();
-			Documentation      = reader.ReadString();
+			PersistentProperty pro = new PersistentProperty ();
+			pro.FullyQualifiedName = PersistentHelper.ReadString (reader, nameTable);
+			pro.Documentation = PersistentHelper.ReadString (reader, nameTable);
 			uint m = reader.ReadUInt32();
-			modifiers          = (ModifierEnum)(m & (canGetFlag - 1));
-			canGet             = (m & canGetFlag) == canGetFlag;
-			canSet             = (m & canSetFlag) == canSetFlag;
-			
-			returnType         = new PersistentReturnType(reader, classProxyCollection);
-			if (returnType.Name == null) {
-				returnType = null;
-			}
+			pro.modifiers = (ModifierEnum)(m & (canGetFlag - 1));
+			pro.canGet = (m & canGetFlag) == canGetFlag;
+			pro.canSet = (m & canSetFlag) == canSetFlag;
+			pro.returnType = PersistentReturnType.Read (reader, nameTable);
+			pro.region = PersistentRegion.Read (reader, nameTable);
+			return pro;
 		}
 		
-		public void WriteTo(BinaryWriter writer)
+		public static void WriteTo (IProperty p, BinaryWriter writer, INameEncoder nameTable)
 		{
-			writer.Write(FullyQualifiedName);
-			writer.Write(Documentation);
-			writer.Write((uint)modifiers + (CanGet ? canGetFlag : 0) + (CanSet ? canSetFlag : 0));
-			((PersistentReturnType)returnType).WriteTo(writer);
+			PersistentHelper.WriteString (p.FullyQualifiedName, writer, nameTable);
+			PersistentHelper.WriteString (p.Documentation, writer, nameTable);
+			writer.Write((uint)p.Modifiers + (p.CanGet ? canGetFlag : 0) + (p.CanSet ? canSetFlag : 0));
+			PersistentReturnType.WriteTo (p.ReturnType, writer, nameTable);
+			PersistentRegion.WriteTo (p.Region, writer, nameTable);
 		}
-		
-		public PersistentProperty(ClassProxyCollection classProxyCollection, IProperty property)
-		{
-			FullyQualifiedName = property.Name;
-			modifiers          = property.Modifiers;
-			if (property.Documentation != null) {
-				Documentation = property.Documentation;
-			} else {
-				Documentation = String.Empty;
-			}
-			
-			if (property.ReturnType != null) {
-				returnType     = new PersistentReturnType(classProxyCollection, property.ReturnType);
-			}
-			region = getterRegion = setterRegion = null;
-			canGet = property.CanGet;
-			canSet = property.CanSet;
-		}
 	}
 }
Index: Main/Base/Internal/Parser/PersistenceLayer/PersistentClass.cs
===================================================================
--- Main/Base/Internal/Parser/PersistenceLayer/PersistentClass.cs	(revision 1623)
+++ Main/Base/Internal/Parser/PersistenceLayer/PersistentClass.cs	(working copy)
@@ -15,424 +15,176 @@
 
 namespace MonoDevelop.Internal.Parser
 {
-	public sealed class PersistentClass : IClass
+	[Serializable]
+	public sealed class PersistentClass : AbstractClass
 	{
-		int                  classProxyIndex;
-		ClassProxyCollection classProxyCollection;
-
-		// an int arraylist of base types.
-		ArrayList          baseTypes         = new ArrayList();
-
-		/// <remarks>
-		/// This collection is only used during creation, if for a basetype no
-		/// proxy index could be determined. It contains all those names as real name.
-		/// They should be read to <code>baseTypesStringCollection</code> when the persistant
-		/// class is read.
-		/// </remarks>
-		StringCollection   notFoundBaseTypes = new StringCollection();
-
-		StringCollection   baseTypesStringCollection = new StringCollection();
-
-		ClassCollection    innerClasses = new ClassCollection();
-		FieldCollection    fields       = new FieldCollection();
-		PropertyCollection properties   = new PropertyCollection();
-		MethodCollection   methods      = new MethodCollection();
-		EventCollection    events       = new EventCollection();
-		IndexerCollection  indexer      = new IndexerCollection();
-
-
-		string       fullyQualifiedName;
-		string       documentation;
-		ClassType    classType;
-		ModifierEnum modifiers;
-
-		public ICompilationUnit CompilationUnit {
+		public override ICompilationUnit CompilationUnit {
 			get {
 				return null;
 			}
 		}
 
-		public PersistentClass(BinaryReader reader, ClassProxyCollection classProxyCollection)
+		public static PersistentClass Read (BinaryReader reader, INameDecoder nameTable)
 		{
-			this.classProxyCollection = classProxyCollection;
-			classProxyIndex = reader.ReadInt32();
+			PersistentClass cls = new PersistentClass ();
+			
+			cls.FullyQualifiedName = PersistentHelper.ReadString (reader, nameTable);
+			cls.Documentation = PersistentHelper.ReadString (reader, nameTable);
+			
+			cls.modifiers          = (ModifierEnum)reader.ReadUInt32();
+			cls.classType          = (ClassType)reader.ReadInt16();
 
-			if (classProxyIndex < 0) {
-				fullyQualifiedName = reader.ReadString();
-				documentation      = reader.ReadString();
-				modifiers          = (ModifierEnum)reader.ReadUInt32();
-				classType          = (ClassType)reader.ReadInt16();
-			}
-
 			uint count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				int baseTypeIndex = reader.ReadInt32();
-				if (baseTypeIndex < 0) {
-					baseTypesStringCollection.Add(reader.ReadString());
-				} else {
-					baseTypes.Add(baseTypeIndex);
-				}
+				cls.baseTypes.Add (PersistentHelper.ReadString (reader, nameTable));
 			}
-
+			
 			count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				innerClasses.Add(new PersistentClass(reader, classProxyCollection));
+				cls.innerClasses.Add(PersistentClass.Read (reader, nameTable));
 			}
 
 			count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				fields.Add(new PersistentField(reader, classProxyCollection));
+				cls.fields.Add(PersistentField.Read (reader, nameTable));
 			}
 
 			count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				properties.Add(new PersistentProperty(reader, classProxyCollection));
+				cls.properties.Add(PersistentProperty.Read (reader, nameTable));
 			}
 
 			count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				IMethod m = new PersistentMethod(reader, classProxyCollection);
-				methods.Add(m);
+				IMethod m = PersistentMethod.Read (reader, nameTable);
+				cls.methods.Add(m);
 			}
 
 			count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				events.Add(new PersistentEvent(reader, classProxyCollection));
+				cls.events.Add(PersistentEvent.Read (reader, nameTable));
 			}
 
 			count = reader.ReadUInt32();
 			for (uint i = 0; i < count; ++i) {
-				indexer.Add(new PersistentIndexer(reader, classProxyCollection));
+				cls.indexer.Add(PersistentIndexer.Read (reader, nameTable));
 			}
+			
+			cls.region = PersistentRegion.Read (reader, nameTable);
+			return cls;
 		}
 
-		public void WriteTo(BinaryWriter writer)
+		public static void WriteTo (IClass cls, BinaryWriter writer, INameEncoder nameTable)
 		{
-			writer.Write(classProxyIndex);
+			PersistentHelper.WriteString (cls.FullyQualifiedName, writer, nameTable);
+			PersistentHelper.WriteString (cls.Documentation, writer, nameTable);
+				
+			writer.Write((uint)cls.Modifiers);
+			writer.Write((short)cls.ClassType);
 
-			if (classProxyIndex < 0) {
-				writer.Write(fullyQualifiedName);
-				writer.Write(documentation);
-				writer.Write((uint)modifiers);
-				writer.Write((short)classType);
-			}
+			writer.Write((uint)(cls.BaseTypes.Count));
+			foreach (string baseType in cls.BaseTypes)
+				PersistentHelper.WriteString (baseType, writer, nameTable);
 
-			writer.Write((uint)(baseTypes.Count + notFoundBaseTypes.Count));
-			foreach (int baseTypeIdx in baseTypes) {
-				writer.Write(baseTypeIdx);
+			writer.Write((uint)cls.InnerClasses.Count);
+			foreach (IClass innerClass in cls.InnerClasses) {
+				PersistentClass.WriteTo (innerClass, writer, nameTable);
 			}
 
-			foreach (string baseType in notFoundBaseTypes) {
-				writer.Write((int)-1);
-				writer.Write(baseType);
+			writer.Write((uint)cls.Fields.Count);
+			foreach (IField field in cls.Fields) {
+				PersistentField.WriteTo (field, writer, nameTable);
 			}
 
-
-			writer.Write((uint)innerClasses.Count);
-			foreach (PersistentClass innerClass in innerClasses) {
-				innerClass.WriteTo(writer);
+			writer.Write((uint)cls.Properties.Count);
+			foreach (IProperty property in cls.Properties) {
+				PersistentProperty.WriteTo (property, writer, nameTable);
 			}
 
-			writer.Write((uint)fields.Count);
-			foreach (PersistentField field in fields) {
-				field.WriteTo(writer);
+			writer.Write((uint)cls.Methods.Count);
+			foreach (IMethod method in cls.Methods) {
+				PersistentMethod.WriteTo (method, writer, nameTable);
 			}
 
-			writer.Write((uint)properties.Count);
-			foreach (PersistentProperty property in properties) {
-				property.WriteTo(writer);
+			writer.Write((uint)cls.Events.Count);
+			foreach (IEvent e in cls.Events) {
+				PersistentEvent.WriteTo (e, writer, nameTable);
 			}
 
-			writer.Write((uint)methods.Count);
-			foreach (PersistentMethod method in methods) {
-				method.WriteTo(writer);
+			writer.Write((uint)cls.Indexer.Count);
+			foreach (IIndexer ind in cls.Indexer) {
+				PersistentIndexer.WriteTo (ind, writer, nameTable);
 			}
-
-			writer.Write((uint)events.Count);
-			foreach (PersistentEvent e in events) {
-				e.WriteTo(writer);
-			}
-
-			writer.Write((uint)indexer.Count);
-			foreach (PersistentIndexer ind in indexer) {
-				ind.WriteTo(writer);
-			}
+			
+			PersistentRegion.WriteTo (cls.Region, writer, nameTable);
 		}
-
-		public PersistentClass(ClassProxyCollection classProxyCollection, IClass c)
+	}
+	
+	public class PersistentRegion: DefaultRegion
+	{
+		public PersistentRegion (): base (-1,-1)
 		{
-			this.classProxyCollection = classProxyCollection;
-			classProxyIndex           = classProxyCollection.IndexOf(c.FullyQualifiedName, true);
-			if (classProxyIndex < 0) {
-				fullyQualifiedName = c.FullyQualifiedName;
-				documentation      = c.Documentation;
-				modifiers          = c.Modifiers;
-				classType          = c.ClassType;
-			}
-
-			foreach (string baseType in c.BaseTypes) {
-				int idx = classProxyCollection.IndexOf(baseType, true);
-				if (idx < 0) {
-					notFoundBaseTypes.Add(baseType);
-				} else {
-					baseTypes.Add(idx);
-				}
-			}
-
-			foreach (IClass innerClass in c.InnerClasses) {
-				innerClasses.Add(new PersistentClass(classProxyCollection, innerClass));
-			}
-
-			foreach (IField field in c.Fields) {
-				fields.Add(new PersistentField(classProxyCollection, field));
-			}
-
-			foreach (IProperty property in c.Properties) {
-				properties.Add(new PersistentProperty(classProxyCollection, property));
-			}
-
-			foreach (IMethod method in c.Methods) {
-				methods.Add(new PersistentMethod(classProxyCollection, method));
-			}
-
-			foreach (IEvent e in c.Events) {
-				events.Add(new PersistentEvent(classProxyCollection, e));
-			}
-
-			foreach (IIndexer ind in c.Indexer) {
-				indexer.Add(new PersistentIndexer(classProxyCollection, ind));
-			}
 		}
-
-		public ClassType ClassType {
-			get {
-				if (classProxyIndex < 0) {
-					return classType;
-				}
-				return classProxyCollection[classProxyIndex].ClassType;
-			}
+		
+		public static PersistentRegion Read (BinaryReader reader, INameDecoder nameTable)
+		{
+			if (PersistentHelper.ReadNull (reader)) return null;
+			
+			PersistentRegion reg = new PersistentRegion ();
+			reg.FileName = PersistentHelper.ReadString (reader, nameTable);
+			reg.beginLine = reader.ReadInt32 ();
+			reg.endLine = reader.ReadInt32 ();
+			reg.beginColumn = reader.ReadInt32 ();
+			reg.endColumn = reader.ReadInt32 ();
+			return reg;
 		}
-
-		public string FullyQualifiedName {
-			get {
-				if (classProxyIndex < 0) {
-					return fullyQualifiedName;
-				}
-				return classProxyCollection[classProxyIndex].FullyQualifiedName;
-			}
-		}
-
-		public string Name {
-			get {
-				string[] name = FullyQualifiedName.Split(new char[] {'.'});
-				return name[name.Length - 1];
-			}
-		}
-
-		public string Namespace {
-			get {
-				int index = FullyQualifiedName.LastIndexOf('.');
-				return index < 0 ? String.Empty : FullyQualifiedName.Substring(0, index);
-			}
-		}
-
-		// regions are currently useless (only assembly classes are
-		// made persistant)
-		public IRegion Region {
-			get {
-				return null;
-			}
-		}
-		public IRegion BodyRegion {
-			get {
-				return null;
-			}
-		}
-
-		public StringCollection BaseTypes {
-			get {
-				// convert base types first time they're requested
-				if (baseTypes.Count > 0) {
-					foreach (int index in baseTypes) {
-						baseTypesStringCollection.Add(classProxyCollection[index].FullyQualifiedName);
-					}
-					baseTypes.Clear();
-				}
-				return baseTypesStringCollection;
-			}
-		}
 		
-		public ClassCollection InnerClasses {
-			get {
-				return innerClasses;
-			}
+		public static void WriteTo (IRegion reg, BinaryWriter writer, INameEncoder nameTable)
+		{
+			if (PersistentHelper.WriteNull (reg, writer)) return;
+			
+			PersistentHelper.WriteString (reg.FileName, writer, nameTable);
+			writer.Write (reg.BeginLine);
+			writer.Write (reg.BeginColumn);
+			writer.Write (reg.EndColumn);
+			writer.Write (reg.EndLine);
 		}
-
-		public FieldCollection Fields {
-			get {
-				return fields;
+	}
+	
+	public class PersistentHelper
+	{
+		public static void WriteString (string s, BinaryWriter writer, INameEncoder nameTable)
+		{
+			if (s == null)
+				writer.Write (-2);
+			else {
+				int id = nameTable.GetStringId (s);
+				writer.Write (id);
+				if (id == -1)
+					writer.Write (s);
 			}
 		}
-
-		public PropertyCollection Properties {
-			get {
-				return properties;
-			}
-		}
-
-		public IndexerCollection Indexer {
-			get {
-				return indexer;
-			}
-		}
-
-		public MethodCollection Methods {
-			get {
-				return methods;
-			}
-		}
-
-		public EventCollection Events {
-			get {
-				return events;
-			}
-		}
-
-		// IDecoration implementation
-		public ModifierEnum Modifiers {
-			get {
-				if (classProxyIndex < 0) {
-					return modifiers;
-				}
-				return classProxyCollection[classProxyIndex].Modifiers;
-			}
-		}
-
-		public AttributeSectionCollection Attributes {
-			get {
+		
+		public static string ReadString (BinaryReader reader, INameDecoder nameTable)
+		{
+			int id = reader.ReadInt32 ();
+			if (id == -1)
+				return reader.ReadString ();
+			else if (id == -2)
 				return null;
-			}
+			else
+				return nameTable.GetStringValue (id);
 		}
-
-		public string Documentation {
-			get {
-				if (classProxyIndex < 0) {
-					return documentation;
-				}
-				return classProxyCollection[classProxyIndex].Documentation;
-			}
-		}
-
-		public bool IsStatic {
-			get {
-				return (Modifiers & ModifierEnum.Static) == ModifierEnum.Static;
-			}
-		}
-
-		public bool IsVirtual {
-			get {
-				return (Modifiers & ModifierEnum.Virtual) == ModifierEnum.Virtual;
-			}
-		}
-
-		public bool IsPublic {
-			get {
-				return (Modifiers & ModifierEnum.Public) == ModifierEnum.Public;
-			}
-		}
-
-		public bool IsFinal {
-			get {
-				return (Modifiers & ModifierEnum.Final) == ModifierEnum.Final;
-			}
-		}
-
-		public bool IsSpecialName {
-			get {
-				return (Modifiers & ModifierEnum.SpecialName) == ModifierEnum.SpecialName;
-			}
-		}
-
-		public bool IsProtected {
-			get {
-				return (Modifiers & ModifierEnum.Protected) == ModifierEnum.Protected;
-			}
-		}
-
-		public bool IsPrivate {
-			get {
-				return (Modifiers & ModifierEnum.Private) == ModifierEnum.Private;
-			}
-		}
-
-		public bool IsInternal {
-			get {
-				return (Modifiers & ModifierEnum.Internal) == ModifierEnum.Internal;
-			}
-		}
-
-		public bool IsProtectedAndInternal {
-			get {
-				return (Modifiers & (ModifierEnum.Internal | ModifierEnum.Protected)) == (ModifierEnum.Internal | ModifierEnum.Protected);
-			}
-		}
-
-		public bool IsProtectedOrInternal {
-			get {
-				return (Modifiers & ModifierEnum.ProtectedOrInternal) == ModifierEnum.ProtectedOrInternal;
-			}
-		}
-
-		public bool IsAbstract {
-			get {
-				return (Modifiers & ModifierEnum.Abstract) == ModifierEnum.Abstract;
-			}
-		}
-
-		public bool IsSealed {
-			get {
-				return (Modifiers & ModifierEnum.Sealed) == ModifierEnum.Sealed;
-			}
-		}
-
-		public bool IsLiteral {
-			get {
-				return (Modifiers & ModifierEnum.Const) == ModifierEnum.Const;
-			}
-		}
-
-		public bool IsReadonly {
-			get {
-				return (Modifiers & ModifierEnum.Readonly) == ModifierEnum.Readonly;
-			}
-		}
-		public bool IsOverride {
-			get {
-				return (Modifiers & ModifierEnum.Override) == ModifierEnum.Override;
-			}
-		}
-
-		public bool IsNew {
-			get {
-				return (Modifiers & ModifierEnum.New) == ModifierEnum.New;
-			}
-		}
-
-		public IEnumerable ClassInheritanceTree {
-			get {
-				return new AbstractClass.ClassInheritanceEnumerator(this);
-			}
-		}
 		
-		int IComparable.CompareTo(object value) {
-			return 0;
+		public static bool WriteNull (object ob, BinaryWriter writer)
+		{
+			writer.Write (ob==null);
+			return ob==null;
 		}
 		
-		// stub
-		public object DeclaredIn {
-			get {
-				return null;
-			}
+		public static bool ReadNull (BinaryReader reader)
+		{
+			return reader.ReadBoolean ();
 		}
 	}
 }
Index: Main/Base/Internal/Parser/IClass.cs
===================================================================
--- Main/Base/Internal/Parser/IClass.cs	(revision 1623)
+++ Main/Base/Internal/Parser/IClass.cs	(working copy)
@@ -70,10 +70,6 @@
 			get;
 		}
 
-		IEnumerable ClassInheritanceTree {
-			get;
-		}
-		
 		object DeclaredIn {
 			get;
 		}
Index: Main/Base/Internal/Parser/ReflectionLayer/ReflectionClass.cs
===================================================================
--- Main/Base/Internal/Parser/ReflectionLayer/ReflectionClass.cs	(revision 1623)
+++ Main/Base/Internal/Parser/ReflectionLayer/ReflectionClass.cs	(working copy)
@@ -48,7 +48,8 @@
 			
 			FullyQualifiedName = type.FullName;
 
-			XmlDocument docs = ((MonodocService)ServiceManager.Services.GetService (typeof (MonodocService))).GetHelpXml (FullyQualifiedName);
+			MonodocService docservice = ((MonodocService)ServiceManager.Services.GetService (typeof (MonodocService)));
+			XmlDocument docs = docservice != null ? docservice.GetHelpXml (FullyQualifiedName) : null;
 			if (docs != null) {
 				XmlNode node = docs.SelectSingleNode ("/Type/Docs/summary");
 				if (node != null) {
Index: Main/Base/Internal/Parser/IRegion.cs
===================================================================
--- Main/Base/Internal/Parser/IRegion.cs	(revision 1623)
+++ Main/Base/Internal/Parser/IRegion.cs	(working copy)
@@ -27,6 +27,11 @@
 			get;
 			set;
 		}
+		
+		string FileName {
+			get;
+			set;
+		}
 
 		bool IsInside(int row, int column);
 	}
Index: Main/Base/Internal/Parser/IUsing.cs
===================================================================
--- Main/Base/Internal/Parser/IUsing.cs	(revision 1623)
+++ Main/Base/Internal/Parser/IUsing.cs	(working copy)
@@ -24,11 +24,5 @@
 		SortedList Aliases {
 			get;
 		}
-
-		IClass SearchType(string partitialTypeName);
-		string SearchNamespace(string partitialNamespaceName);
-		
-		IClass SearchType(string partitialTypeName, bool caseSensitive);
-		string SearchNamespace(string partitialNamespaceName, bool caseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitivecaseSensitive);
 	}
 }
Index: Main/Base/Internal/Parser/Implementations/AbstractDecoration.cs
===================================================================
--- Main/Base/Internal/Parser/Implementations/AbstractDecoration.cs	(revision 1623)
+++ Main/Base/Internal/Parser/Implementations/AbstractDecoration.cs	(working copy)
@@ -16,7 +16,7 @@
 	{
 		protected ModifierEnum               modifiers     = ModifierEnum.None;
 		protected AttributeSectionCollection attributes    = null;
-		int    documentationHash = -1;
+		string documentation;
 		static Hashtable documentationHashtable = new Hashtable();
 		
 		
@@ -37,15 +37,19 @@
 
 		public string Documentation {
 			get {
-				if (documentationHash == -1) {
-					return String.Empty;
-				}
-				return (string)documentationHashtable[documentationHash];
+				return documentation == null ? "" : documentation;
 			}
 			set {
-				documentationHash = value.GetHashCode();
-				if (documentationHashtable[documentationHash] == null) {
-					documentationHashtable[documentationHash] = value;
+				if (value == null)
+					documentation = null;
+				else {
+					string sharedVal = documentationHashtable [value] as string;
+					if (sharedVal == null) {
+						documentationHashtable [value] = value;
+						documentation = value;
+					}
+					else
+						documentation = sharedVal;
 				}
 			}
 		}
Index: Main/Base/Internal/Parser/Implementations/DefaultRegion.cs
===================================================================
--- Main/Base/Internal/Parser/Implementations/DefaultRegion.cs	(revision 1623)
+++ Main/Base/Internal/Parser/Implementations/DefaultRegion.cs	(working copy)
@@ -18,6 +18,7 @@
 		protected int endLine = -1;
 		protected int beginColumn = -1;
 		protected int endColumn = -1;
+		protected string fileName;
 
 		public virtual int BeginLine {
 			get {
@@ -57,6 +58,15 @@
 			}
 		}
 
+		public string FileName {
+			get { 
+				return fileName; 
+			}
+			set {
+				fileName = value;
+			}
+		}
+		
 		public DefaultRegion(Point start, Point end) : this(start.Y, start.X, end.Y, end.X)
 		{
 		}
Index: Main/Base/Internal/Parser/Implementations/AbstractClass.cs
===================================================================
--- Main/Base/Internal/Parser/Implementations/AbstractClass.cs	(revision 1623)
+++ Main/Base/Internal/Parser/Implementations/AbstractClass.cs	(working copy)
@@ -155,91 +155,10 @@
 			return CompareTo((IClass)o);
 		}
 		
-		public IEnumerable ClassInheritanceTree {
-			get {
-				return new ClassInheritanceEnumerator(this);
-			}
-		}
-		
 		protected override bool CanBeSubclass {
 			get {
 				return true;
 			}
 		}
-
-		public class ClassInheritanceEnumerator : IEnumerator, IEnumerable
-		{
-			static IParserService parserService = (IParserService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IParserService));
-			IClass topLevelClass;
-			IClass currentClass  = null;
-			Queue  baseTypeQueue = new Queue();
-
-			public ClassInheritanceEnumerator(IClass topLevelClass)
-			{
-				this.topLevelClass = topLevelClass;
-				baseTypeQueue.Enqueue(topLevelClass.FullyQualifiedName);
-				PutBaseClassesOnStack(topLevelClass);
-				baseTypeQueue.Enqueue("System.Object");
-			}
-			public IEnumerator GetEnumerator()
-			{
-				return this;
-			}
-
-			void PutBaseClassesOnStack(IClass c)
-			{
-				foreach (string baseTypeName in c.BaseTypes) {
-					baseTypeQueue.Enqueue(baseTypeName);
-				}
-			}
-
-			public IClass Current {
-				get {
-					return currentClass;
-				}
-			}
-
-			object IEnumerator.Current {
-				get {
-					return currentClass;
-				}
-			}
-
-			public bool MoveNext()
-			{
-				if (baseTypeQueue.Count == 0) {
-					return false;
-				}
-				string baseTypeName = baseTypeQueue.Dequeue().ToString();
-
-				IClass baseType = parserService.GetClass(baseTypeName);
-				if (baseType == null) {
-					ICompilationUnit unit = currentClass == null ? null : currentClass.CompilationUnit;
-					if (unit != null) {
-						foreach (IUsing u in unit.Usings) {
-							baseType = u.SearchType(baseTypeName);
-							if (baseType != null) {
-								break;
-							}
-						}
-					}
-				}
-
-				if (baseType != null) {
-					currentClass = baseType;
-					PutBaseClassesOnStack(currentClass);
-				}
-
-				return baseType != null;
-			}
-
-			public void Reset()
-			{
-				baseTypeQueue.Clear();
-				baseTypeQueue.Enqueue(topLevelClass.FullyQualifiedName);
-				PutBaseClassesOnStack(topLevelClass);
-				baseTypeQueue.Enqueue("System.Object");
-			}
-		}
 	}
 }
Index: Main/Base/Internal/Parser/Implementations/AbstractParameter.cs
===================================================================
--- Main/Base/Internal/Parser/Implementations/AbstractParameter.cs	(revision 1623)
+++ Main/Base/Internal/Parser/Implementations/AbstractParameter.cs	(working copy)
@@ -72,7 +72,7 @@
 
 		public string Documentation {
 			get {
-				return documentation;
+				return documentation == null ? "" : documentation;
 			}
 		}
 		
Index: Main/Base/Internal/Parser/Implementations/AbstractNamedEntity.cs
===================================================================
--- Main/Base/Internal/Parser/Implementations/AbstractNamedEntity.cs	(revision 1623)
+++ Main/Base/Internal/Parser/Implementations/AbstractNamedEntity.cs	(working copy)
@@ -14,16 +14,23 @@
 	public abstract class AbstractNamedEntity : AbstractDecoration
 	{
 		public static Hashtable fullyQualifiedNames = new Hashtable();
-		int nameHashCode = -1;
+		string fqname;
 		
 		public virtual string FullyQualifiedName {
 			get {
-				return (string)fullyQualifiedNames[nameHashCode];
+				return fqname;
 			}
 			set {
-				nameHashCode = value.GetHashCode();
-				if (fullyQualifiedNames[nameHashCode] == null) {
-					fullyQualifiedNames[nameHashCode] = value;
+				if (value == null)
+					fqname = null;
+				else {
+					string sharedVal = fullyQualifiedNames[value] as string;
+					if (sharedVal != null)
+						fqname = sharedVal;
+					else {
+						fullyQualifiedNames[value] = value;
+						fqname = value;
+					}
 				}
 			}
 		}
Index: Main/Base/Internal/Parser/Implementations/AbstractReturnType.cs
===================================================================
--- Main/Base/Internal/Parser/Implementations/AbstractReturnType.cs	(revision 1623)
+++ Main/Base/Internal/Parser/Implementations/AbstractReturnType.cs	(working copy)
@@ -15,16 +15,23 @@
 		protected int    pointerNestingLevel;
 		protected int[]  arrayDimensions;
 		protected object declaredin = null;
-		int nameHashCode = -1;
+		string fname;
 		
 		public virtual string FullyQualifiedName {
 			get {
-				return (string)AbstractNamedEntity.fullyQualifiedNames[nameHashCode];
+				return fname;
 			}
 			set {
-				nameHashCode = value.GetHashCode();
-				if (AbstractNamedEntity.fullyQualifiedNames[nameHashCode] == null) {
-					AbstractNamedEntity.fullyQualifiedNames[nameHashCode] = value;
+				if (value == null)
+					fname = value;
+				else {
+					string sharedName = (string) AbstractNamedEntity.fullyQualifiedNames [value];
+					if (sharedName == null) {
+						AbstractNamedEntity.fullyQualifiedNames [value] = value;
+						fname = value;
+					}
+					else
+						fname = sharedName;
 				}
 			}
 		}
Index: Main/Base/Internal/Parser/Implementations/AbstractUsing.cs
===================================================================
--- Main/Base/Internal/Parser/Implementations/AbstractUsing.cs	(revision 1623)
+++ Main/Base/Internal/Parser/Implementations/AbstractUsing.cs	(working copy)
@@ -38,114 +38,6 @@
 			}
 		}
 		
-		static IParserService parserService = (IParserService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IParserService));
-		public string SearchNamespace(string partitialNamespaceName)
-		{
-			return SearchNamespace(partitialNamespaceName, true);
-		}
-		
-		public string SearchNamespace(string partitialNamespaceName, bool caseSensitive)
-		{
-//			Console.WriteLine("SearchNamespace : >{0}<", partitialNamespaceName);
-			if (parserService.NamespaceExists(partitialNamespaceName, caseSensitive)) {
-				return partitialNamespaceName;
-			}
-			
-			// search for partitial namespaces
-			string declaringNamespace = (string)aliases[""];
-			if (declaringNamespace != null) {
-				while (declaringNamespace.Length > 0) {
-					if ((caseSensitive ? declaringNamespace.EndsWith(partitialNamespaceName) : declaringNamespace.ToLower().EndsWith(partitialNamespaceName.ToLower()) ) && parserService.NamespaceExists(declaringNamespace, caseSensitive)) {
-						return declaringNamespace;
-					}
-					int index = declaringNamespace.IndexOf('.');
-					if (index > 0) {
-						declaringNamespace = declaringNamespace.Substring(0, index);
-					} else {
-						break;
-					}
-				}
-			}
-			
-			// Remember:
-			//     Each namespace has an own using object
-			//     The namespace name is an alias which has the key ""
-			foreach (DictionaryEntry entry in aliases) {
-				string aliasString = entry.Key.ToString();
-				if (caseSensitive ? partitialNamespaceName.StartsWith(aliasString) : partitialNamespaceName.ToLower().StartsWith(aliasString.ToLower())) {
-					if (aliasString.Length >= 0) {
-						string nsName = nsName = String.Concat(entry.Value.ToString(), partitialNamespaceName.Remove(0, aliasString.Length));
-						if (parserService.NamespaceExists(nsName, caseSensitive)) {
-							return nsName;
-						}
-					}
-				}
-			}
-			return null;
-		}
-
-		public IClass SearchType(string partitialTypeName)
-		{
-			return SearchType(partitialTypeName, true);
-		}
-		
-		public IClass SearchType(string partitialTypeName, bool caseSensitive)
-		{
-//			Console.WriteLine("Search type : >{0}<", partitialTypeName);
-			IClass c = parserService.GetClass(partitialTypeName, caseSensitive);
-			if (c != null) {
-				return c;
-			}
-			
-			foreach (string str in usings) {
-				string possibleType = String.Concat(str, ".", partitialTypeName);
-//				Console.WriteLine("looking for " + possibleType);
-				c = parserService.GetClass(possibleType, caseSensitive);
-				if (c != null) {
-//					Console.WriteLine("Found!");
-					return c;
-				}
-			}
-			
-			// search class in partitial namespaces
-			string declaringNamespace = (string)aliases[""];
-			if (declaringNamespace != null) {
-				while (declaringNamespace.Length > 0) {
-					string className = String.Concat(declaringNamespace, ".", partitialTypeName);
-//					Console.WriteLine("looking for " + className);
-					c = parserService.GetClass(className, caseSensitive);
-					if (c != null) {
-//						Console.WriteLine("Found!");
-						return c;
-					}
-					int index = declaringNamespace.IndexOf('.');
-					if (index > 0) {
-						declaringNamespace = declaringNamespace.Substring(0, index);
-					} else {
-						break;
-					}
-				}
-			}
-			
-			foreach (DictionaryEntry entry in aliases) {
-				string aliasString = entry.Key.ToString();
-				if (caseSensitive ? partitialTypeName.StartsWith(aliasString) : partitialTypeName.ToLower().StartsWith(aliasString.ToLower())) {
-					string className = null;
-					if (aliasString.Length > 0) {
-						className = String.Concat(entry.Value.ToString(), partitialTypeName.Remove(0, aliasString.Length));
-//						Console.WriteLine("looking for " + className);
-						c = parserService.GetClass(className, caseSensitive);
-						if (c != null) {
-//							Console.WriteLine("Found!");
-							return c;
-						}
-					}
-				}
-			}
-			
-			return null;
-		}
-		
 		public override string ToString()
 		{
 			StringBuilder builder = new StringBuilder("[AbstractUsing: using list=");

--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=classscout.diff
Content-Type: text/x-patch; name=classscout.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: Main/Base/Gui/Pads/ClassScout/ClassScout.cs
===================================================================
--- Main/Base/Gui/Pads/ClassScout/ClassScout.cs	(revision 1623)
+++ Main/Base/Gui/Pads/ClassScout/ClassScout.cs	(working copy)
@@ -60,8 +60,7 @@
 		Gtk.Frame contentPanel;
 
 		ResourceService resourceService = (ResourceService)ServiceManager.Services.GetService(typeof(IResourceService));
-		ParseInformationEventHandler addParseInformationHandler = null;
-		ParseInformationEventHandler removeParseInformationHandler = null;
+		ClassInformationEventHandler changeClassInformationHandler = null;
 		Combine parseCombine;
 		ArrayList ImageList;
 		
@@ -99,8 +98,7 @@
 		
 		public ClassScout() : base (false, TreeNodeComparer.GtkDefault)
 		{
-			addParseInformationHandler = new ParseInformationEventHandler(OnParseInformationAdded);
-			removeParseInformationHandler = new ParseInformationEventHandler(OnParseInformationRemoved);
+			changeClassInformationHandler = new ClassInformationEventHandler(OnClassInformationChanged);
 			
 			FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
 
@@ -110,8 +108,6 @@
 
 			projectService.CombineOpened += new CombineEventHandler(OnCombineOpen);
 			projectService.CombineClosed += new CombineEventHandler(OnCombineClosed);
-			projectService.FileAddedToProject += new FileEventHandler (OnProjectFilesChanged);
-			projectService.FileRemovedFromProject += new FileEventHandler (OnProjectFilesChanged);
 
 			Gtk.ScrolledWindow sw = new Gtk.ScrolledWindow ();
 			sw.Add(this);
@@ -133,12 +129,6 @@
 			}
 		}
 
-		void OnProjectFilesChanged (object sender, FileEventArgs e)
-		{
-			IProjectService projectService = (IProjectService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
-			OnCombineOpen (sender, new CombineEventArgs (projectService.CurrentOpenCombine));
-		}
-
 		public void RedrawContent()
 		{
 		}
@@ -153,44 +143,24 @@
 		void OnCombineClosed(object sender, CombineEventArgs e)
 		{
 			IParserService parserService  = (IParserService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IParserService));
-			parserService.ParseInformationAdded -= addParseInformationHandler;
-			parserService.ParseInformationRemoved -= removeParseInformationHandler;
+			parserService.ClassInformationChanged -= changeClassInformationHandler;
 			Nodes.Clear();
 		}
-
-		ParseInformationEventArgs add_e = null;
-		void OnParseInformationAdded(object sender, ParseInformationEventArgs e)
+		
+		void AddIdle (IdleStateHandler cb, object data)
 		{
-			add_e = e;
-			GLib.Idle.Add (new GLib.IdleHandler (addParseInfo));
+			GLib.Idle.Add (new GLib.IdleHandler (new IdleWork (cb, data).Run));
 		}
 
-		bool addParseInfo ()
+		void OnClassInformationChanged(object sender, ClassInformationEventArgs e)
 		{
-			if (add_e != null) {
-				lock (add_e) {
-					AddParseInformation (Nodes, add_e);
-				}
-				add_e = null;
-			}
-			return false;
+			AddIdle (new IdleStateHandler(ChangeClassInfo), e);
 		}
 		
-		ParseInformationEventArgs remove_e;
-		void OnParseInformationRemoved(object sender, ParseInformationEventArgs e)
+		bool ChangeClassInfo (object e)
 		{
-			remove_e = e;
-			GLib.Idle.Add (new GLib.IdleHandler (removeParseInfo));
-		}
-
-		bool removeParseInfo ()
-		{
-			if (remove_e != null) {
-				lock (remove_e) {
-					RemoveParseInformation (Nodes, remove_e);
-				}
-				remove_e = null;
-			}
+			ClassInformationEventArgs ce = (ClassInformationEventArgs) e;
+			ChangeClassInformation (Nodes, ce);
 			return false;
 		}
 
@@ -213,6 +183,29 @@
 				}
 			}
 		}
+		
+		protected override void OnBeforeExpand (TreeViewCancelEventArgs e)
+		{
+			TreeNode nod = e.Node;
+			if (nod.Tag == null || nod.Tag is IProject)
+			{
+				while (nod != null && nod.Tag == null)
+					nod = nod.Parent;
+					
+				if (nod == null) return;
+				
+				IProject p = (IProject)nod.Tag;
+				foreach (IClassScoutNodeBuilder classBrowserNodeBuilder in classBrowserNodeBuilders) {
+					if (classBrowserNodeBuilder.CanBuildClassTree(p)) {
+						classBrowserNodeBuilder.ExpandNode (e.Node);
+						break;
+					}
+				}
+				
+			}
+		}
+		
+		
 /*
 		protected override void OnMouseDown(MouseEventArgs e)
 		{
@@ -272,14 +265,13 @@
 		
 		void StartPopulating()
 		{
-			ParseCombine(parseCombine);
+			//ParseCombine(parseCombine);
 			//Invoke(new MyD(DoPopulate));
 			Gdk.Threads.Enter();
 			DoPopulate();
 			Gdk.Threads.Leave();
 			IParserService parserService  = (IParserService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IParserService));
-			parserService.ParseInformationAdded += addParseInformationHandler;
-			parserService.ParseInformationRemoved += removeParseInformationHandler;
+			parserService.ClassInformationChanged += changeClassInformationHandler;
 		}
 
 		public void ParseCombine(Combine combine)
@@ -369,7 +361,7 @@
 			}
 		}
 
-		void AddParseInformation(TreeNodeCollection nodes, ParseInformationEventArgs e)
+		void ChangeClassInformation(TreeNodeCollection nodes, ClassInformationEventArgs e)
 		{
 			BeginUpdate();
 			foreach (TreeNode node in nodes) {
@@ -377,35 +369,35 @@
 					IProject p = (IProject)node.Tag;
 					if (p.IsFileInProject(e.FileName)) {
 						foreach (IClassScoutNodeBuilder classBrowserNodeBuilder in classBrowserNodeBuilders) {
-							classBrowserNodeBuilder.AddToClassTree(node, e);
+							classBrowserNodeBuilder.UpdateClassTree(node, e);
 							break;
 						}
 					}
 				} else {
-					AddParseInformation(node.Nodes, e);
+					ChangeClassInformation(node.Nodes, e);
 				}
 			}
 			EndUpdate();
 		}
+	}
+	
+	public delegate bool IdleStateHandler (object state);
+	
+	class IdleWork
+	{
+		object _data;
+		IdleStateHandler _cb;
 		
-		void RemoveParseInformation(TreeNodeCollection nodes, ParseInformationEventArgs e)
+		public IdleWork (IdleStateHandler cb, object data)
 		{
-			BeginUpdate();
-			foreach (TreeNode node in nodes) {
-				if (node.Tag is IProject) {
-					IProject p = (IProject)node.Tag;
-					if (p.IsFileInProject(e.FileName)) {
-						foreach (IClassScoutNodeBuilder classBrowserNodeBuilder in classBrowserNodeBuilders) {
-							classBrowserNodeBuilder.RemoveFromClassTree(node, e);
-							break;
-						}
-					}
-				} else {
-					RemoveParseInformation(node.Nodes, e);
-				}
-			}
-			EndUpdate();
+			_data = data;
+			_cb = cb;
 		}
+		
+		public bool Run ()
+		{
+			return _cb (_data);
+		}
 	}
 }
 
Index: Main/Base/Gui/Pads/ClassScout/NodeBuilder/DefaultDotNetClassScoutNodeBuilder.cs
===================================================================
--- Main/Base/Gui/Pads/ClassScout/NodeBuilder/DefaultDotNetClassScoutNodeBuilder.cs	(revision 1623)
+++ Main/Base/Gui/Pads/ClassScout/NodeBuilder/DefaultDotNetClassScoutNodeBuilder.cs	(working copy)
@@ -49,30 +49,32 @@
 		}
 
 		private object locker = new object ();
-		public void AddToClassTree(TreeNode parentNode, ParseInformationEventArgs e)
+		
+		public void UpdateClassTree (TreeNode parentNode, ClassInformationEventArgs e)
 		{
 			lock (locker) {
-				AddToClassTree(parentNode, e.FileName, (ICompilationUnit)e.ParseInformation.MostRecentCompilationUnit);
+				RemoveFromClassTree (parentNode, e.ClassInformation.Removed);
+				AddToClassTree (parentNode, e.FileName, e.ClassInformation.Added);
+				AddToClassTree (parentNode, e.FileName, e.ClassInformation.Modified);
 			}
 		}
 		
-		public void RemoveFromClassTree(TreeNode parentNode, ParseInformationEventArgs e) {
+		public void RemoveFromClassTree (TreeNode parentNode, ClassCollection removed) {
 			ClassBrowserIconsService classBrowserIconService = (ClassBrowserIconsService)ServiceManager.Services.GetService(typeof(ClassBrowserIconsService));
 			
 			TreeNode classNode = new TreeNode();
 			
-			ICompilationUnit unit = (ICompilationUnit)e.ParseInformation.MostRecentCompilationUnit;
-			foreach (IClass c in unit.Classes) {
+			foreach (IClass c in removed) {
 				classNode.Text = c.Name;
 				classNode.Image = classBrowserIconService.GetIcon (c);
 				// TODO: Perf check
-				TreeNode node = GetNodeByPath(c.Namespace, parentNode.Nodes, false);
-				if (node != null) {
-					int oldIndex = SortUtility.BinarySearch (classNode, node.Nodes, TreeNodeComparer.Default);
+				TreeNode node = GetNodeByPath (c.Namespace, parentNode, false);
+				if (node != null && !NeedsExpansion (node)) {
+					int oldIndex = FindNodeByName (node.Nodes, c.Name);
 					if (oldIndex >= 0) {
 						node.Nodes[oldIndex].Remove ();
 					}
-					DropPhantomNamespaces (c.Namespace, parentNode.Nodes);
+					DropPhantomNamespaces (c.Namespace, parentNode);
 				}
 			}
 		}
@@ -84,6 +86,11 @@
 			foreach (TreeNode node in newNode.Nodes)
 				projectNode.Nodes.Add(node);
 		}
+		
+		static bool NeedsExpansion (TreeNode nod)
+		{
+			return (nod.Nodes.Count == 1 && nod.Nodes[0].Text == "");
+		}
 
 		public TreeNode BuildClassTreeNode(IProject p)
 		{
@@ -96,41 +103,65 @@
 
 			TreeNode prjNode = new AbstractClassScoutNode(p.Name);
 			prjNode.Image = iconService.GetImageForProjectType(p.ProjectType);
- 			foreach (ProjectFile finfo in p.ProjectFiles) {
-				if (finfo.BuildAction == BuildAction.Compile) {
-					int i = 0;
-					IParserService parserService = (IParserService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IParserService));
-					if (parserService.GetParser(finfo.Name) == null) {
-						continue;
-					}
+			prjNode.Nodes.Add (new TreeNode (""));
+			prjNode.Tag = p;
+			return prjNode;
+		}
+		
+		public void ExpandNode (TreeNode node)
+		{
+			if (node.Tag == null)
+			{
+				// Build the namespace
+				string ns = node.Text;
+				TreeNode nod = node.Parent;
+				while (nod.Tag == null) {
+					ns = nod.Text + "." + ns;
+					nod = nod.Parent;
+				}
 
-					for(i=0; i < 5 && parserService.GetParseInformation(finfo.Name) == null; i++) {
-						Thread.Sleep(100);
-					}
-
-					if (parserService.GetParseInformation(finfo.Name) == null) {
-						continue;
-					}
-
-					IParseInformation parseInformation = parserService.GetParseInformation(finfo.Name);
-					if (parseInformation != null) {
-						ICompilationUnit unit = parseInformation.BestCompilationUnit as ICompilationUnit;
-						if (unit != null) {
-						   AddToClassTree(prjNode, finfo.Name, unit);
-						}
-					}
+				IProject p = (IProject)nod.Tag;
+				ExpandNamespaceTree (p, ns, node);
+			}
+			else if (node.Tag is IProject)
+			{
+				IProject p = (IProject)node.Tag;
+				ExpandNamespaceTree (p, "", node);
+			}
+		}
+		
+		void ExpandNamespaceTree (IProject project, string ns, TreeNode node)
+		{
+			if (!NeedsExpansion (node)) return;
+			node.Nodes.Clear ();
+			
+			IParserService parserService  = (IParserService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IParserService));
+			ArrayList contents = parserService.GetNamespaceContents (project, ns, false);
+			foreach (object item in contents)
+			{
+				if (item is string)
+				{
+					TreeNode newnode = new AbstractClassScoutNode ((string)item);
+					newnode.Image = Stock.NameSpace;
+					node.Nodes.Add (newnode);
+					newnode.Nodes.Add (new TreeNode (""));
 				}
+				else if (item is IClass)
+				{
+					node.Nodes.Add (BuildClassNode ((IClass)item));
+				}
 			}
-			return prjNode;
 		}
 		
-		public void AddToClassTree(TreeNode parentNode, string filename, ICompilationUnit unit)
+		public void AddToClassTree(TreeNode parentNode, string filename, ClassCollection classes)
 		{
-			foreach (IClass c in unit.Classes) {
-				TreeNode node = GetNodeByPath(c.Namespace, parentNode.Nodes, true);
-				if (node == null) {
-					node = parentNode;
-				}
+			if (NeedsExpansion (parentNode)) return;
+			
+			foreach (IClass c in classes) {
+			
+				TreeNode node = GetNodeByPath (c.Namespace, parentNode, true);
+				if (node == null || NeedsExpansion (node))
+					continue;
 				
 				TreeNode oldClassNode = GetNodeByName(node.Nodes, c.Name);
 				bool wasExpanded = false;
@@ -139,7 +170,7 @@
 					oldClassNode.Remove();
 				}
 				
-				TreeNode classNode = BuildClassNode(filename, c);
+				TreeNode classNode = BuildClassNode(c);
 				if(classNode != null) {
 					node.Nodes.Add (classNode);
 					
@@ -150,15 +181,16 @@
 			}
 		}
 		
-		TreeNode BuildClassNode(string filename, IClass c)
+		TreeNode BuildClassNode (IClass c)
 		{
 			ClassBrowserIconsService classBrowserIconService = (ClassBrowserIconsService)ServiceManager.Services.GetService(typeof(ClassBrowserIconsService));
 
 			AbstractClassScoutNode classNode = new AbstractClassScoutNode(c.Name);
+			string file = c.Region.FileName;
 			
 			classNode.Image = classBrowserIconService.GetIcon (c);
 			classNode.ContextmenuAddinTreePath = "/SharpDevelop/Views/ClassScout/ContextMenu/ClassNode";
-			classNode.Tag = new ClassScoutTag(c.Region.BeginLine, filename);
+			classNode.Tag = new ClassScoutTag(c.Region.BeginLine, file);
 
 			// don't insert delegate 'members'
 			if (c.ClassType == ClassType.Delegate) {
@@ -168,12 +200,12 @@
 			foreach (IClass innerClass in c.InnerClasses) {
 				if (innerClass.ClassType == ClassType.Delegate) {
 					TreeNode innerClassNode = new AbstractClassScoutNode(languageConversion.Convert(innerClass));
-					innerClassNode.Tag = new ClassScoutTag(innerClass.Region.BeginLine, filename);
+					innerClassNode.Tag = new ClassScoutTag(innerClass.Region.BeginLine, innerClass.Region.FileName == null ? file : innerClass.Region.FileName);
 					//innerClassNode.SelectedImageIndex = innerClassNode.ImageIndex = classBrowserIconService.GetIcon(innerClass);
 					innerClassNode.Image = classBrowserIconService.GetIcon(innerClass);
 					classNode.Nodes.Add(innerClassNode);
 				} else {
-					TreeNode n = BuildClassNode(filename, innerClass);
+					TreeNode n = BuildClassNode(innerClass);
 					if(classNode != null) {
 						classNode.Nodes.Add(n);
 					}
@@ -182,7 +214,7 @@
 
 			foreach (IMethod method in c.Methods) {
 				TreeNode methodNode = new AbstractClassScoutNode(languageConversion.Convert(method));
-				methodNode.Tag = new ClassScoutTag(method.Region.BeginLine, filename);
+				methodNode.Tag = new ClassScoutTag(method.Region.BeginLine, method.Region.FileName == null ? file : method.Region.FileName);
 				//methodNode.SelectedImageIndex = methodNode.ImageIndex = classBrowserIconService.GetIcon(method);
 				methodNode.Image = classBrowserIconService.GetIcon(method);
 				classNode.Nodes.Add(methodNode);
@@ -190,7 +222,7 @@
 			
 			foreach (IProperty property in c.Properties) {
 				TreeNode propertyNode = new AbstractClassScoutNode(languageConversion.Convert(property));
-				propertyNode.Tag = new ClassScoutTag(property.Region.BeginLine, filename);
+				propertyNode.Tag = new ClassScoutTag(property.Region.BeginLine, property.Region.FileName == null ? file : property.Region.FileName);
 				//propertyNode.SelectedImageIndex = propertyNode.ImageIndex = classBrowserIconService.GetIcon(property);
 				propertyNode.Image = classBrowserIconService.GetIcon(property);
 				classNode.Nodes.Add(propertyNode);
@@ -198,7 +230,7 @@
 			
 			foreach (IField field in c.Fields) {
 				TreeNode fieldNode = new AbstractClassScoutNode(languageConversion.Convert(field));
-				fieldNode.Tag = new ClassScoutTag(field.Region.BeginLine, filename);
+				fieldNode.Tag = new ClassScoutTag(field.Region.BeginLine, field.Region.FileName == null ? file : field.Region.FileName);
 				//fieldNode.SelectedImageIndex = fieldNode.ImageIndex = classBrowserIconService.GetIcon(field);
 				fieldNode.Image = classBrowserIconService.GetIcon(field);
 				classNode.Nodes.Add(fieldNode);
@@ -206,7 +238,7 @@
 			
 			foreach (IEvent e in c.Events) {
 				TreeNode eventNode = new AbstractClassScoutNode(languageConversion.Convert(e));
-				eventNode.Tag = new ClassScoutTag(e.Region.BeginLine, filename);
+				eventNode.Tag = new ClassScoutTag(e.Region.BeginLine, e.Region.FileName == null ? file : e.Region.FileName);
 				//eventNode.SelectedImageIndex = eventNode.ImageIndex = classBrowserIconService.GetIcon(e);
 				eventNode.Image = classBrowserIconService.GetIcon(e);
 				classNode.Nodes.Add(eventNode);
@@ -215,51 +247,51 @@
 			return classNode;
 		}
 
-		public void DropPhantomNamespaces (string dir, TreeNodeCollection root)
+		public void DropPhantomNamespaces (string dir, TreeNode parentNode)
 		{
 			string[] full_path = dir.Split (new char[] { '.' });
 			for (int i = full_path.Length - 1; i != -1; i--)
 			{
-				TreeNode node = GetNodeByPath (String.Join (".", full_path, 0, i + 1), root, false);
-				if (node != null && node.Nodes.Count == 0)
+				TreeNode node = GetNodeByPath (String.Join (".", full_path, 0, i + 1), parentNode, false);
+				if (node != null && node.Nodes.Count == 0 && node != parentNode)
 					node.Remove ();
 			}
 		}
 		
-		static public TreeNode GetNodeByPath(string directory, TreeNodeCollection root, bool create)
+		static public TreeNode GetNodeByPath(string directory, TreeNode parentNode, bool create)
 		{
 			ClassBrowserIconsService classBrowserIconService = (ClassBrowserIconsService)ServiceManager.Services.GetService(typeof(ClassBrowserIconsService));
 
 			string[] treepath   = directory.Split(new char[] { '.' });
-			TreeNodeCollection curcollection = root;
-			TreeNode           curnode       = null;
-			if (treepath.Length == 1 && treepath[0].Length == 0) {
-				if (root.Count == 0)
-					return null;
-				return root[0].Parent;
-			}
+			TreeNode curnode = parentNode;
+			
+			if (NeedsExpansion (parentNode)) return null;
+			
+			if (treepath.Length == 1 && treepath[0].Length == 0)
+				return parentNode;
+			
 			foreach (string path in treepath) {
 				if (path.Length == 0 || path[0] == '.') {
 					continue;
 				}
 
-				TreeNode node = GetNodeByName(curcollection, path);
-				if (node == null) {
+				curnode = GetNodeByName (curnode.Nodes, path);
+				
+				if (curnode == null) {
 					if (create) {
-						TreeNode newnode = new AbstractClassScoutNode(path);
-						//newnode.ImageIndex = newnode.SelectedImageIndex = classBrowserIconService.NamespaceIndex;
-						newnode.Image = Stock.NameSpace;
-
-						curcollection.Add (newnode);
-						curnode = newnode;
-						curcollection = curnode.Nodes;
-						continue;
+						curnode = new AbstractClassScoutNode(path);
+						curnode.Image = Stock.NameSpace;
+						curnode.Nodes.Add (new TreeNode (""));
+						parentNode.Nodes.Add (curnode);
+						return null;	// Delay expansion
 					} else {
 						return null;
 					}
 				}
-				curnode = node;
-				curcollection = curnode.Nodes;
+				else if (NeedsExpansion (curnode))
+					return null;
+				
+				parentNode = curnode;
 			}
 			return curnode;
 		}
@@ -273,5 +305,14 @@
 			}
 			return null;
 		}
+
+		static int FindNodeByName(TreeNodeCollection collection, string name)
+		{
+			for (int n=0; n<collection.Count; n++)
+				if (collection[n].Text == name)
+					return n;
+
+			return -1;
+		}
 	}
 }
Index: Main/Base/Gui/Pads/ClassScout/NodeBuilder/IClassScoutNodeBuilder.cs
===================================================================
--- Main/Base/Gui/Pads/ClassScout/NodeBuilder/IClassScoutNodeBuilder.cs	(revision 1623)
+++ Main/Base/Gui/Pads/ClassScout/NodeBuilder/IClassScoutNodeBuilder.cs	(working copy)
@@ -23,8 +23,8 @@
 	{
 		bool     CanBuildClassTree(IProject project);
 		TreeNode BuildClassTreeNode(IProject project);
+		void     ExpandNode (TreeNode node);
 
-		void     AddToClassTree(TreeNode projectNode, ParseInformationEventArgs e);
-		void     RemoveFromClassTree(TreeNode parentNode, ParseInformationEventArgs e);
+		void     UpdateClassTree (TreeNode projectNode, ClassInformationEventArgs e);
 	}
 }

--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=dbgen.diff
Content-Type: text/x-patch; name=dbgen.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: Makefile.am
===================================================================
--- Makefile.am	(revision 1623)
+++ Makefile.am	(working copy)
@@ -1,3 +1,3 @@
 
-SUBDIRS = Tools Libraries Main AddIns
+SUBDIRS = Libraries Main Tools AddIns
 
Index: Tools/dbgen/src/AssemblyInfo.cs
===================================================================
--- Tools/dbgen/src/AssemblyInfo.cs	(revision 0)
+++ Tools/dbgen/src/AssemblyInfo.cs	(revision 0)
@@ -0,0 +1,32 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+// Information about this assembly is defined by the following
+// attributes.
+//
+// change them to the information which is associated with the assembly
+// you compile.
+
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// The assembly version has following format :
+//
+// Major.Minor.Build.Revision
+//
+// You can specify all values by your own or you can build default build and revision
+// numbers with the '*' character (the default):
+
+[assembly: AssemblyVersion("1.0.*")]
+
+// The following attributes specify the key for the sign of your assembly. See the
+// .NET Framework documentation for more information about signing.
+// This is not required, if you don't want signing let these attributes like they're.
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
Index: Tools/dbgen/src/dbgen.cs
===================================================================
--- Tools/dbgen/src/dbgen.cs	(revision 0)
+++ Tools/dbgen/src/dbgen.cs	(revision 0)
@@ -0,0 +1,20 @@
+
+using System;
+using System.Reflection;
+using MonoDevelop.Services;
+
+public class CodeCompletionDatabaseGeneratorTool
+{
+	public static int Main (string[] args)
+	{
+		if (args.Length == 0) {
+			Console.WriteLine ("MonoDevelop Code Completion Database Generation Tool");
+			Console.WriteLine ("Usage: dbgen <destDirectory> [<assemblyName> | <assemblyPath>]");
+			return 0;
+		}
+		DefaultParserService parserService = new DefaultParserService ();
+		parserService.GenerateAssemblyDatabase (args[0], args[1]);
+		return 0;
+	}
+}
+
Index: Tools/dbgen/Makefile.am
===================================================================
--- Tools/dbgen/Makefile.am	(revision 0)
+++ Tools/dbgen/Makefile.am	(revision 0)
@@ -0,0 +1,23 @@
+
+CSC = mcs /debug
+ASSEMBLY = dbgen.exe
+
+FILES = src/AssemblyInfo.cs \
+src/dbgen.cs
+
+build_sources = $(addprefix $(srcdir)/, $(FILES))
+
+all: $(ASSEMBLY)
+
+REFS = /r:../../../build/bin/MonoDevelop.Base.dll
+	
+$(ASSEMBLY): $(build_sources)
+	$(CSC) $(build_sources) $(REFS) /out:$(ASSEMBLY)
+	cp $(ASSEMBLY) ../../../build/bin/.
+
+assemblydir = $(libdir)/monodevelop/bin
+assembly_DATA = $(ASSEMBLY)           
+
+CLEANFILES = $(ASSEMBLY)
+EXTRA_DIST = $(FILES)
+
Index: Tools/Makefile.am
===================================================================
--- Tools/Makefile.am	(revision 1623)
+++ Tools/Makefile.am	(working copy)
@@ -1,3 +1,3 @@
 
-SUBDIRS = SharpCoco
+SUBDIRS = SharpCoco dbgen
 

--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=other.diff
Content-Type: text/x-patch; name=other.diff; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Index: AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorBuffer.cs
===================================================================
--- AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorBuffer.cs	(revision 1623)
+++ AddIns/DisplayBindings/SourceEditor/Gui/SourceEditorBuffer.cs	(working copy)
@@ -193,14 +193,19 @@
 		
 		public void LoadFile (string file, string mime)
 		{
-			LoadText (File.OpenText (file).ReadToEnd (), mime);		
+			StreamReader sr = File.OpenText (file);
+			LoadText (sr.ReadToEnd (), mime);		
+			sr.Close ();
 			Modified = false;
 		}
 		
 		public void LoadFile (string file)
 		{
-			using (NoUndo n = new NoUndo (this))
-				Text = File.OpenText (file).ReadToEnd ();
+			using (NoUndo n = new NoUndo (this)) {
+				StreamReader sr = File.OpenText (file);
+				Text = sr.ReadToEnd ();
+				sr.Close ();
+			}
 			
 			Modified = false;
 			ScrollToTop ();
Index: Libraries/SharpRefactory/src/Parser/AST/AbstractNode.cs
===================================================================
--- Libraries/SharpRefactory/src/Parser/AST/AbstractNode.cs	(revision 1623)
+++ Libraries/SharpRefactory/src/Parser/AST/AbstractNode.cs	(working copy)
@@ -26,7 +26,7 @@
 	public abstract class AbstractNode : INode
 	{
 		INode     parent;
-		ArrayList children = new ArrayList();
+		ArrayList children;
 		Hashtable specials;
 		Point     startLocation;
 		Point     endLocation;
@@ -69,6 +69,7 @@
 		
 		public ArrayList Children {
 			get {
+				if (children == null) children = new ArrayList();
 				return children;
 			}
 		}
@@ -85,6 +86,7 @@
 		
 		public object AcceptChildren(IASTVisitor visitor, object data)
 		{
+			if (children == null) return data;
 			foreach (INode child in children) {
 				if (child != null) {
 					child.AcceptVisitor(visitor, data);
Index: Main/Base/Gui/Workbench/DefaultWorkbench.cs
===================================================================
--- Main/Base/Gui/Workbench/DefaultWorkbench.cs	(revision 1623)
+++ Main/Base/Gui/Workbench/DefaultWorkbench.cs	(working copy)
@@ -13,6 +13,7 @@
 using System.CodeDom.Compiler;
 using System.ComponentModel;
 using System.Xml;
+using System.Text;
 
 using MonoDevelop.Internal.Project;
 using MonoDevelop.Core.AddIns;
@@ -145,8 +146,32 @@
 				dbgr.ResumedEvent += new EventHandler (onDebuggerResumed);		
 				dbgr.StoppedEvent += new EventHandler (onDebuggerStopped);
 			}
+			
+			Gtk.TargetEntry [] target_table = new Gtk.TargetEntry [] {
+				new Gtk.TargetEntry ("text/uri-list", 0, (uint) 0),
+			};
+			this.DragDataReceived += new Gtk.DragDataReceivedHandler (OnDragDataReceived);
+			Gtk.Drag.DestSet (this, Gtk.DestDefaults.All, target_table, Gdk.DragAction.Copy | Gdk.DragAction.Move);
 		}
 
+		void OnDragDataReceived (object sender, Gtk.DragDataReceivedArgs args)
+		{
+			IFileService fileService = (IFileService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IFileService));
+			IProjectService proj = (IProjectService)ServiceManager.Services.GetService (typeof (IProjectService));
+			string name = Encoding.UTF8.GetString (args.SelectionData.Data).Substring (7);
+			Console.WriteLine (name);
+			switch (System.IO.Path.GetExtension (name).ToUpper()) {
+			case ".PRJX":
+			case ".CMBX":
+				proj.OpenCombine (name);
+				break;
+			default:
+				fileService.OpenFile(name);
+				break;
+			}
+			Gtk.Drag.Finish (args.Context, true, false, args.Time);
+		}
+	
 		void onDebuggerStarted (object o, EventArgs e)
 		{
 			context = WorkbenchContext.Debug;

--=-r+QCz1sSqgvIGOdPecXD
Content-Disposition: attachment; filename=DefaultParserService.cs
Content-Type: text/x-csharp; name=DefaultParserService.cs; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Mike Krger" email="mike@icsharpcode.net"/>
//     <version value="$version"/>
// </file>

using System;
using System.IO;
using System.Threading;
using System.Collections;
using System.Collections.Utility;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security;
using System.Security.Permissions;
using System.Security.Policy;
using System.Xml;

using MonoDevelop.Core.Properties;
using MonoDevelop.Core.Services;
using MonoDevelop.Services;
using MonoDevelop.Core.AddIns;
using MonoDevelop.Internal.Project;
using MonoDevelop.Gui;
using MonoDevelop.Internal.Parser;

namespace MonoDevelop.Services
{
	public class DefaultParserService : AbstractService, IParserService
	{
		CodeCompletionDatabase coreDatabase;
		
		const int MAX_CACHE_SIZE = 10;
		const string CoreDB = "Assembly:mscorlib";

		class ParsingCacheEntry
		{
			   public ParseInformation ParseInformation;
			   public string FileName;
			   public DateTime AccessTime;
		}
		
		class ParsingJob
		{
			public object Data;
			public WaitCallback ParseCallback;
		}

		Hashtable lastUpdateSize = new Hashtable();
		Hashtable parsings = new Hashtable ();
		
		ParseInformation addedParseInformation = new ParseInformation();
		ParseInformation removedParseInformation = new ParseInformation();
		CombineEntryEventHandler combineEntryAddedHandler;
		CombineEntryEventHandler combineEntryRemovedHandler;

		public static Queue parseQueue = new Queue();
		
		string codeCompletionPath;

		Hashtable databases = new Hashtable();
		
		IParser[] parser;
		
		readonly static string[] assemblyList = {
			"Microsoft.VisualBasic",
			"mscorlib",
			"System.Data",
			"System.Design",
			"System.Drawing.Design",
			"System.Drawing",
			"System.Runtime.Remoting",
			"System.Security",
			"System.ServiceProcess",
			"System.Web.Services",
			"System.Web",
			"System",
			"System.Xml",
			"glib-sharp",
			"atk-sharp",
			"pango-sharp",
			"gdk-sharp",
			"gtk-sharp",
			"gnome-sharp",
			"gconf-sharp",
			"gtkhtml-sharp",
			//"System.Windows.Forms",
			//"Microsoft.JScript",
		};
		
		StringNameTable nameTable;
		
		string[] sharedNameTable = new string[] {
			"System.String", "System.Boolean", "System.Int32", "System.Attribute",
			"System.Delegate", "System.Enum", "System.Exception", "System.MarshalByRefObject",
			"System.Object", "SerializableAttribtue", "System.Type", "System.ValueType",
			"System.ICloneable", "System.IDisposable", "System.IConvertible", "System.Bye",
			"System.Char", "System.DateTime", "System.Decimal", "System.Double", "System.Int16",
			"System.Int64", "System.IntPtr", "System.SByte", "System.Single", "System.TimeSpan",
			"System.UInt16", "System.UInt32", "System.UInt64", "System.Void"
		};
		
		public DefaultParserService()
		{
			addedParseInformation.DirtyCompilationUnit = new DummyCompilationUnit();
			removedParseInformation.DirtyCompilationUnit = new DummyCompilationUnit();
			combineEntryAddedHandler = new CombineEntryEventHandler (OnCombineEntryAdded);
			combineEntryRemovedHandler = new CombineEntryEventHandler (OnCombineEntryRemoved);
			nameTable = new StringNameTable (sharedNameTable);
		}
		
		public string LoadAssemblyFromGac (string name) {
			MethodInfo gac_get = typeof (System.Environment).GetMethod ("internalGetGacPath", BindingFlags.Static|BindingFlags.NonPublic);
			
			if (name == "mscorlib")
				return typeof(object).Assembly.Location;
				
			Assembly asm;
			try {
				asm = Assembly.Load (name);
			}
			catch {
				asm = Assembly.LoadWithPartialName (name);
			}
			if (asm == null) {
				Console.WriteLine ("Could not find: " + name);
				return string.Empty;
			}
			
			return asm.Location;
		}
		
		string sys_version;
		string GetSysVersion () {
			if (sys_version != null)
				return sys_version;
			sys_version = typeof (object).Assembly.GetName ().Version.ToString ();
			return sys_version;
		}
		

		private bool ContinueWithProcess(IProgressMonitor progressMonitor)
		{
			while (Gtk.Application.EventsPending ())
				Gtk.Application.RunIteration ();

			if (progressMonitor.Canceled)
				return false;
			else
				return true;
		}
	
		public void GenerateCodeCompletionDatabase(string createPath, IProgressMonitor progressMonitor)
		{
			if (progressMonitor != null)
				progressMonitor.BeginTask(GettextCatalog.GetString ("Generate code completion database"), assemblyList.Length);

			for (int i = 0; i < assemblyList.Length; ++i)
			{
				try {
					AssemblyCodeCompletionDatabase db = new AssemblyCodeCompletionDatabase (codeCompletionPath, assemblyList[i], this);
					db.ParseAll ();
					db.Write ();
					
					if (progressMonitor != null)
						progressMonitor.Worked(i, GettextCatalog.GetString ("Writing class"));
						
					if (!ContinueWithProcess (progressMonitor))
						return;
				}
				catch (Exception ex) {
					Console.WriteLine (ex);
				}
			}

			if (progressMonitor != null) {
				progressMonitor.Done();
			}
		}
		
		public void GenerateAssemblyDatabase (string baseDir, string name)
		{
			AssemblyCodeCompletionDatabase db = GetDatabase (baseDir, "Assembly:" + name) as AssemblyCodeCompletionDatabase;
			db.ParseInExternalProcess = false;
			db.ParseAll ();
			db.Write ();
		}
		
		void SetDefaultCompletionFileLocation()
		{
			PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
			string path = (propertyService.GetProperty("SharpDevelop.CodeCompletion.DataDirectory", String.Empty).ToString());
			FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
			codeCompletionPath = fileUtilityService.GetDirectoryNameWithSeparator(path);
		}

		public override void InitializeService()
		{
			parser = (IParser[])(AddInTreeSingleton.AddInTree.GetTreeNode("/Workspace/Parser").BuildChildItems(this)).ToArray(typeof(IParser));
			
			SetDefaultCompletionFileLocation();
			DeleteObsoleteDatabases ();

			coreDatabase = new AssemblyCodeCompletionDatabase (codeCompletionPath, "mscorlib", this);
			databases [CoreDB] = coreDatabase;
			
			IProjectService projectService = (IProjectService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
			projectService.CombineOpened += new CombineEventHandler(OnCombineOpened);
			projectService.CombineClosed += new CombineEventHandler(OnCombineClosed);
			projectService.FileRemovedFromProject += new ProjectFileEventHandler (OnProjectFilesChanged);
			projectService.FileAddedToProject += new ProjectFileEventHandler (OnProjectFilesChanged);
			projectService.ReferenceAddedToProject += new ProjectReferenceEventHandler (OnProjectReferencesChanged);
			projectService.ReferenceRemovedFromProject += new ProjectReferenceEventHandler (OnProjectReferencesChanged);
			projectService.ProjectRenamed += new ProjectRenameEventHandler(OnProjectRenamed);
		}
		
		internal CodeCompletionDatabase GetDatabase (string uri)
		{
			return GetDatabase (null, uri);
		}
		
		internal ProjectCodeCompletionDatabase GetProjectDatabase (IProject project)
		{
			if (project == null) return null;
			return (ProjectCodeCompletionDatabase) GetDatabase (null, "Project:" + project.Name);
		}
		
		internal CodeCompletionDatabase GetDatabase (string baseDir, string uri)
		{
			lock (databases)
			{
				if (baseDir == null) baseDir = codeCompletionPath;
				CodeCompletionDatabase db = (CodeCompletionDatabase) databases [uri];
				if (db == null) 
				{
					// Create/load the database
						
					if (uri.StartsWith ("Assembly:"))
					{
						string file = uri.Substring (9);
						db = new AssemblyCodeCompletionDatabase (baseDir, file, this);
					}
					else if (uri.StartsWith ("Gac:"))
					{
						string file = uri.Substring (4);
						db = new AssemblyCodeCompletionDatabase (baseDir, file, this);
					}
					if (db != null)
						databases [uri] = db;
				}
				return db;
			}
		}
		
		void LoadProjectDatabase (IProject project)
		{
			lock (databases)
			{
				string uri = "Project:" + project.Name;
				if (databases.Contains (uri)) return;
				
				ProjectCodeCompletionDatabase db = new ProjectCodeCompletionDatabase (project, this);
				databases [uri] = db;
				
				foreach (ReferenceEntry re in db.References)
				{
					GetDatabase (re.Uri);
				}
			}
		}
		
		void UnloadDatabase (string uri)
		{
			if (uri == CoreDB) return;
			lock (databases)
			{
				CodeCompletionDatabase db = databases [uri] as CodeCompletionDatabase;
				if (db != null) {
					db.Write ();
					databases.Remove (uri);
				}
			}
		}
		
		void UnloadProjectDatabase (IProject project)
		{
			string uri = "Project:" + project.Name;
			UnloadDatabase (uri);
		}
		
		void CleanUnusedDatabases ()
		{
			lock (databases)
			{
				Hashtable references = new Hashtable ();
				foreach (CodeCompletionDatabase db in databases.Values)
				{
					if (db is ProjectCodeCompletionDatabase) {
						foreach (ReferenceEntry re in ((ProjectCodeCompletionDatabase)db).References)
							references [re.Uri] = null;
					}
				}
				
				ArrayList todel = new ArrayList ();
				foreach (DictionaryEntry en in databases)
				{
					if (!(en.Value is ProjectCodeCompletionDatabase) && !references.Contains (en.Key))
						todel.Add (en.Key);
				}
				
				foreach (string uri in todel)
					UnloadDatabase (uri);
			}
		}
		
		public void LoadCombineDatabases (Combine combine)
		{
			ArrayList projects = Combine.GetAllProjects(combine);
			foreach (ProjectCombineEntry entry in projects) {
				LoadProjectDatabase (entry.Project);
			}
		}
		
		public void UnloadCombineDatabases (Combine combine)
		{
			ArrayList projects = Combine.GetAllProjects(combine);
			foreach (ProjectCombineEntry entry in projects) {
				UnloadProjectDatabase (entry.Project);
			}
		}
		
		public void OnCombineOpened(object sender, CombineEventArgs e)
		{
			LoadCombineDatabases (e.Combine);
			e.Combine.EntryAdded += combineEntryAddedHandler;
			e.Combine.EntryRemoved += combineEntryRemovedHandler;
		}
		
		public void OnCombineClosed (object sender, CombineEventArgs e)
		{
			UnloadCombineDatabases (e.Combine);
			CleanUnusedDatabases ();
			e.Combine.EntryAdded -= combineEntryAddedHandler;
			e.Combine.EntryRemoved -= combineEntryRemovedHandler;
		}
		
		void OnProjectRenamed (object sender, ProjectRenameEventArgs args)
		{
			ProjectCodeCompletionDatabase db = GetProjectDatabase (args.Project);
			if (db == null) return;
			
			db.Rename (args.NewName);
			databases.Remove ("Project:" + args.OldName);
			databases ["Project:" + args.NewName] = db;
			RefreshProjectDatabases ();
			CleanUnusedDatabases ();
		}
		
		void OnCombineEntryAdded (object sender, CombineEntryEventArgs args)
		{
			if (args.CombineEntry is ProjectCombineEntry)
				LoadProjectDatabase (((ProjectCombineEntry)args.CombineEntry).Project);
			else if (args.CombineEntry is CombineCombineEntry)
				LoadCombineDatabases (((CombineCombineEntry)args.CombineEntry).Combine);
		}
		
		void OnCombineEntryRemoved (object sender, CombineEntryEventArgs args)
		{
			if (args.CombineEntry is ProjectCombineEntry)
				UnloadProjectDatabase (((ProjectCombineEntry)args.CombineEntry).Project);
			else if (args.CombineEntry is CombineCombineEntry)
				UnloadCombineDatabases (((CombineCombineEntry)args.CombineEntry).Combine);
			CleanUnusedDatabases ();
		}
		
		void OnProjectFilesChanged (object sender, ProjectFileEventArgs args)
		{
			ProjectCodeCompletionDatabase db = GetProjectDatabase (args.Project);
			if (db != null) db.UpdateFromProject ();
		}
		
		void OnProjectReferencesChanged (object sender, ProjectReferenceEventArgs args)
		{
			ProjectCodeCompletionDatabase db = GetProjectDatabase (args.Project);
			if (db != null) {
				db.UpdateFromProject ();
				foreach (ReferenceEntry re in db.References)
				{
					// Make sure the db is loaded
					GetDatabase (re.Uri);
				}
			}
		}
		
		void RefreshProjectDatabases ()
		{
			foreach (CodeCompletionDatabase db in databases.Values)
			{
				ProjectCodeCompletionDatabase pdb = db as ProjectCodeCompletionDatabase;
				if (pdb != null)
					pdb.UpdateFromProject ();
			}
		}
		
		internal void QueueParseJob (WaitCallback callback, object data)
		{
			ParsingJob job = new ParsingJob ();
			job.ParseCallback = callback;
			job.Data = data;
			lock (parseQueue)
			{
				parseQueue.Enqueue (job);
			}
		}
		
		void DeleteObsoleteDatabases ()
		{
			string[] files = Directory.GetFiles (codeCompletionPath, "*.pidb");
			foreach (string file in files)
			{
				string name = Path.GetFileNameWithoutExtension (file);
				string baseDir = Path.GetDirectoryName (file);
				AssemblyCodeCompletionDatabase.CleanDatabase (baseDir, name);
			}
		}
		
		public void StartParserThread()
		{
			Thread t = new Thread(new ThreadStart(ParserUpdateThread));
			t.IsBackground  = true;
			t.Start();
		}
		
		
		void ParserUpdateThread()
		{
			int loop = 0;
			while (true)
			{
				Thread.Sleep(500);
				
				ParseCurrentFile ();
				
				ConsumeParsingQueue ();
				
				if (loop % 10 == 0)
					CheckModifiedFiles ();
				
				loop++;
			}
		}
		
		void CheckModifiedFiles ()
		{
			ArrayList list = new ArrayList ();
			lock (databases) {
				list.AddRange (databases.Values);
			}
			
			foreach (CodeCompletionDatabase db in list) 
				if (!(db is AssemblyCodeCompletionDatabase))
					db.CheckModifiedFiles ();
		}
		
		void ConsumeParsingQueue ()
		{
			int pending;
			do {
				ParsingJob job = null;
				lock (parseQueue)
				{
					if (parseQueue.Count > 0)
						job = (ParsingJob) parseQueue.Dequeue ();
				}
				
				if (job != null)
					job.ParseCallback (job.Data);
				
				lock (parseQueue)
					pending = parseQueue.Count;
				
			}
			while (pending > 0);
		}
		
		
		void ParseCurrentFile()
		{
			try {
				IWorkbenchWindow win = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow;
				if (win == null || win.ActiveViewContent == null) return;
				
				IEditable editable = win.ActiveViewContent as IEditable;
				if (editable == null) return;
				
				string fileName = null;
				
				IViewContent viewContent = win.ViewContent;
				IParseableContent parseableContent = win.ActiveViewContent as IParseableContent;
				
				if (parseableContent != null) {
					fileName = parseableContent.ParseableContentName;
				} else {
					fileName = viewContent.IsUntitled ? viewContent.UntitledName : viewContent.ContentName;
				}
				
				if (fileName == null || fileName.Length == 0) return;
				
				string text = editable.Text;
				if (text == null) return;
					
				IParseInformation parseInformation = null;
				bool updated = false;
				lock (parsings) {
				
					if (lastUpdateSize[fileName] == null || (int)lastUpdateSize[fileName] != text.GetHashCode()) {
						parseInformation = DoParseFile(fileName, text);
						if (parseInformation == null) return;
						
						ProjectCodeCompletionDatabase db = GetProjectDatabase (viewContent.Project);
						if (db != null) {
							ICompilationUnit cu = (ICompilationUnit)parseInformation.BestCompilationUnit;
							ClassUpdateInformation res = db.UpdateClassInformation (cu.Classes, fileName);
							NotifyParseInfoChange (fileName, res);
						}
						lastUpdateSize[fileName] = text.GetHashCode();
						updated = true;
					}
				}
				if (updated && parseInformation != null && editable is IParseInformationListener) {
					((IParseInformationListener)editable).ParseInformationUpdated(parseInformation);
				}
			} catch (Exception e) {
				try {
					Console.WriteLine(e.ToString());
				} catch {}
			}
		}
		
		
#region Default Parser Layer dependent functions

		public IClass GetClass (IProject project, string typeName)
		{
			return GetClass(project, typeName, true);
		}
		
		public IClass GetClass (IProject project, string typeName, bool caseSensitive)
		{
			CodeCompletionDatabase db = GetProjectDatabase (project);
			IClass c;
			if (db != null) {
				c = db.GetClass (typeName, caseSensitive);
				if (c != null) return c;
				foreach (ReferenceEntry re in db.References)
				{
					CodeCompletionDatabase cdb = GetDatabase (re.Uri);
					if (cdb == null) continue;
					c = cdb.GetClass (typeName, caseSensitive);
					if (c != null) return c;
				}
			}
			db = GetDatabase (CoreDB);
			return db.GetClass (typeName, caseSensitive);
		}
		
		public string[] GetNamespaceList (IProject project, string subNameSpace)
		{
			return GetNamespaceList (project, subNameSpace, true);
		}
		
		public string[] GetNamespaceList (IProject project, string subNameSpace, bool caseSensitive)
		{
			ArrayList contents = new ArrayList ();
			
			CodeCompletionDatabase db = GetProjectDatabase (project);
			if (db != null) {
				db.GetNamespaceList (contents, subNameSpace, caseSensitive);
				foreach (ReferenceEntry re in db.References)
				{
					CodeCompletionDatabase cdb = GetDatabase (re.Uri);
					if (cdb == null) continue;
					cdb.GetNamespaceList (contents, subNameSpace, caseSensitive);
				}
			}
			
			db = GetDatabase (CoreDB);
			db.GetNamespaceList (contents, subNameSpace, caseSensitive);
			
			return (string[]) contents.ToArray (typeof(string));
		}
		
		public ArrayList GetNamespaceContents (IProject project, string namspace, bool includeReferences)
		{
			return GetNamespaceContents (project, namspace, includeReferences, true);
		}
		
		public ArrayList GetNamespaceContents (IProject project, string namspace, bool includeReferences, bool caseSensitive)
		{
			ArrayList contents = new ArrayList ();
			
			CodeCompletionDatabase db = GetProjectDatabase (project);
			if (db != null) {
				db.GetNamespaceContents (contents, namspace, caseSensitive);
				if (includeReferences) {
					foreach (ReferenceEntry re in db.References)
					{
						CodeCompletionDatabase cdb = GetDatabase (re.Uri);
						if (cdb == null) continue;
						cdb.GetNamespaceContents (contents, namspace, caseSensitive);
					}
				}
			}
			
			if (includeReferences) {
				db = GetDatabase (CoreDB);
				db.GetNamespaceContents (contents, namspace, caseSensitive);
			}
			
			return contents;
		}
		
		public bool NamespaceExists(IProject project, string name)
		{
			return NamespaceExists(project, name, true);
		}
		
		public bool NamespaceExists(IProject project, string name, bool caseSensitive)
		{
			CodeCompletionDatabase db = GetProjectDatabase (project);
			if (db != null) {
				if (db.NamespaceExists (name, caseSensitive)) return true;
				foreach (ReferenceEntry re in db.References)
				{
					CodeCompletionDatabase cdb = GetDatabase (re.Uri);
					if (cdb == null) continue;
					if (cdb.NamespaceExists (name, caseSensitive)) return true;
				}
			}
			
			db = GetDatabase (CoreDB);
			return db.NamespaceExists (name, caseSensitive);
			}

		public string SearchNamespace(IProject project, IUsing usin, string partitialNamespaceName)
		{
			return SearchNamespace(project, usin, partitialNamespaceName, true);
		}
		
		public string SearchNamespace(IProject project, IUsing usin, string partitialNamespaceName, bool caseSensitive)
		{
//			Console.WriteLine("SearchNamespace : >{0}<", partitialNamespaceName);
			if (NamespaceExists(project, partitialNamespaceName, caseSensitive)) {
				return partitialNamespaceName;
			}
			
			// search for partitial namespaces
			string declaringNamespace = (string)usin.Aliases[""];
			if (declaringNamespace != null) {
				while (declaringNamespace.Length > 0) {
					if ((caseSensitive ? declaringNamespace.EndsWith(partitialNamespaceName) : declaringNamespace.ToLower().EndsWith(partitialNamespaceName.ToLower()) ) && NamespaceExists(project, declaringNamespace, caseSensitive)) {
						return declaringNamespace;
					}
					int index = declaringNamespace.IndexOf('.');
					if (index > 0) {
						declaringNamespace = declaringNamespace.Substring(0, index);
					} else {
						break;
					}
				}
			}
			
			// Remember:
			//     Each namespace has an own using object
			//     The namespace name is an alias which has the key ""
			foreach (DictionaryEntry entry in usin.Aliases) {
				string aliasString = entry.Key.ToString();
				if (caseSensitive ? partitialNamespaceName.StartsWith(aliasString) : partitialNamespaceName.ToLower().StartsWith(aliasString.ToLower())) {
					if (aliasString.Length >= 0) {
						string nsName = nsName = String.Concat(entry.Value.ToString(), partitialNamespaceName.Remove(0, aliasString.Length));
						if (NamespaceExists (project, nsName, caseSensitive)) {
							return nsName;
						}
					}
				}
			}
			return null;
		}

		public IClass SearchType(IProject project, IUsing iusing, string partitialTypeName)
		{
			return SearchType(project, iusing, partitialTypeName, true);
		}
		
		public IClass SearchType(IProject project, IUsing iusing, string partitialTypeName, bool caseSensitive)
		{
//			Console.WriteLine("Search type : >{0}<", partitialTypeName);
			IClass c = GetClass(project, partitialTypeName, caseSensitive);
			if (c != null) {
				return c;
			}
			
			foreach (string str in iusing.Usings) {
				string possibleType = String.Concat(str, ".", partitialTypeName);
//				Console.WriteLine("looking for " + possibleType);
				c = GetClass(project, possibleType, caseSensitive);
				if (c != null) {
//					Console.WriteLine("Found!");
					return c;
				}
			}
			
			// search class in partitial namespaces
			string declaringNamespace = (string)iusing.Aliases[""];
			if (declaringNamespace != null) {
				while (declaringNamespace.Length > 0) {
					string className = String.Concat(declaringNamespace, ".", partitialTypeName);
//					Console.WriteLine("looking for " + className);
					c = GetClass(project, className, caseSensitive);
					if (c != null) {
//						Console.WriteLine("Found!");
						return c;
					}
					int index = declaringNamespace.IndexOf('.');
					if (index > 0) {
						declaringNamespace = declaringNamespace.Substring(0, index);
					} else {
						break;
					}
				}
			}
			
			foreach (DictionaryEntry entry in iusing.Aliases) {
				string aliasString = entry.Key.ToString();
				if (caseSensitive ? partitialTypeName.StartsWith(aliasString) : partitialTypeName.ToLower().StartsWith(aliasString.ToLower())) {
					string className = null;
					if (aliasString.Length > 0) {
						className = String.Concat(entry.Value.ToString(), partitialTypeName.Remove(0, aliasString.Length));
//						Console.WriteLine("looking for " + className);
						c = GetClass(project, className, caseSensitive);
						if (c != null) {
//							Console.WriteLine("Found!");
							return c;
						}
					}
				}
			}
			
			return null;
		}
		
		public IEnumerable GetClassInheritanceTree (IProject project, IClass cls)
		{
			return new ClassInheritanceEnumerator (this, project, cls);
		}
		
#endregion
		
		public IParseInformation ParseFile(string fileName)
		{
			return ParseFile(fileName, null);
		}
		
		public IParseInformation ParseFile (string fileName, string fileContent)
		{
			return DoParseFile (fileName, fileContent);
		}
		
		public IParseInformation DoParseFile (string fileName, string fileContent)
		{
			Console.WriteLine ("PARSING " + fileName);
			IParser parser = GetParser(fileName);
			
			if (parser == null) {
				return null;
			}
			
			parser.LexerTags = new string[] { "HACK", "TODO", "UNDONE", "FIXME" };
			
			ICompilationUnitBase parserOutput = null;
			
			if (fileContent == null) {
				IProjectService projectService = (IProjectService)MonoDevelop.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
				if (projectService.CurrentOpenCombine != null) {
					ArrayList projects = Combine.GetAllProjects(projectService.CurrentOpenCombine);
					foreach (ProjectCombineEntry entry in projects) {
						if (entry.Project.IsFileInProject(fileName)) {
							fileContent = entry.Project.GetParseableFileContent(fileName);
						}
					}
				}
			}
			
			if (fileContent != null) {
				parserOutput = parser.Parse(fileName, fileContent);
			} else {
				parserOutput = parser.Parse(fileName);
			}
			
			ParseInformation parseInformation = GetCachedParseInformation (fileName);
			bool newInfo = false;
			
			if (parseInformation == null) {
				parseInformation = new ParseInformation();
				newInfo = true;
			}
			
			if (parserOutput.ErrorsDuringCompile) {
				parseInformation.DirtyCompilationUnit = parserOutput;
			} else {
				parseInformation.ValidCompilationUnit = parserOutput;
				parseInformation.DirtyCompilationUnit = null;
			}
			
			if (newInfo) {
				AddToCache (parseInformation, fileName);
			}
			
			OnParseInformationChanged (new ParseInformationEventArgs (fileName, parseInformation));
			return parseInformation;
		}
		
		ParseInformation GetCachedParseInformation (string fileName)
		{
			lock (parsings) 
			{
				ParsingCacheEntry en = parsings [fileName] as ParsingCacheEntry;
				if (en != null) {
					en.AccessTime = DateTime.Now;
					return en.ParseInformation;
				}
				else
					return null;
			}
		}
		
		void AddToCache (ParseInformation info, string fileName)
		{
			lock (parsings) 
			{
				if (parsings.Count >= MAX_CACHE_SIZE)
				{
					DateTime tim = DateTime.MaxValue;
					string toDelete = null;
					foreach (DictionaryEntry pce in parsings)
					{
						DateTime ptim = ((ParsingCacheEntry)pce.Value).AccessTime;
						if (ptim < tim) {
							tim = ptim;
							toDelete = pce.Key.ToString();
						}
					}
					parsings.Remove (toDelete);
				}
				
				ParsingCacheEntry en = new ParsingCacheEntry();
				en.ParseInformation = info;
				en.AccessTime = DateTime.Now;
				parsings [fileName] = en;
			}
		}

		public IParseInformation GetParseInformation(string fileName)
		{
			if (fileName == null || fileName.Length == 0) {
				return null;
			}
			
			IParseInformation info = GetCachedParseInformation (fileName);
			if (info != null) return info;
			else return ParseFile(fileName);
		}
		
		public IExpressionFinder GetExpressionFinder(string fileName)
		{
			IParser parser = GetParser(fileName);
			if (parser != null) {
				return parser.ExpressionFinder;
			}
			return null;
		}
		public virtual IParser GetParser(string fileName)
		{
			// HACK: I'm too lazy to do it 'right'
			if (fileName != null) {
				if (Path.GetExtension(fileName).ToUpper() == ".CS") {
					return parser[0];
				}
				if (Path.GetExtension(fileName).ToUpper() == ".VB") {
					return parser[1];
				}
			}
			return null;
		}
		
		////////////////////////////////////
		
		public ArrayList CtrlSpace(IParserService parserService, IProject project, int caretLine, int caretColumn, string fileName)
		{
			IParser parser = GetParser(fileName);
			if (parser != null) {
				return parser.CtrlSpace(parserService, project, caretLine, caretColumn, fileName);
			}
			return null;
		}

		public ArrayList IsAsResolve (string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent)
		{
			try {
				IParser parser = GetParser (fileName);
				if (parser != null) {
					return parser.IsAsResolve (this, expression, caretLineNumber, caretColumn, fileName, fileContent);
				}
				return null;
			} catch {
				return null;
			}
		}
		
		public ResolveResult Resolve(IProject project,
									 string expression, 
		                             int caretLineNumber,
		                             int caretColumn,
		                             string fileName,
		                             string fileContent)
		{
			// added exception handling here to prevent silly parser exceptions from
			// being thrown and corrupting the textarea control
			try {
				IParser parser = GetParser(fileName);
				//Console.WriteLine("Parse info : " + GetParseInformation(fileName).MostRecentCompilationUnit.Tag);
				if (parser != null) {
					return parser.Resolve(this, project, expression, caretLineNumber, caretColumn, fileName, fileContent);
				}
				return null;
			} catch {
				return null;
			}
		}
		
		internal INameEncoder DefaultNameEncoder {
			get { return nameTable; }
		}

		internal INameDecoder DefaultNameDecoder {
			get { return nameTable; }
		}
		
		public string MonodocResolver (string expression, int caretLineNumber, int caretColumn, string fileName, string fileContent)
		{
			try {
				IParser parser = GetParser (fileName);
				if (parser != null) {
					return parser.MonodocResolver (this, expression, caretLineNumber, caretColumn, fileName, fileContent);
				}
				return null;
			} catch {
				return null;
			}
		}
		
		public void NotifyParseInfoChange (string file, ClassUpdateInformation res)
		{
			ClassInformationEventArgs args = new ClassInformationEventArgs (file, res);
			OnClassInformationChanged (args);
		}

		protected virtual void OnParseInformationChanged(ParseInformationEventArgs e)
		{
			if (ParseInformationChanged != null) {
				ParseInformationChanged(this, e);
			}
		}
		
		protected virtual void OnClassInformationChanged(ClassInformationEventArgs e)
		{
			if (ClassInformationChanged != null) {
				ClassInformationChanged(this, e);
			}
		}
		
		public event ParseInformationEventHandler ParseInformationChanged;
		public event ClassInformationEventHandler ClassInformationChanged;
	}
	
	[Serializable]
	public class DummyCompilationUnit : AbstractCompilationUnit
	{
		CommentCollection miscComments = new CommentCollection();
		CommentCollection dokuComments = new CommentCollection();
		TagCollection     tagComments  = new TagCollection();
		
		public override CommentCollection MiscComments {
			get {
				return miscComments;
			}
		}
		
		public override CommentCollection DokuComments {
			get {
				return dokuComments;
			}
		}
		
		public override TagCollection TagComments {
			get {
				return tagComments;
			}
		}
	}
	
	public class ClassInheritanceEnumerator : IEnumerator, IEnumerable
	{
		IParserService parserService;
		IClass topLevelClass;
		IClass currentClass  = null;
		Queue  baseTypeQueue = new Queue();
		IProject project;

		public ClassInheritanceEnumerator(IParserService parserService, IProject project, IClass topLevelClass)
		{
			this.parserService = parserService;
			this.project = project;
			this.topLevelClass = topLevelClass;
			baseTypeQueue.Enqueue(topLevelClass.FullyQualifiedName);
			PutBaseClassesOnStack(topLevelClass);
			baseTypeQueue.Enqueue("System.Object");
		}
		public IEnumerator GetEnumerator()
		{
			return this;
		}

		void PutBaseClassesOnStack(IClass c)
		{
			foreach (string baseTypeName in c.BaseTypes) {
				baseTypeQueue.Enqueue(baseTypeName);
			}
		}

		public IClass Current {
			get {
				return currentClass;
			}
		}

		object IEnumerator.Current {
			get {
				return currentClass;
			}
		}

		public bool MoveNext()
		{
			if (baseTypeQueue.Count == 0) {
				return false;
			}
			string baseTypeName = baseTypeQueue.Dequeue().ToString();

			IClass baseType = parserService.GetClass(project, baseTypeName);
			if (baseType == null) {
				ICompilationUnit unit = currentClass == null ? null : currentClass.CompilationUnit;
				if (unit != null) {
					foreach (IUsing u in unit.Usings) {
						baseType = parserService.SearchType(project, u, baseTypeName);
						if (baseType != null) {
							break;
						}
					}
				}
			}

			if (baseType != null) {
				currentClass = baseType;
				PutBaseClassesOnStack(currentClass);
			}

			return baseType != null;
		}

		public void Reset()
		{
			baseTypeQueue.Clear();
			baseTypeQueue.Enqueue(topLevelClass.FullyQualifiedName);
			PutBaseClassesOnStack(topLevelClass);
			baseTypeQueue.Enqueue("System.Object");
		}
	}	
	
	public class ClassUpdateInformation
	{
		ClassCollection added = new ClassCollection ();
		ClassCollection removed = new ClassCollection ();
		ClassCollection modified = new ClassCollection ();
		
		public ClassCollection Added
		{
			get { return added; }
		}
		
		public ClassCollection Removed
		{
			get { return removed; }
		}
		
		public ClassCollection Modified
		{
			get { return modified; }
		}
	}
}

--=-r+QCz1sSqgvIGOdPecXD--