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

📄 parserservice.cs

📁 SharpDevelop2.0.0 c#开发免费工具
💻 CS
📖 第 1 页 / 共 2 页
字号:
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Mike Krüger" email="mike@icsharpcode.net"/>
//     <version>$Revision: 1393 $</version>
// </file>

using System;
using System.IO;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
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;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Dom;

namespace ICSharpCode.Core
{
	public static class ParserService
	{
		static ParserDescriptor[] parser;
		
		static Dictionary<IProject, IProjectContent> projectContents = new Dictionary<IProject, IProjectContent>();
		static Dictionary<string, ParseInformation> parsings = new Dictionary<string, ParseInformation>();
		
		public static IProjectContent CurrentProjectContent {
			[DebuggerStepThrough]
			get {
				if (forcedContent != null) return forcedContent;
				
				if (ProjectService.CurrentProject == null || !projectContents.ContainsKey(ProjectService.CurrentProject)) {
					return DefaultProjectContent;
				}
				return projectContents[ProjectService.CurrentProject];
			}
		}
		
		static IProjectContent forcedContent;
		/// <summary>
		/// Used for unit tests ONLY!!
		/// </summary>
		public static void ForceProjectContent(IProjectContent content)
		{
			forcedContent = content;
		}
		
		/// <summary>
		/// Gets the list of project contents of all open projects.
		/// </summary>
		public static IEnumerable<IProjectContent> AllProjectContents {
			get {
				return projectContents.Values;
			}
		}
		
		/// <summary>
		/// Gets the list of project contents of all open projects plus the referenced project contents.
		/// </summary>
		public static IEnumerable<IProjectContent> AllProjectContentsWithReferences {
			get {
				foreach (IProjectContent pc in AllProjectContents) {
					yield return pc;
				}
				foreach (IProjectContent pc in ProjectContentRegistry.LoadedProjectContents) {
					yield return pc;
				}
			}
		}
		
		static ParserService()
		{
			parser = (ParserDescriptor[])AddInTree.BuildItems("/Workspace/Parser", null, false).ToArray(typeof(ParserDescriptor));
			
			ProjectService.SolutionClosed += ProjectServiceSolutionClosed;
		}
		
		static void ProjectServiceSolutionClosed(object sender, EventArgs e)
		{
			abortLoadSolutionProjectsThread = true;
			lock (projectContents) {
				foreach (IProjectContent content in projectContents.Values) {
					content.Dispose();
				}
				projectContents.Clear();
				parsings.Clear();
			}
		}
		
		static Thread loadSolutionProjectsThread;
		static bool   abortLoadSolutionProjectsThread;
		
		// do not use an event for this because a solution might be loaded before ParserService
		// is initialized
		internal static void OnSolutionLoaded()
		{
			if (loadSolutionProjectsThread != null) {
				if (!abortLoadSolutionProjectsThread)
					throw new InvalidOperationException("Cannot open new combine without closing old combine!");
				if (!loadSolutionProjectsThread.Join(50)) {
					// loadSolutionProjects might be waiting for main thread, so give it
					// a chance to complete asynchronous calls
					WorkbenchSingleton.SafeThreadAsyncCall((ThreadStart)OnSolutionLoaded);
					return;
				}
			}
			loadSolutionProjectsThread = new Thread(new ThreadStart(LoadSolutionProjects));
			loadSolutionProjectsThread.Priority = ThreadPriority.BelowNormal;
			loadSolutionProjectsThread.IsBackground = true;
			loadSolutionProjectsThread.Start();
		}
		
		public static bool LoadSolutionProjectsThreadRunning {
			get {
				return loadSolutionProjectsThread != null;
			}
		}
		
		static void LoadSolutionProjects()
		{
			try {
				abortLoadSolutionProjectsThread = false;
				LoggingService.Info("Start LoadSolutionProjects thread");
				LoadSolutionProjectsInternal();
			} finally {
				LoggingService.Info("LoadSolutionProjects thread ended");
				loadSolutionProjectsThread = null;
				OnLoadSolutionProjectsThreadEnded(EventArgs.Empty);
			}
		}
		
		static void LoadSolutionProjectsInternal()
		{
			List<ParseProjectContent> createdContents = new List<ParseProjectContent>();
			foreach (IProject project in ProjectService.OpenSolution.Projects) {
				try {
					ParseProjectContent newContent = project.CreateProjectContent();
					lock (projectContents) {
						projectContents[project] = newContent;
					}
					createdContents.Add(newContent);
				} catch (Exception e) {
					ICSharpCode.Core.MessageService.ShowError(e, "Error while retrieving project contents from " + project);
				}
			}
			WorkbenchSingleton.SafeThreadAsyncCall((ThreadStart)ProjectService.ParserServiceCreatedProjectContents);
			int workAmount = 0;
			foreach (ParseProjectContent newContent in createdContents) {
				if (abortLoadSolutionProjectsThread) return;
				try {
					newContent.Initialize1();
					workAmount += newContent.GetInitializationWorkAmount();
				} catch (Exception e) {
					ICSharpCode.Core.MessageService.ShowError(e, "Error while initializing project references:" + newContent);
				}
			}
			StatusBarService.ProgressMonitor.BeginTask("Parsing...", workAmount);
			foreach (ParseProjectContent newContent in createdContents) {
				if (abortLoadSolutionProjectsThread) break;
				try {
					newContent.Initialize2();
				} catch (Exception e) {
					ICSharpCode.Core.MessageService.ShowError(e, "Error while initializing project contents:" + newContent);
				}
			}
			StatusBarService.ProgressMonitor.Done();
		}
		
