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

📄 refactoringservice.cs

📁 SharpDevelop2.0.0 c#开发免费工具
💻 CS
📖 第 1 页 / 共 2 页
字号:
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
//     <version>$Revision: 1393 $</version>
// </file>

using System;
using System.Collections.Generic;
using System.Drawing;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;

namespace ICSharpCode.SharpDevelop.Refactoring
{
	public static class RefactoringService
	{
		#region FindDerivedClasses
		/// <summary>
		/// Finds all classes deriving from baseClass.
		/// </summary>
		/// <param name="baseClass">The base class.</param>
		/// <param name="projectContents">The project contents in which derived classes should be searched.</param>
		/// <param name="directDerivationOnly">If true, gets only the classes that derive directly from <paramref name="baseClass"/>.</param>
		public static List<IClass> FindDerivedClasses(IClass baseClass, IEnumerable<IProjectContent> projectContents, bool directDerivationOnly)
		{
			baseClass = baseClass.GetCompoundClass();
			string baseClassName = baseClass.Name;
			string baseClassFullName = baseClass.FullyQualifiedName;
			List<IClass> list = new List<IClass>();
			foreach (IProjectContent pc in projectContents) {
				if (pc != baseClass.ProjectContent && !pc.ReferencedContents.Contains(baseClass.ProjectContent)) {
					// only project contents referencing the content of the base class
					// can derive from the class
					continue;
				}
				AddDerivedClasses(pc, baseClass, baseClassName, baseClassFullName, pc.Classes, list);
			}
			if (!directDerivationOnly) {
				List<IClass> additional = new List<IClass>();
				foreach (IClass c in list) {
					additional.AddRange(FindDerivedClasses(c, projectContents, directDerivationOnly));
				}
				foreach (IClass c in additional) {
					if (!list.Contains(c))
						list.Add(c);
				}
			}
			return list;
		}
		
		static void AddDerivedClasses(IProjectContent pc, IClass baseClass, string baseClassName, string baseClassFullName,
		                              IEnumerable<IClass> classList, IList<IClass> resultList)
		{
			foreach (IClass c in classList) {
				AddDerivedClasses(pc, baseClass, baseClassName, baseClassFullName, c.InnerClasses, resultList);
				int count = c.BaseTypes.Count;
				for (int i = 0; i < count; i++) {
					string baseTypeName = c.BaseTypes[i].Name;
					if (pc.Language.NameComparer.Equals(baseTypeName, baseClassName) ||
					    pc.Language.NameComparer.Equals(baseTypeName, baseClassFullName)) {
						IReturnType possibleBaseClass = c.GetBaseType(i);
						if (possibleBaseClass.FullyQualifiedName == baseClass.FullyQualifiedName) {
							resultList.Add(c);
						}
					}
				}
			}
		}
		#endregion
		
		#region FindReferences
		/// <summary>
		/// Find all references to the specified member.
		/// </summary>
		public static List<Reference> FindReferences(IMember member, IProgressMonitor progressMonitor)
		{
			return RunFindReferences(member.DeclaringType, member, false, progressMonitor);
		}
		
		/// <summary>
		/// Find all references to the specified class.
		/// </summary>
		public static List<Reference> FindReferences(IClass @class, IProgressMonitor progressMonitor)
		{
			if (@class == null)
				throw new ArgumentNullException("class");
			return RunFindReferences(@class, null, false, progressMonitor);
		}
		
		/// <summary>
		/// Find all references to the resolved entity.
		/// </summary>
		public static List<Reference> FindReferences(ResolveResult entity, IProgressMonitor progressMonitor)
		{
			if (entity == null)
				throw new ArgumentNullException("entity");
			if (entity is LocalResolveResult) {
				return RunFindReferences(entity.CallingClass, (entity as LocalResolveResult).Field, true, progressMonitor);
			} else if (entity is TypeResolveResult) {
				return FindReferences((entity as TypeResolveResult).ResolvedClass, progressMonitor);
			} else if (entity is MemberResolveResult) {
				return FindReferences((entity as MemberResolveResult).ResolvedMember, progressMonitor);
			} else if (entity is MethodResolveResult) {
				IMethod method = (entity as MethodResolveResult).GetMethodIfSingleOverload();
				if (method != null) {
					return FindReferences(method, progressMonitor);
				}
			} else if (entity is MixedResolveResult) {
				return FindReferences((entity as MixedResolveResult).PrimaryResult, progressMonitor);
			}
			return null;
		}
		
		/// <summary>
		/// Find all references to the specified local variable.
		/// </summary>
		public static List<Reference> FindReferences(LocalResolveResult local, IProgressMonitor progressMonitor)
		{
			return RunFindReferences(local.CallingClass, local.Field, true, progressMonitor);
		}
		
		/// <summary>
		/// This method can be used in three modes:
		/// 1. Find references to classes (parentClass = targetClass, member = null, isLocal = false)
		/// 2. Find references to members (parentClass = parent, member = member, isLocal = false)
		/// 3. Find references to local variables (parentClass = parent, member = local var as field, isLocal = true)
		/// </summary>
		static List<Reference> RunFindReferences(IClass ownerClass, IMember member,
		                                         bool isLocal,
		                                         IProgressMonitor progressMonitor)
		{
			if (ParserService.LoadSolutionProjectsThreadRunning) {
				MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
				return null;
			}
			List<ProjectItem> files;
			if (isLocal) {
				files = new List<ProjectItem>();
				files.Add(FindItem(ownerClass.CompilationUnit.FileName));
			} else {
				ownerClass = ownerClass.GetCompoundClass();
				files = GetPossibleFiles(ownerClass, member);
			}
			ParseableFileContentEnumerator enumerator = new ParseableFileContentEnumerator(files.ToArray());
			List<Reference> references = new List<Reference>();
			try {
				if (progressMonitor != null) {
					progressMonitor.BeginTask("${res:SharpDevelop.Refactoring.FindingReferences}", files.Count);
				}
				#if DEBUG
				if (System.Windows.Forms.Control.ModifierKeys == System.Windows.Forms.Keys.Control) {
					System.Diagnostics.Debugger.Break();
				}
				#endif
				while (enumerator.MoveNext()) {
					if (progressMonitor != null) {
						progressMonitor.WorkDone = enumerator.Index;
					}
					
					AddReferences(references, ownerClass, member, isLocal, enumerator.CurrentFileName, enumerator.CurrentFileContent);
				}
			} finally {
				if (progressMonitor != null) {
					progressMonitor.Done();
				}
				enumerator.Dispose();
			}
			return references;
		}
		
		/// <summary>
		/// This method can be used in three modes (like RunFindReferences)
		/// </summary>
		static void AddReferences(List<Reference> list,
		                          IClass parentClass, IMember member,
		                          bool isLocal,
		                          string fileName, string fileContent)
		{
			string lowerFileContent = fileContent.ToLowerInvariant();
			string searchedText; // the text that is searched for
			bool searchingIndexer = false;
			
			if (member == null) {
				searchedText = parentClass.Name.ToLowerInvariant();
			} else {
				// When looking for a member, the name of the parent class does not always exist
				// in the file where the member is accessed.
				// (examples: derived classes, partial classes)
				if (member is IMethod && ((IMethod)member).IsConstructor)
					searchedText = parentClass.Name.ToLowerInvariant();
				else {
					if (member is IProperty && ((IProperty)member).IsIndexer) {
						searchingIndexer = true;
						searchedText = GetIndexerExpressionStartToken(fileName);
					} else {
						searchedText = member.Name.ToLowerInvariant();
					}
				}
			}
			
			int pos = -1;
			int exprPos;
			IExpressionFinder expressionFinder = null;
			while ((pos = lowerFileContent.IndexOf(searchedText, pos + 1)) >= 0) {
				if (!searchingIndexer) {
					if (pos > 0 && char.IsLetterOrDigit(fileContent, pos - 1)) {
						continue; // memberName is not a whole word (a.SomeName cannot reference Name)
					}
					if (pos < fileContent.Length - searchedText.Length - 1
					    && char.IsLetterOrDigit(fileContent, pos + searchedText.Length))
					{
						continue; // memberName is not a whole word (a.Name2 cannot reference Name)
					}
					exprPos = pos;
				} else {
					exprPos = pos-1;	// indexer expressions are found by resolving the part before the indexer
				}
				
				if (expressionFinder == null) {
					expressionFinder = ParserService.GetExpressionFinder(fileName);
				}
				ExpressionResult expr = expressionFinder.FindFullExpression(fileContent, exprPos);
				if (expr.Expression != null) {
					Point position = GetPosition(fileContent, exprPos);
				repeatResolve:
					// TODO: Optimize by re-using the same resolver if multiple expressions were
					// found in this file (the resolver should parse all methods at once)
					ResolveResult rr = ParserService.Resolve(expr, position.Y, position.X, fileName, fileContent);
					MemberResolveResult mrr = rr as MemberResolveResult;
					if (isLocal) {
						// find reference to local variable
						if (IsReferenceToLocalVariable(rr, member)) {
							list.Add(new Reference(fileName, pos, searchedText.Length, expr.Expression, rr));
						} else if (FixIndexerExpression(expressionFinder, ref expr, mrr)) {
							goto repeatResolve;
						}
					} else if (member != null) {
						// find reference to member
						if (IsReferenceToMember(member, rr)) {
							list.Add(new Reference(fileName, pos, searchedText.Length, expr.Expression, rr));
						} else if (FixIndexerExpression(expressionFinder, ref expr, mrr)) {
							goto repeatResolve;
						}
					} else {
						// find reference to class
						if (mrr != null) {
							if (mrr.ResolvedMember is IMethod && ((IMethod)mrr.ResolvedMember).IsConstructor) {
								if (mrr.ResolvedMember.DeclaringType.FullyQualifiedName == parentClass.FullyQualifiedName) {
									list.Add(new Reference(fileName, pos, searchedText.Length, expr.Expression, rr));
								}
							}
						} else {
							if (rr is TypeResolveResult && rr.ResolvedType.FullyQualifiedName == parentClass.FullyQualifiedName) {
								list.Add(new Reference(fileName, pos, searchedText.Length, expr.Expression, rr));
							}
						}
					}
				}
			}
		}
		
		/// <summary>
		/// Makes the given ExpressionResult point to the underlying expression if
		/// the expression is an indexer expression.

⌨️ 快捷键说明

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