.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

751 lines
29 KiB

// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Linq;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors;
namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
{
/// <summary>
/// Resolves expressions.
/// </summary>
sealed class ResolveVisitor : AbstractAstVisitor
{
NRefactoryResolver resolver;
public ResolveVisitor(NRefactoryResolver resolver)
{
this.resolver = resolver;
}
ResolveResult CreateResolveResult(TypeReference reference)
{
return CreateResolveResult(TypeVisitor.CreateReturnType(reference, resolver));
}
ResolveResult CreateResolveResult(Expression expression)
{
return CreateResolveResult(ResolveType(expression));
}
ResolveResult CreateResolveResult(IReturnType resolvedType)
{
if (resolvedType == null)
return null;
else
return new ResolveResult(resolver.CallingClass, resolver.CallingMember, resolvedType);
}
TypeResolveResult CreateTypeResolveResult(IReturnType resolvedType)
{
if (resolvedType == null) {
return null;
} else {
IReturnType rt = resolvedType;
while (rt != null && rt.IsArrayReturnType) {
rt = rt.CastToArrayReturnType().ArrayElementType;
}
IClass resolvedClass = rt != null ? rt.GetUnderlyingClass() : null;
return new TypeResolveResult(resolver.CallingClass, resolver.CallingMember, resolvedType, resolvedClass);
}
}
MemberResolveResult CreateMemberResolveResult(IMember member)
{
if (member == null)
return null;
else
return new MemberResolveResult(resolver.CallingClass, resolver.CallingMember, member);
}
readonly Dictionary<Expression, ResolveResult> cachedResults = new Dictionary<Expression, ResolveResult>();
public ResolveResult Resolve(Expression expression)
{
ResolveResult rr;
if (!cachedResults.TryGetValue(expression, out rr)) {
rr = (ResolveResult)expression.AcceptVisitor(this, null);
if (rr != null)
rr.Freeze();
cachedResults[expression] = rr;
}
return rr;
}
public IReturnType ResolveType(Expression expression)
{
ResolveResult rr = Resolve(expression);
if (rr != null)
return rr.ResolvedType;
else
return null;
}
public override object VisitAddressOfExpression(AddressOfExpression addressOfExpression, object data)
{
bool oldValue = resolver.allowMethodGroupResolveResult;
resolver.allowMethodGroupResolveResult = true;
object result = base.VisitAddressOfExpression(addressOfExpression, data);
resolver.allowMethodGroupResolveResult = oldValue;
return result;
}
public override object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data)
{
return CreateResolveResult(new LambdaReturnType(anonymousMethodExpression, resolver));
}
public override object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data)
{
if (arrayCreateExpression.IsImplicitlyTyped) {
return CreateResolveResult(arrayCreateExpression.ArrayInitializer);
} else {
return CreateTypeResolveResult(TypeVisitor.CreateReturnType(arrayCreateExpression.CreateType, resolver));
}
}
public override object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data)
{
return CreateResolveResult(assignmentExpression.Left);
}
public override object VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data)
{
if (resolver.CallingClass == null) {
return null;
}
if (resolver.Language == SupportedLanguage.VBNet && IsInstanceConstructor(resolver.CallingMember)) {
return new VBBaseOrThisReferenceInConstructorResolveResult(
resolver.CallingClass, resolver.CallingMember, resolver.CallingClass.BaseType);
} else {
return new BaseResolveResult(resolver.CallingClass, resolver.CallingMember, resolver.CallingClass.BaseType);
}
}
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data)
{
switch (binaryOperatorExpression.Op) {
case BinaryOperatorType.NullCoalescing:
return CreateResolveResult(binaryOperatorExpression.Right);
case BinaryOperatorType.DivideInteger:
return CreateResolveResult(resolver.ProjectContent.SystemTypes.Int32);
case BinaryOperatorType.Concat:
return CreateResolveResult(resolver.ProjectContent.SystemTypes.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 CreateResolveResult(resolver.ProjectContent.SystemTypes.Boolean);
default:
return CreateResolveResult(MemberLookupHelper.GetCommonType(
resolver.ProjectContent,
ResolveType(binaryOperatorExpression.Left),
ResolveType(binaryOperatorExpression.Right)));
}
}
public override object VisitCastExpression(CastExpression castExpression, object data)
{
return CreateResolveResult(castExpression.CastTo);
}
public override object VisitCheckedExpression(CheckedExpression checkedExpression, object data)
{
return CreateResolveResult(checkedExpression.Expression);
}
public override object VisitClassReferenceExpression(ClassReferenceExpression classReferenceExpression, object data)
{
if (resolver.CallingClass != null)
return CreateResolveResult(resolver.CallingClass.DefaultReturnType);
else
return null;
}
public override object VisitCollectionInitializerExpression(CollectionInitializerExpression collectionInitializerExpression, object data)
{
// used for implicitly typed arrays
if (collectionInitializerExpression.CreateExpressions.Count == 0)
return null;
IReturnType combinedRT = ResolveType(collectionInitializerExpression.CreateExpressions[0]);
for (int i = 1; i < collectionInitializerExpression.CreateExpressions.Count; i++) {
IReturnType rt = ResolveType(collectionInitializerExpression.CreateExpressions[i]);
combinedRT = MemberLookupHelper.GetCommonType(resolver.ProjectContent, combinedRT, rt);
}
if (combinedRT == null)
return null;
return CreateResolveResult(new ArrayReturnType(resolver.ProjectContent, combinedRT, 1));
}
public override object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data)
{
return CreateResolveResult(MemberLookupHelper.GetCommonType(
resolver.ProjectContent,
ResolveType(conditionalExpression.TrueExpression),
ResolveType(conditionalExpression.FalseExpression)));
}
public override object VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data)
{
return null;
}
public override object VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data)
{
return CreateResolveResult(defaultValueExpression.TypeReference);
}
public override object VisitDirectionExpression(DirectionExpression directionExpression, object data)
{
return CreateResolveResult(new ReferenceReturnType(ResolveType(directionExpression.Expression)));
}
public override object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data)
{
return resolver.ResolveIdentifier(identifierExpression, ExpressionContext.Default);
}
public override object VisitIndexerExpression(IndexerExpression indexerExpression, object data)
{
IReturnType target = ResolveType(indexerExpression.TargetObject);
return CreateMemberResolveResult(
GetIndexer(target, indexerExpression.Indexes)
);
}
IProperty GetIndexer(IReturnType target, List<Expression> indexes)
{
if (target == null)
return null;
return MemberLookupHelper.FindOverload(
target.GetProperties().Where((IProperty p) => p.IsIndexer).ToList(),
indexes.Select<Expression, IReturnType>(ResolveType).ToArray()
);
}
IProperty GetVisualBasicIndexer(InvocationExpression invocationExpression)
{
ResolveResult targetRR = Resolve(invocationExpression.TargetObject);
if (targetRR != null) {
// Visual Basic can call indexers in two ways:
// collection(index) - use indexer
// collection.Item(index) - use parametrized property
if (invocationExpression.TargetObject is IdentifierExpression || invocationExpression.TargetObject is MemberReferenceExpression) {
// only IdentifierExpression/MemberReferenceExpression can represent a parametrized property
// - the check is necessary because collection.Items and collection.Item(index) both
// resolve to the same property, but we want to use the default indexer for the second call in
// collection.Item(index1)(index2)
MemberResolveResult memberRR = targetRR as MemberResolveResult;
if (memberRR != null) {
IProperty p = memberRR.ResolvedMember as IProperty;
if (p != null && p.Parameters.Count > 0) {
// this is a parametrized property
return p;
}
}
}
// not a parametrized property - try normal indexer
return GetIndexer(targetRR.ResolvedType, invocationExpression.Arguments);
} else {
return null;
}
}
public override object VisitInvocationExpression(InvocationExpression invocationExpression, object data)
{
if (resolver.Language == SupportedLanguage.CSharp && resolver.CallingClass != null) {
if (invocationExpression.TargetObject is ThisReferenceExpression) {
// call to constructor
return ResolveConstructorOverload(resolver.CallingClass, invocationExpression.Arguments);
} else if (invocationExpression.TargetObject is BaseReferenceExpression) {
return ResolveConstructorOverload(resolver.CallingClass.BaseType, invocationExpression.Arguments);
}
}
ResolveResult rr = Resolve(invocationExpression.TargetObject);
MixedResolveResult mixedRR = rr as MixedResolveResult;
if (mixedRR != null) {
rr = mixedRR.PrimaryResult;
}
MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult;
if (mgrr != null) {
if (resolver.Language == SupportedLanguage.VBNet) {
if (mgrr.Methods.All(mg => mg.Count == 0))
return CreateMemberResolveResult(GetVisualBasicIndexer(invocationExpression));
// IMethod empty = mgrr.GetMethodWithEmptyParameterList();
// if (empty != null)
// return CreateMemberResolveResult(empty);
}
IReturnType[] argumentTypes = invocationExpression.Arguments.Select<Expression, IReturnType>(ResolveType).ToArray();
MemberResolveResult firstResult = null;
foreach (MethodGroup methodGroup in mgrr.Methods) {
bool resultIsAcceptable;
IMethod method;
if (methodGroup.IsExtensionMethodGroup) {
IReturnType[] extendedTypes = new IReturnType[argumentTypes.Length + 1];
extendedTypes[0] = mgrr.ContainingType;
argumentTypes.CopyTo(extendedTypes, 1);
method = MemberLookupHelper.FindOverload(methodGroup, extendedTypes, out resultIsAcceptable);
} else {
method = MemberLookupHelper.FindOverload(methodGroup, argumentTypes, out resultIsAcceptable);
}
MemberResolveResult result = CreateMemberResolveResult(method);
if (result != null && methodGroup.IsExtensionMethodGroup)
result.IsExtensionMethodCall = true;
if (resultIsAcceptable)
return result;
if (firstResult == null)
firstResult = result;
}
if (firstResult != null) {
return firstResult;
} else {
return FallbackResolveMethod(invocationExpression, mgrr, argumentTypes);
}
} else if (rr != null && rr.ResolvedType != null) {
IClass c = rr.ResolvedType.GetUnderlyingClass();
if (c != null && c.ClassType == ClassType.Delegate) {
// 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
IMethod method = rr.ResolvedType.GetMethods().FirstOrDefault(innerMethod => innerMethod.Name == "Invoke");
if (method != null) {
return new DelegateCallResolveResult(rr, method);
}
}
}
if (resolver.Language == SupportedLanguage.VBNet) {
return CreateMemberResolveResult(GetVisualBasicIndexer(invocationExpression));
}
return resolver.CreateUnknownMethodResolveResult(invocationExpression);
}
ResolveResult FallbackResolveMethod(InvocationExpression invocation, MethodGroupResolveResult mgrr, IReturnType[] argumentTypes)
{
// method not found, let's try if we can find a method if we violate the
// accessibility rules
MemberReferenceExpression mre = invocation.TargetObject as MemberReferenceExpression;
if (mre != null) {
List<IMethod> methods = mgrr.ContainingType.GetMethods().Where(m => resolver.IsSameName(m.Name, mre.MemberName)).ToList();
bool resultIsAcceptable;
IMethod result = MemberLookupHelper.FindOverload(
methods, argumentTypes, out resultIsAcceptable);
if (result != null) {
return CreateMemberResolveResult(result);
}
}
return resolver.CreateUnknownMethodResolveResult(invocation);
}
public override object VisitLambdaExpression(LambdaExpression lambdaExpression, object data)
{
return CreateResolveResult(new LambdaReturnType(lambdaExpression, resolver));
}
public override object VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data)
{
IReturnType type;
if (string.IsNullOrEmpty(memberReferenceExpression.MemberName)) {
// NRefactory creates this "dummy" fieldReferenceExpression when it should
// parse a primitive type name (int, short; Integer, Decimal)
if (memberReferenceExpression.TargetObject is TypeReferenceExpression) {
type = TypeVisitor.CreateReturnType(((TypeReferenceExpression)memberReferenceExpression.TargetObject).TypeReference, resolver);
return CreateTypeResolveResult(type);
}
}
ResolveResult targetRR = Resolve(memberReferenceExpression.TargetObject);
if (targetRR == null)
return null;
type = GetType(targetRR);
if (targetRR is NamespaceResolveResult) {
return ResolveMemberInNamespace(((NamespaceResolveResult)targetRR).Name, memberReferenceExpression);
} else if (type != null) {
TypeResolveResult typeRR = targetRR as TypeResolveResult;
if (typeRR != null && typeRR.ResolvedClass != null) {
foreach (IClass c1 in typeRR.ResolvedClass.ClassInheritanceTree) {
foreach (IClass c in c1.InnerClasses) {
if (resolver.IsSameName(memberReferenceExpression.MemberName, c.Name)
&& c.TypeParameters.Count == memberReferenceExpression.TypeArguments.Count)
{
return CreateTypeResolveResult(resolver.ConstructType(c.DefaultReturnType, memberReferenceExpression.TypeArguments));
}
}
}
}
var memberRR = resolver.ResolveMember(type, memberReferenceExpression.MemberName,
memberReferenceExpression.TypeArguments,
NRefactoryResolver.IsInvoked(memberReferenceExpression),
typeRR == null, // allow extension methods only for non-static method calls
targetRR is BaseResolveResult ? (bool?)true : null // allow calling protected members using "base."
);
// MethodGroupResolveResult mgRR = memberRR as MethodGroupResolveResult;
//
// if (mgRR == null)
// mgRR = targetRR as MethodGroupResolveResult;
//
// if (mgRR != null && !resolver.allowMethodGroupResolveResult)
// return CreateMemberResolveResult(mgRR.GetMethodWithEmptyParameterList());
return memberRR;
}
return null;
}
IReturnType GetType(ResolveResult targetRR)
{
if (targetRR.ResolvedType != null)
return targetRR.ResolvedType;
if (targetRR is MixedResolveResult && ((MixedResolveResult)targetRR).TypeResult != null)
return ((MixedResolveResult)targetRR).TypeResult.ResolvedType;
return null;
}
ResolveResult ResolveMemberInNamespace(string namespaceName, MemberReferenceExpression mre)
{
string combinedName;
if (string.IsNullOrEmpty(namespaceName))
combinedName = mre.MemberName;
else
combinedName = namespaceName + "." + mre.MemberName;
if (resolver.ProjectContent.NamespaceExists(combinedName)) {
return new NamespaceResolveResult(resolver.CallingClass, resolver.CallingMember, combinedName);
}
IClass c = resolver.GetClass(combinedName, mre.TypeArguments.Count);
if (c != null) {
return CreateTypeResolveResult(resolver.ConstructType(c.DefaultReturnType, mre.TypeArguments));
}
if (resolver.LanguageProperties.ImportModules) {
// go through the members of the modules
List<IMember> possibleMembers = new List<IMember>();
foreach (object o in resolver.ProjectContent.GetNamespaceContents(namespaceName)) {
IMember member = o as IMember;
if (member != null && resolver.IsSameName(member.Name, mre.MemberName)) {
possibleMembers.Add(member);
}
}
return resolver.CreateMemberOrMethodGroupResolveResult(
null, mre.MemberName, new IList<IMember>[] { possibleMembers }, false, null);
}
return null;
}
public override object VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data)
{
if (objectCreateExpression.IsAnonymousType) {
return CreateResolveResult(CreateAnonymousTypeClass(objectCreateExpression.ObjectInitializer).DefaultReturnType);
} else {
IReturnType rt = TypeVisitor.CreateReturnType(objectCreateExpression.CreateType, resolver);
if (rt == null)
return new UnknownConstructorCallResolveResult(resolver.CallingClass, resolver.CallingMember, objectCreateExpression.CreateType.ToString());
return ResolveConstructorOverload(rt, objectCreateExpression.Parameters)
?? CreateResolveResult(rt);
}
}
internal ResolveResult ResolveConstructorOverload(IReturnType rt, List<Expression> arguments)
{
if (rt == null)
return null;
List<IMethod> methods = rt.GetMethods().Where(m => m.IsConstructor && !m.IsStatic).ToList();
IReturnType[] argumentTypes = arguments.Select<Expression, IReturnType>(ResolveType).ToArray();
bool resultIsAcceptable;
IMethod result = MemberLookupHelper.FindOverload(methods, argumentTypes, out resultIsAcceptable);
ResolveResult rr = CreateMemberResolveResult(result);
if (rr != null)
rr.ResolvedType = rt;
return rr;
}
internal ResolveResult ResolveConstructorOverload(IClass c, List<Expression> arguments)
{
if (c == null)
return null;
else
return ResolveConstructorOverload(c.DefaultReturnType, arguments);
}
DefaultClass CreateAnonymousTypeClass(CollectionInitializerExpression initializer)
{
List<IReturnType> fieldTypes = new List<IReturnType>();
List<string> fieldNames = new List<string>();
foreach (Expression expr in initializer.CreateExpressions) {
if (expr is NamedArgumentExpression) {
// use right part only
fieldTypes.Add( ResolveType(((NamedArgumentExpression)expr).Expression) );
} else {
fieldTypes.Add( ResolveType(expr) );
}
fieldNames.Add(GetAnonymousTypeFieldName(expr));
}
StringBuilder nameBuilder = new StringBuilder();
nameBuilder.Append('{');
for (int i = 0; i < fieldTypes.Count; i++) {
if (i > 0) nameBuilder.Append(", ");
nameBuilder.Append(fieldNames[i]);
nameBuilder.Append(" : ");
if (fieldTypes[i] != null) {
nameBuilder.Append(fieldTypes[i].DotNetName);
}
}
nameBuilder.Append('}');
DefaultClass c = new DefaultClass(new DefaultCompilationUnit(resolver.ProjectContent), nameBuilder.ToString());
c.Modifiers = ModifierEnum.Internal | ModifierEnum.Synthetic | ModifierEnum.Sealed;
for (int i = 0; i < fieldTypes.Count; i++) {
DefaultProperty p = new DefaultProperty(fieldNames[i], fieldTypes[i], ModifierEnum.Public | ModifierEnum.Synthetic, DomRegion.Empty, DomRegion.Empty, c);
p.CanGet = true;
p.CanSet = false;
c.Properties.Add(p);
}
return c;
}
static string GetAnonymousTypeFieldName(Expression expr)
{
if (expr is MemberReferenceExpression) {
return ((MemberReferenceExpression)expr).MemberName;
} else if (expr is NamedArgumentExpression) {
return ((NamedArgumentExpression)expr).Name;
} else if (expr is IdentifierExpression) {
return ((IdentifierExpression)expr).Identifier;
} else {
return "?";
}
}
public override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data)
{
return CreateResolveResult(parenthesizedExpression.Expression);
}
public override object VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data)
{
ResolveResult targetRR = Resolve(pointerReferenceExpression.TargetObject);
if (targetRR == null || targetRR.ResolvedType == null)
return null;
PointerReturnType type = targetRR.ResolvedType.CastToDecoratingReturnType<PointerReturnType>();
if (type != null) {
return resolver.ResolveMember(type.BaseType, pointerReferenceExpression.MemberName,
pointerReferenceExpression.TypeArguments,
NRefactoryResolver.IsInvoked(pointerReferenceExpression),
true, null
);
}
return null;
}
public override object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data)
{
if (primitiveExpression.Value == null) {
return CreateResolveResult(NullReturnType.Instance);
} else if (primitiveExpression.Value is int) {
return new IntegerLiteralResolveResult(resolver.CallingClass, resolver.CallingMember, resolver.ProjectContent.SystemTypes.Int32);
} else {
return CreateResolveResult(resolver.ProjectContent.SystemTypes.CreatePrimitive(primitiveExpression.Value.GetType()));
}
}
public override object VisitQueryExpression(QueryExpression queryExpression, object data)
{
QueryExpressionSelectClause selectClause = queryExpression.SelectOrGroupClause as QueryExpressionSelectClause;
QueryExpressionGroupClause groupClause = queryExpression.SelectOrGroupClause as QueryExpressionGroupClause;
if (selectClause != null) {
// Fake a call to 'Select'
var fakeInvocation = new InvocationExpression(new MemberReferenceExpression(
queryExpression.FromClause.Sources.First().Expression, "Select"));
var selector = new LambdaExpression();
selector.Parameters.Add(new ParameterDeclarationExpression(null, "__rangeVariable"));
selector.ExpressionBody = selectClause.Projection;
selector.Parent = fakeInvocation;
fakeInvocation.Arguments.Add(selector);
return CreateResolveResult(ResolveType(fakeInvocation));
} else if (groupClause != null) {
// Fake a call to 'GroupBy'
var fakeInvocation = new InvocationExpression(new MemberReferenceExpression(
queryExpression.FromClause.Sources.First().Expression, "GroupBy"));
var keySelector = new LambdaExpression();
keySelector.Parameters.Add(new ParameterDeclarationExpression(null, "__rangeVariable"));
keySelector.ExpressionBody = groupClause.GroupBy;
keySelector.Parent = fakeInvocation;
var elementSelector = new LambdaExpression();
elementSelector.Parameters.Add(new ParameterDeclarationExpression(null, "__rangeVariable"));
elementSelector.ExpressionBody = groupClause.Projection;
elementSelector.Parent = fakeInvocation;
fakeInvocation.Arguments.Add(keySelector);
fakeInvocation.Arguments.Add(elementSelector);
return CreateResolveResult(ResolveType(fakeInvocation));
} else {
return null;
}
}
public override object VisitSizeOfExpression(SizeOfExpression sizeOfExpression, object data)
{
return CreateResolveResult(resolver.ProjectContent.SystemTypes.Int32);
}
public override object VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data)
{
return null;
}
public override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data)
{
if (resolver.CallingClass == null)
return null;
if (resolver.Language == SupportedLanguage.VBNet && IsInstanceConstructor(resolver.CallingMember)) {
return new VBBaseOrThisReferenceInConstructorResolveResult(
resolver.CallingClass, resolver.CallingMember, resolver.CallingClass.DefaultReturnType);
} else {
return CreateResolveResult(resolver.CallingClass.DefaultReturnType);
}
}
static bool IsInstanceConstructor(IMember member)
{
IMethod m = member as IMethod;
return m != null && m.IsConstructor && !m.IsStatic;
}
public override object VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data)
{
return CreateResolveResult(resolver.ProjectContent.SystemTypes.Type);
}
public override object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data)
{
return CreateResolveResult(resolver.ProjectContent.SystemTypes.Boolean);
}
public override object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data)
{
TypeReference reference = typeReferenceExpression.TypeReference;
ResolveResult rr = CreateTypeResolveResult(TypeVisitor.CreateReturnType(reference, resolver));
if (rr == null && reference.GenericTypes.Count == 0 && !reference.IsArrayType) {
// reference to namespace is possible
if (reference.IsGlobal) {
if (resolver.ProjectContent.NamespaceExists(reference.Type))
return new NamespaceResolveResult(resolver.CallingClass, resolver.CallingMember, reference.Type);
} else {
string name = resolver.SearchNamespace(reference.Type, typeReferenceExpression.StartLocation);
if (name != null)
return new NamespaceResolveResult(resolver.CallingClass, resolver.CallingMember, name);
}
}
if (rr != null) {
return rr;
} else {
return new UnknownIdentifierResolveResult(resolver.CallingClass, resolver.CallingMember, reference.Type);
}
}
public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
{
IReturnType type = ResolveType(unaryOperatorExpression.Expression);
if (type == null)
return null;
switch (unaryOperatorExpression.Op) {
case UnaryOperatorType.AddressOf:
return CreateResolveResult(new PointerReturnType(type));
case UnaryOperatorType.Dereference:
PointerReturnType prt = type.CastToDecoratingReturnType<PointerReturnType>();
if (prt != null) {
return CreateResolveResult(prt.BaseType);
} else {
return null;
}
default:
return CreateResolveResult(type);
}
}
public override object VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data)
{
return CreateResolveResult(uncheckedExpression.Expression);
}
#region XML Literal resolver
public override object VisitXmlContentExpression(XmlContentExpression xmlContentExpression, object data)
{
switch (xmlContentExpression.Type) {
case XmlContentType.Comment:
return CreateResolveResult(new TypeReference("System.Xml.Linq.XComment"));
case XmlContentType.Text:
return CreateResolveResult(new TypeReference("System.Xml.Linq.XText"));
case XmlContentType.CData:
return CreateResolveResult(new TypeReference("System.Xml.Linq.XCData"));
case XmlContentType.ProcessingInstruction:
if (xmlContentExpression.Content.StartsWith("xml ", StringComparison.OrdinalIgnoreCase))
return CreateResolveResult(new TypeReference("System.Xml.Linq.XDocumentType"));
return CreateResolveResult(new TypeReference("System.Xml.Linq.XProcessingInstruction"));
default:
throw new Exception("Invalid value for XmlContentType");
}
}
public override object VisitXmlDocumentExpression(XmlDocumentExpression xmlDocumentExpression, object data)
{
return CreateResolveResult(new TypeReference("System.Xml.Linq.XDocument"));
}
public override object VisitXmlElementExpression(XmlElementExpression xmlElementExpression, object data)
{
return CreateResolveResult(new TypeReference("System.Xml.Linq.XElement"));
}
public override object VisitXmlMemberAccessExpression(XmlMemberAccessExpression xmlMemberAccessExpression, object data)
{
switch (xmlMemberAccessExpression.AxisType) {
case XmlAxisType.Element:
case XmlAxisType.Descendents:
return CreateResolveResult(
new TypeReference("System.Collections.Generic.IEnumerable",
new List<TypeReference> { new TypeReference("System.Xml.Linq.XElement") { IsGlobal = true } }
) { IsGlobal = true }
);
case XmlAxisType.Attribute:
return CreateResolveResult(new TypeReference("System.String", true) { IsGlobal = true });
default:
throw new Exception("Invalid value for XmlAxisType");
}
}
#endregion
}
}