⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 defaultparserservice.cs

📁 c#源代码
💻 CS
📖 第 1 页 / 共 4 页
字号:
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Mike Krueger" 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.InteropServices;
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 System.Text;

using ICSharpCode.Core.Properties;
using ICSharpCode.Core.Services;
using ICSharpCode.SharpDevelop.Services;
using ICSharpCode.Core.AddIns;
using ICSharpCode.SharpDevelop.Internal.Project;
using ICSharpCode.SharpDevelop.Gui;
using SharpDevelop.Internal.Parser;

namespace ICSharpCode.SharpDevelop.Services
{
	public class DefaultParserService : AbstractService, IParserService
	{
		Hashtable classes                = new Hashtable();
		Hashtable caseInsensitiveClasses = new Hashtable();
		
		// used to map 'real' namespace hashtable inside case insensitive hashtable
		const string CaseInsensitiveKey = "__CASE_INSENSITIVE_HASH";
		Hashtable namespaces                = new Hashtable();
		Hashtable caseInsensitiveNamespaces = new Hashtable();
		
		Hashtable parsings   = new Hashtable();
		
		ParseInformation addedParseInformation = new ParseInformation();
		ParseInformation removedParseInformation = new ParseInformation();

		/// <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();
		
		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"
		};
		
		public DefaultParserService()
		{
			addedParseInformation.DirtyCompilationUnit = new DummyCompilationUnit();
			removedParseInformation.DirtyCompilationUnit = new DummyCompilationUnit();
		}
		
		public static string[] AssemblyList {
			get {
				return assemblyList;
			}
		}

		/// <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;
			}
		}
		
		public void GenerateCodeCompletionDatabase(string createPath, IProgressMonitor progressMonitor)
		{
			SetCodeCompletionFileLocation(createPath);

			// 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("generate code completion database", assemblyList.Length);
			}
			
			// convert all assemblies
			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());
					
					AssemblyInformation frameworkAssemblyInformation = new AssemblyInformation();
					frameworkAssemblyInformation.Load(String.Concat(path, assemblyList[i], ".dll"), 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) {
						progressMonitor.Worked(i);
					}
				} catch (Exception) {
				}
			}

			classWriter.Close();
			proxyWriter.Close();
			if (progressMonitor != null) {
				progressMonitor.Done();
			}
		}
		
		void SetCodeCompletionFileLocation(string path)
		{
			FileUtilityService fileUtilityService = (FileUtilityService)ServiceManager.Services.GetService(typeof(FileUtilityService));
			string codeCompletionTemp = fileUtilityService.GetDirectoryNameWithSeparator(path);

			codeCompletionProxyFile = codeCompletionTemp + "CodeCompletionProxyDataV02.bin";
			codeCompletionMainFile  = codeCompletionTemp + "CodeCompletionMainDataV02.bin";
		}

		void SetDefaultCompletionFileLocation()
		{
			PropertyService propertyService = (PropertyService)ServiceManager.Services.GetService(typeof(PropertyService));
			SetCodeCompletionFileLocation(propertyService.GetProperty("SharpDevelop.CodeCompletion.DataDirectory", String.Empty).ToString());
		}

		public void LoadProxyDataFile()
		{
			if (!File.Exists(codeCompletionProxyFile)) {
				return;
			}
			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;
				}
			}
			reader.Close();
		}
		
		void LoadThread()
		{
			SetDefaultCompletionFileLocation();
			
			BinaryFormatter formatter = new BinaryFormatter();
			
			if (File.Exists(codeCompletionProxyFile)) {
				LoadProxyDataFile();
			}
		}
		
		public override void InitializeService()
		{
			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)ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
			projectService.CombineOpened += new CombineEventHandler(OpenCombine);
		}
		
		public void AddReferenceToCompletionLookup(IProject project, ProjectReference reference)
		{
			if (reference.ReferenceType == ReferenceType.Project) {
				IProjectService projectService = (IProjectService)ICSharpCode.Core.Services.ServiceManager.Services.GetService(typeof(IProjectService));
				IProject refProject = projectService.GetProject(reference.Reference);
				// don't load project assemblies when a parser for them exists
				if (refProject == null)
					return;
				foreach (IParser possibleParser in parser) {
					if (possibleParser.CanParse(refProject))
						return;
				}
			}
			
			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;
				}
			}
//				// HACK : Don't load references for non C# projects
//				if (project.ProjectType != "C#") {
//					return;
//				}
			
			if (File.Exists(fileName)) {
				try {
					AssemblyLoader assemblyLoader = new AssemblyLoader(this, fileName);
					assemblyLoader.NonLocking = reference.ReferenceType != ReferenceType.Gac;
					Thread t = new Thread(new ThreadStart(assemblyLoader.LoadAssemblyParseInformations));
					t.IsBackground = true;
					t.Start();
				} catch (Exception e) { Console.WriteLine(e); }
			}
		}
		
		class AssemblyLoader
		{
			DefaultParserService parserService;
			string assemblyFileName;
			bool nonLocking = false;
			
			public bool NonLocking {
				get {
					return nonLocking;
				}
				set {
					nonLocking = value;
				}
			}
			
			public AssemblyLoader(DefaultParserService parserService, string assemblyFileName)
			{
				this.parserService    = parserService;
				this.assemblyFileName = assemblyFileName;
			}
			
			public void LoadAssemblyParseInformations()
			{
				if (parserService.loadedAssemblies[assemblyFileName] != null) {
					return;
				}
				parserService.loadedAssemblies[assemblyFileName] = true;
				//Console.WriteLine("Before: " + Environment.WorkingSet / (1024 * 1024) + " -- " + assemblyFileName);
				try {
					AssemblyInformation assemblyInformation = new AssemblyInformation();
					assemblyInformation.Load(assemblyFileName, nonLocking);
					
					foreach (IClass newClass in assemblyInformation.Classes) {
						Console.WriteLine(newClass);
						parserService.AddClassToNamespaceList(newClass);
						lock (parserService.classes) {
							parserService.caseInsensitiveClasses[newClass.FullyQualifiedName.ToLower()] = parserService.classes[newClass.FullyQualifiedName] = new ClasstableEntry(null, null, newClass);
						}
					}
				} catch (Exception) {
				}
				//Console.WriteLine("After: " + Environment.WorkingSet / (1024 * 1024) + " -- " + assemblyFileName);
			}
		}
		
		public virtual void OpenCombine(object sender, CombineEventArgs e)
		{
			ArrayList projects =  Combine.GetAllProjects(e.Combine);
			foreach (ProjectCombineEntry entry in projects) {
				foreach (ProjectReference r in entry.Project.ProjectReferences) {
					AddReferenceToCompletionLookup(entry.Project, r);
				}
			}
		}
		
		public void StartParserThread()
		{
			Thread parserThread = new Thread(new ThreadStart(ParserUpdateThread));
			parserThread.IsBackground  = true;
			parserThread.Start();
		}
		
		public override void UnloadService()
		{
			doneParserThread = true;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -