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

📄 nrefactoryresolver.cs

📁 SharpDevelop2.0.0 c#开发免费工具
💻 CS
📖 第 1 页 / 共 3 页
字号:
// <file>
//     <copyright see="prj:///doc/copyright.txt"/>
//     <license see="prj:///doc/license.txt"/>
//     <owner name="Andrea Paatz" email="andrea@icsharpcode.net"/>
//     <version>$Revision: 1379 $</version>
// </file>

using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;

using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.NRefactory.Parser.AST;
using ICSharpCode.NRefactory.Parser;

namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
	public class NRefactoryResolver : IResolver
	{
		ICompilationUnit cu;
		IClass callingClass;
		IMember callingMember;
		ICSharpCode.NRefactory.Parser.LookupTableVisitor lookupTableVisitor;
		IProjectContent projectContent = null;
		
		SupportedLanguage language;
		
		int caretLine;
		int caretColumn;
		
		public SupportedLanguage Language {
			get {
				return language;
			}
		}
		
		public IProjectContent ProjectContent {
			get {
				return projectContent;
			}
			set {
				projectContent = value;
			}
		}
		
		public ICompilationUnit CompilationUnit {
			get {
				return cu;
			}
		}
		
		public IClass CallingClass {
			get {
				return callingClass;
			}
		}
		
		public IMember CallingMember {
			get {
				return callingMember;
			}
		}
		
		public int CaretLine {
			get {
				return caretLine;
			}
		}
		
		public int CaretColumn {
			get {
				return caretColumn;
			}
		}
		
		LanguageProperties languageProperties;
		
		public LanguageProperties LanguageProperties {
			get {
				return languageProperties;
			}
		}
		
		public NRefactoryResolver(SupportedLanguage language)
		{
			this.language = language;
			this.projectContent = ParserService.CurrentProjectContent;
			switch (language) {
				case SupportedLanguage.CSharp:
					languageProperties = LanguageProperties.CSharp;
					break;
				case SupportedLanguage.VBNet:
					languageProperties = LanguageProperties.VBNet;
					break;
				default:
					throw new NotSupportedException("The language " + language + " is not supported in the resolver");
			}
		}
		
		Expression ParseExpression(string expression)
		{
			Expression expr = SpecialConstructs(expression);
			if (expr == null) {
				using (ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, new System.IO.StringReader(expression))) {
					expr = p.ParseExpression();
				}
			}
			return expr;
		}
		
		string GetFixedExpression(ExpressionResult expressionResult)
		{
			string expression = expressionResult.Expression;
			if (expression == null) {
				expression = "";
			}
			expression = expression.TrimStart();
			
			return expression;
		}
		
		public static ResolveResult GetResultFromDeclarationLine(IClass callingClass, IMethodOrProperty callingMember, int caretLine, int caretColumn, string expression)
		{
			if (callingClass == null) return null;
			int pos = expression.IndexOf('(');
			if (pos >= 0) {
				expression = expression.Substring(0, pos);
			}
			expression = expression.Trim();
			if (!callingClass.BodyRegion.IsInside(caretLine, caretColumn)
			    && callingClass.ProjectContent.Language.NameComparer.Equals(expression, callingClass.Name))
			{
				return new TypeResolveResult(callingClass, callingMember, callingClass);
			}
			if (callingMember != null
			    && !callingMember.BodyRegion.IsInside(caretLine, caretColumn)
			    && callingClass.ProjectContent.Language.NameComparer.Equals(expression, callingMember.Name))
			{
				return new MemberResolveResult(callingClass, callingMember, callingMember);
			}
			return null;
		}
		
		public ResolveResult Resolve(ExpressionResult expressionResult,
		                             int caretLineNumber,
		                             int caretColumn,
		                             string fileName,
		                             string fileContent)
		{
			string expression = GetFixedExpression(expressionResult);
			
			this.caretLine   = caretLineNumber;
			this.caretColumn = caretColumn;
			
			ParseInformation parseInfo = ParserService.GetParseInformation(fileName);
			if (parseInfo == null) {
				return null;
			}
			
			cu = parseInfo.MostRecentCompilationUnit;
			
			if (cu != null) {
				callingClass = cu.GetInnermostClass(caretLine, caretColumn);
			}
			
			Expression expr = null;
			if (language == SupportedLanguage.VBNet) {
				if (expression.Length == 0 || expression[0] == '.') {
					return WithResolve(expression, fileContent);
				} else if ("global".Equals(expression, StringComparison.InvariantCultureIgnoreCase)) {
					return new NamespaceResolveResult(null, null, "");
				}
			}
			if (expr == null) {
				expr = ParseExpression(expression);
				if (expr == null) {
					return null;
				}
				if (expressionResult.Context.IsObjectCreation) {
					Expression tmp = expr;
					while (tmp != null) {
						if (tmp is IdentifierExpression)
							return ResolveInternal(expr, ExpressionContext.Type);
						if (tmp is FieldReferenceExpression)
							tmp = (tmp as FieldReferenceExpression).TargetObject;
						else
							break;
					}
					expr = ParseExpression("new " + expression);
					if (expr == null) {
						return null;
					}
				}
			}
			
			if (expressionResult.Context == ExpressionContext.Attribute) {
				return ResolveAttribute(expr);
			}
			
			RunLookupTableVisitor(fileContent);
			
			ResolveResult rr = GetResultFromDeclarationLine(callingClass, callingMember as IMethodOrProperty, caretLine, caretColumn, expression);
			if (rr != null) return rr;
			
			return ResolveInternal(expr, expressionResult.Context);
		}
		
		ResolveResult WithResolve(string expression, string fileContent)
		{
			RunLookupTableVisitor(fileContent);
			
			WithStatement innermost = null;
			if (lookupTableVisitor.WithStatements != null) {
				foreach (WithStatement with in lookupTableVisitor.WithStatements) {
					if (IsInside(new Point(caretColumn, caretLine), with.StartLocation, with.EndLocation)) {
						innermost = with;
					}
				}
			}
			if (innermost != null) {
				if (expression.Length > 1) {
					Expression expr = ParseExpression(DummyFindVisitor.dummyName + expression);
					if (expr == null) return null;
					DummyFindVisitor v = new DummyFindVisitor();
					expr.AcceptVisitor(v, null);
					if (v.result == null) return null;
					v.result.TargetObject = innermost.Expression;
					return ResolveInternal(expr, ExpressionContext.Default);
				} else {
					return ResolveInternal(innermost.Expression, ExpressionContext.Default);
				}
			} else {
				return null;
			}
		}
		private class DummyFindVisitor : AbstractAstVisitor {
			internal const string dummyName = "___withStatementExpressionDummy";
			internal FieldReferenceExpression result;
			public override object Visit(FieldReferenceExpression fieldReferenceExpression, object data)
			{
				IdentifierExpression ie = fieldReferenceExpression.TargetObject as IdentifierExpression;
				if (ie != null && ie.Identifier == dummyName)
					result = fieldReferenceExpression;
				return base.Visit(fieldReferenceExpression, data);
			}
		}
		
		void RunLookupTableVisitor(string fileContent)
		{
			lookupTableVisitor = new LookupTableVisitor(languageProperties.NameComparer);
			
			callingMember = GetCurrentMember();
			if (callingMember != null) {
				System.IO.TextReader content = ExtractMethod(fileContent, callingMember);
				if (content != null) {
					ICSharpCode.NRefactory.Parser.IParser p = ParserFactory.CreateParser(language, content);
					p.Parse();
					lookupTableVisitor.Visit(p.CompilationUnit, null);
				}
			}
		}
		
		string GetAttributeName(Expression expr)
		{
			if (expr is IdentifierExpression) {
				return (expr as IdentifierExpression).Identifier;
			} else if (expr is FieldReferenceExpression) {
				TypeVisitor typeVisitor = new TypeVisitor(this);
				FieldReferenceExpression fieldReferenceExpression = (FieldReferenceExpression)expr;
				IReturnType type = fieldReferenceExpression.TargetObject.AcceptVisitor(typeVisitor, null) as IReturnType;
				if (type is TypeVisitor.NamespaceReturnType) {
					return type.FullyQualifiedName + "." + fieldReferenceExpression.FieldName;
				}
			}
			return null;
		}
		
		IClass GetAttribute(string name)
		{
			if (name == null)
				return null;
			IClass c = SearchClass(name);
			if (c != null) {
				if (c.IsTypeInInheritanceTree(ProjectContentRegistry.Mscorlib.GetClass("System.Attribute")))
					return c;
			}
			return SearchClass(name + "Attribute");
		}
		
		ResolveResult ResolveAttribute(Expression expr)
		{
			string attributeName = GetAttributeName(expr);
			IClass c = GetAttribute(attributeName);
			if (c != null) {
				return new TypeResolveResult(callingClass, callingMember, c);
			} else if (expr is InvocationExpression) {
				InvocationExpression ie = (InvocationExpression)expr;
				attributeName = GetAttributeName(ie.TargetObject);
				c = GetAttribute(attributeName);
				if (c != null) {
					List<IMethod> ctors = new List<IMethod>();
					foreach (IMethod m in c.Methods) {
						if (m.IsConstructor && !m.IsStatic)
							ctors.Add(m);
					}
					TypeVisitor typeVisitor = new TypeVisitor(this);
					return CreateMemberResolveResult(typeVisitor.FindOverload(ctors, null, ie.Arguments, null));
				}
			}
			return null;
		}
		
		ResolveResult ResolveInternal(Expression expr, ExpressionContext context)
		{
			TypeVisitor typeVisitor = new TypeVisitor(this);
			IReturnType type;
			
			if (expr is PrimitiveExpression) {
				if (((PrimitiveExpression)expr).Value is int)
					return new IntegerLiteralResolveResult(callingClass, callingMember);
			} else if (expr is InvocationExpression) {
				IMethodOrProperty method = typeVisitor.GetMethod(expr as InvocationExpression);
				if (method != null) {
					return CreateMemberResolveResult(method);
				} else {
					// InvocationExpression can also be a delegate/event call
					ResolveResult invocationTarget = ResolveInternal((expr as InvocationExpression).TargetObject, ExpressionContext.Default);
					if (invocationTarget == null)
						return null;
					type = invocationTarget.ResolvedType;
					if (type == null)
						return null;
					IClass c = type.GetUnderlyingClass();
					if (c == null || c.ClassType != ClassType.Delegate)
						return null;
					// We don't want to show "System.EventHandler.Invoke" in the tooltip
					// of "EventCall(this, EventArgs.Empty)", we just show the event/delegate for now
					
					// but for DelegateCall(params).* completion, we use the delegate's
					// return type instead of the delegate type itself
					method = c.Methods.Find(delegate(IMethod innerMethod) { return innerMethod.Name == "Invoke"; });
					if (method != null)
						invocationTarget.ResolvedType = method.ReturnType;
					
					return invocationTarget;
				}
			} else if (expr is IndexerExpression) {
				return CreateMemberResolveResult(typeVisitor.GetIndexer(expr as IndexerExpression));
			} else if (expr is FieldReferenceExpression) {
				FieldReferenceExpression fieldReferenceExpression = (FieldReferenceExpression)expr;
				if (fieldReferenceExpression.FieldName == null || fieldReferenceExpression.FieldName.Length == 0) {
					// NRefactory creates this "dummy" fieldReferenceExpression when it should
					// parse a primitive type name (int, short; Integer, Decimal)
					if (fieldReferenceExpression.TargetObject is TypeReferenceExpression) {
						type = TypeVisitor.CreateReturnType(((TypeReferenceExpression)fieldReferenceExpression.TargetObject).TypeReference, this);
						if (type != null) {
							return new TypeResolveResult(callingClass, callingMember, type);
						}
					}
				}
				type = fieldReferenceExpression.TargetObject.AcceptVisitor(typeVisitor, null) as IReturnType;
				if (type != null) {
					ResolveResult result = ResolveMemberReferenceExpression(type, fieldReferenceExpression);
					if (result != null)
						return result;
				}
			} else if (expr is IdentifierExpression) {
				ResolveResult result = ResolveIdentifier(((IdentifierExpression)expr).Identifier, context);
				if (result != null)
					return result;
			} else if (expr is TypeReferenceExpression) {
				type = TypeVisitor.CreateReturnType(((TypeReferenceExpression)expr).TypeReference, this);
				if (type != null) {
					if (type is TypeVisitor.NamespaceReturnType)
						return new NamespaceResolveResult(callingClass, callingMember, type.FullyQualifiedName);
					IClass c = type.GetUnderlyingClass();
					if (c != null)
						return new TypeResolveResult(callingClass, callingMember, type, c);
				}
				return null;

⌨️ 快捷键说明

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