		static void InitAddedProject(object state)
		{
			ParseProjectContent newContent = (ParseProjectContent)state;
			newContent.Initialize1();
			StatusBarService.ProgressMonitor.BeginTask("Parsing...", newContent.GetInitializationWorkAmount());
			newContent.Initialize2();
			StatusBarService.ProgressMonitor.Done();
		}
		
		static void ReparseProject(object state)
		{
			ParseProjectContent newContent = (ParseProjectContent)state;
			StatusBarService.ProgressMonitor.BeginTask("Parsing...", newContent.GetInitializationWorkAmount());
			newContent.ReInitialize2();
			StatusBarService.ProgressMonitor.Done();
		}
		
		public static void Reparse(IProject project)
		{
			ParseProjectContent pc = GetProjectContent(project) as ParseProjectContent;
			if (pc != null) {
				ThreadPool.QueueUserWorkItem(ReparseProject, pc);
			}
		}
		
		internal static IProjectContent CreateProjectContentForAddedProject(IProject project)
		{
			lock (projectContents) {
				ParseProjectContent newContent = project.CreateProjectContent();
				projectContents[project] = newContent;
				ThreadPool.QueueUserWorkItem(InitAddedProject, newContent);
				return newContent;
			}
		}
		
		public static IProjectContent GetProjectContent(IProject project)
		{
			lock (projectContents) {
				if (projectContents.ContainsKey(project)) {
					return projectContents[project];
				}
			}
			return null;
		}
		
		static Queue<KeyValuePair<string, string>> parseQueue = new Queue<KeyValuePair<string, string>>();
		
		static void ParseQueue()
		{
			while (true) {
				KeyValuePair<string, string> entry;
				lock (parseQueue) {
					if (parseQueue.Count == 0)
						return;
					entry = parseQueue.Dequeue();
				}
				ParseFile(entry.Key, entry.Value);
			}
		}
		
		public static void EnqueueForParsing(string fileName)
		{
			EnqueueForParsing(fileName, GetParseableFileContent(fileName));
		}
		
		public static void EnqueueForParsing(string fileName, string fileContent)
		{
			lock (parseQueue) {
				parseQueue.Enqueue(new KeyValuePair<string, string>(fileName, fileContent));
			}
		}
		
		public static void StartParserThread()
		{
			abortParserUpdateThread = false;
			Thread parserThread = new Thread(new ThreadStart(ParserUpdateThread));
			parserThread.Priority = ThreadPriority.BelowNormal;
			parserThread.IsBackground  = true;
			parserThread.Start();
		}
		
		public static void StopParserThread()
		{
			abortParserUpdateThread = true;
		}
		
		static volatile bool abortParserUpdateThread = false;
		
		static Dictionary<string, int> lastUpdateHash = new Dictionary<string, int>();
		
		static void ParserUpdateThread()
		{
			LoggingService.Info("ParserUpdateThread started");
			// preload mscorlib, we're going to need it anyway
			IProjectContent dummyVar = ProjectContentRegistry.Mscorlib;
			
			while (!abortParserUpdateThread) {
				try {
					ParseQueue();
					ParserUpdateStep();
				} catch (Exception e) {
					ICSharpCode.Core.MessageService.ShowError(e);
					
					// don't fire an exception every 2 seconds at the user, give him at least
					// time to read the first :-)
					Thread.Sleep(10000);
				}
				Thread.Sleep(2000);
			}
			LoggingService.Info("ParserUpdateThread stopped");
		}
		
		static object[] GetWorkbench()
		{
			IWorkbenchWindow activeWorkbenchWindow = WorkbenchSingleton.Workbench.ActiveWorkbenchWindow;
			if (activeWorkbenchWindow == null)
				return null;
			IBaseViewContent activeViewContent = activeWorkbenchWindow.ActiveViewContent;
			if (activeViewContent == null)
				return null;
			return new object[] { activeViewContent, activeWorkbenchWindow.ViewContent };
		}
		
		public static void ParseCurrentViewContent()
		{
			ParserUpdateStep();
		}
		
		static void ParserUpdateStep()
		{
			object[] workbench;
			try {
				workbench = (object[])WorkbenchSingleton.SafeThreadCall(typeof(ParserService), "GetWorkbench");
			} catch (ObjectDisposedException) {
				// maybe workbench has been disposed while waiting for the SafeThreadCall
				LoggingService.Warn("ObjectDisposedException while trying to invoke GetWorkbench()");
				if (abortParserUpdateThread)
					return; // abort this thread
				else
					throw;  // some other error -> re-raise
			}
			if (workbench != null) {
				IEditable editable = workbench[0] as IEditable;
				if (editable != null) {
					string fileName = null;
					
					IViewContent viewContent = (IViewContent)workbench[1];
					IParseableContent parseableContent = workbench[0] as IParseableContent;
					
					//ivoko: Pls, do not throw text = parseableContent.ParseableText away. I NEED it.
					string text = null;
					if (parseableContent != null) {
						fileName = parseableContent.ParseableContentName;
						text = parseableContent.ParseableText;
					} else {
						fileName = viewContent.IsUntitled ? viewContent.UntitledName : viewContent.FileName;

⌨️ 快捷键说明

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