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

📄 typevisitor.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: 1339 $</version>
// </file>

// created on 22.08.2003 at 19:02

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

using ICSharpCode.NRefactory.Parser;
using ICSharpCode.NRefactory.Parser.AST;

using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.Core;

namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
	public class TypeVisitor : AbstractAstVisitor
	{
		NRefactoryResolver resolver;
		
		public TypeVisitor(NRefactoryResolver resolver)
		{
			this.resolver = resolver;
		}
		
		public override object Visit(PrimitiveExpression primitiveExpression, object data)
		{
			if (primitiveExpression.Value == null) {
				return NullReturnType.Instance;
			} else {
				return ReflectionReturnType.CreatePrimitive(primitiveExpression.Value.GetType());
			}
		}
		
		public override object Visit(BinaryOperatorExpression binaryOperatorExpression, object data)
		{
			switch (binaryOperatorExpression.Op) {
				case BinaryOperatorType.NullCoalescing:
					return binaryOperatorExpression.Right.AcceptVisitor(this, data);
				case BinaryOperatorType.DivideInteger:
					return ReflectionReturnType.Int;
				case BinaryOperatorType.Concat:
					return ReflectionReturnType.String;
				case BinaryOperatorType.Equality:
				case BinaryOperatorType.InEquality:
				case BinaryOperatorType.ReferenceEquality:
				case BinaryOperatorType.ReferenceInequality:
				case BinaryOperatorType.LogicalAnd:
				case BinaryOperatorType.LogicalOr:
				case BinaryOperatorType.LessThan:
				case BinaryOperatorType.LessThanOrEqual:
				case BinaryOperatorType.GreaterThan:
				case BinaryOperatorType.GreaterThanOrEqual:
					return ReflectionReturnType.Bool;
				default:
					return MemberLookupHelper.GetCommonType(binaryOperatorExpression.Left.AcceptVisitor(this, data) as IReturnType,
					                                        binaryOperatorExpression.Right.AcceptVisitor(this, data) as IReturnType);
			}
		}
		
		public override object Visit(ParenthesizedExpression parenthesizedExpression, object data)
		{
			return parenthesizedExpression.Expression.AcceptVisitor(this, data);
		}
		
		public override object Visit(InvocationExpression invocationExpression, object data)
		{
			IMethodOrProperty m = GetMethod(invocationExpression);
			if (m == null) {
				// This might also be a delegate invocation:
				// get the delegate's Invoke method
				IReturnType targetType = invocationExpression.TargetObject.AcceptVisitor(this, data) as IReturnType;
				if (targetType != null) {
					IClass c = targetType.GetUnderlyingClass();
					if (c != null && c.ClassType == ClassType.Delegate) {
						// find the delegate's return type
						m = c.Methods.Find(delegate(IMethod innerMethod) { return innerMethod.Name == "Invoke"; });
					}
				}
			}
			if (m != null)
				return m.ReturnType;
			else
				return null;
		}
		
		public override object Visit(IndexerExpression indexerExpression, object data)
		{
			IProperty i = GetIndexer(indexerExpression);
			if (i != null)
				return i.ReturnType;
			else
				return null;
		}
		
		public IMethod FindOverload(List<IMethod> methods, IReturnType[] typeParameters, IList<Expression> arguments, object data)
		{
			if (methods.Count <= 0) {
				return null;
			}
			// We can't use this shortcut because MemberLookupHelper does type inference and
			// type substitution for us
			//if (methods.Count == 1)
			//	return methods[0];
			
			IReturnType[] types = new IReturnType[arguments.Count];
			for (int i = 0; i < types.Length; ++i) {
				types[i] = arguments[i].AcceptVisitor(this, data) as IReturnType;
			}
			return MemberLookupHelper.FindOverload(methods, typeParameters, types);
		}
		
		/*
		/// <summary>
		/// Finds the index of the overload in <paramref name="methods"/> that is the best
		/// match for a call with the specified return types.
		/// </summary>
		/// <param name="methods">ArrayList containing IMethodOrIndexers</param>
		/// <param name="types">Array containing the types of the parameters.</param>
		/// <param name="forceParameterCount">True when the parameter count should exactly be
		/// types.Length; False when more parameters are possible</param>
		/// <param name="singleBestOverload">Returns true when the overload returned is
		/// the only overload that had the highest score or false when there were
		/// multiple overloads with an equal score.</param>
		public static int FindOverload(List<IMethodOrProperty> methods, IReturnType[] types, bool forceParameterCount, out bool singleBestOverload)
		{
			singleBestOverload = true;
			if (methods.Count == 0)
				return -1;
			if (methods.Count == 1)
				return 0;
			
			IMethodOrProperty bestMethod = methods[0];
			int bestIndex = 0;
			int bestScore = ScoreOverload(bestMethod, types, forceParameterCount);
			
			for (int i = 1; i < methods.Count; ++i) {
				IMethodOrProperty method = methods[i];
				int score = ScoreOverload(method, types, forceParameterCount);
				if (score > bestScore) {
					bestScore = score;
					bestMethod = method;
					bestIndex = i;
					singleBestOverload = true;
				} else if (score == bestScore) {
					singleBestOverload = false;
				}
			}
			
			return bestIndex;
		}
		
		
		/// <summary>
		/// Calculates a score how good the specified <paramref name="method"/> matches
		/// the <paramref name="types"/>.
		/// </summary>
		/// <param name="methods">ArrayList containing IMethodOrIndexers</param>
		/// <param name="types">Array containing the types of the parameters.</param>
		/// <param name="forceParameterCount">True when the parameter count should exactly be
		/// types.Length; False when more parameters are possible</param>
		/// <returns>
		/// Integer score. When the parameter count matches, score is between 0 (no types matches)
		/// and types.Length (all types matched).
		/// When there were too many parameters but forceParameterCount was false, score is
		/// between -1 for no matches and types.Length - 1 for all matches.
		/// When the parameter count didn't match, score is -(Difference between parameter counts)
		/// </returns>
		public static int ScoreOverload(IMethodOrProperty method, IReturnType[] types, bool forceParameterCount)
		{
			if (method == null) return -1;
			if (forceParameterCount
			    ? (method.Parameters.Count == types.Length)
			    : (method.Parameters.Count >= types.Length))
			{
				int points = 0;
				for (int i = 0; i < types.Length; ++i) {
					IReturnType type = method.Parameters[i].ReturnType;
					if (type != null && types[i] != null) {
						if (type.Equals(types[i]))
							points += 1;
					}
				}
				if (method.Parameters.Count == types.Length)
					return points;
				else
					return points - 1;
			} else {
				return -Math.Abs(method.Parameters.Count - types.Length);
			}
		}
		 */
		
		/// <summary>
		/// Gets the method called by the InvocationExpression. In Visual Basic, the result
		/// can also be an Indexer.
		/// </summary>
		public IMethodOrProperty GetMethod(InvocationExpression invocationExpression)
		{
			IReturnType[] typeParameters = CreateReturnTypes(invocationExpression.TypeArguments);
			if (invocationExpression.TargetObject is FieldReferenceExpression) {
				FieldReferenceExpression field = (FieldReferenceExpression)invocationExpression.TargetObject;
				IReturnType type = field.TargetObject.AcceptVisitor(this, null) as IReturnType;
				List<IMethod> methods = resolver.SearchMethod(type, field.FieldName);
				if (methods.Count == 0 && resolver.Language == SupportedLanguage.VBNet)
					return GetVisualBasicIndexer(invocationExpression);
				return FindOverload(methods, typeParameters, invocationExpression.Arguments, null);
			} else if (invocationExpression.TargetObject is IdentifierExpression) {
				string id = ((IdentifierExpression)invocationExpression.TargetObject).Identifier;
				if (resolver.CallingClass == null) {
					return null;
				}
				List<IMethod> methods = resolver.SearchMethod(id);
				if (methods.Count == 0 && resolver.Language == SupportedLanguage.VBNet)
					return GetVisualBasicIndexer(invocationExpression);
				return FindOverload(methods, typeParameters, invocationExpression.Arguments, null);
			}
			return null;
		}
		
		IProperty GetVisualBasicIndexer(InvocationExpression invocationExpression)
		{
			return GetIndexer(new IndexerExpression(invocationExpression.TargetObject, invocationExpression.Arguments));
		}
		
		public IProperty GetIndexer(IndexerExpression indexerExpression)
		{
			IReturnType type = (IReturnType)indexerExpression.TargetObject.AcceptVisitor(this, null);
			if (type == null) {
				return null;
			}
			List<IProperty> indexers = type.GetProperties();
			// remove non-indexers:
			for (int i = 0; i < indexers.Count; i++) {
				if (!indexers[i].IsIndexer)
					indexers.RemoveAt(i--);
			}
			IReturnType[] parameters = new IReturnType[indexerExpression.Indices.Count];
			for (int i = 0; i < parameters.Length; i++) {
				Expression expr = indexerExpression.Indices[i] as Expression;
				if (expr != null)
					parameters[i] = (IReturnType)expr.AcceptVisitor(this, null);
			}
			return MemberLookupHelper.FindOverload(indexers.ToArray(), parameters);
		}
		
		public override object Visit(FieldReferenceExpression fieldReferenceExpression, object data)
		{
			if (fieldReferenceExpression == null) {
				return null;
			}
			// int. generates a FieldreferenceExpression with TargetObject TypeReferenceExpression and no FieldName
			if (fieldReferenceExpression.FieldName == null || fieldReferenceExpression.FieldName == "") {
				if (fieldReferenceExpression.TargetObject is TypeReferenceExpression) {
					return CreateReturnType(((TypeReferenceExpression)fieldReferenceExpression.TargetObject).TypeReference);
				}
			}
			IReturnType returnType = fieldReferenceExpression.TargetObject.AcceptVisitor(this, data) as IReturnType;
			if (returnType != null) {
				if (returnType is NamespaceReturnType) {
					string name = returnType.FullyQualifiedName;
					string combinedName;
					if (name.Length == 0)
						combinedName = fieldReferenceExpression.FieldName;
					else
						combinedName = name + "." + fieldReferenceExpression.FieldName;
					if (resolver.ProjectContent.NamespaceExists(combinedName)) {
						return new NamespaceReturnType(combinedName);
					}
					IClass c = resolver.GetClass(combinedName);
					if (c != null) {
						return c.DefaultReturnType;
					}
					if (resolver.LanguageProperties.ImportModules) {
						// go through the members of the modules
						foreach (object o in resolver.ProjectContent.GetNamespaceContents(name)) {
							IMember member = o as IMember;
							if (member != null && resolver.IsSameName(member.Name, fieldReferenceExpression.FieldName))
								return member.ReturnType;
						}
					}
					return null;
				}
				return resolver.SearchMember(returnType, fieldReferenceExpression.FieldName);
			}
			return null;
		}
		

⌨️ 快捷键说明

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