CodeAssemblyTypeManager.cs :  » Development » devAdvantage » AnticipatingMinds » Genesis » CodeDOM » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Development » devAdvantage 
devAdvantage » AnticipatingMinds » Genesis » CodeDOM » CodeAssemblyTypeManager.cs
using System;
using System.Reflection;
using System.Threading;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using AnticipatingMinds.Genesis.AspNetDom;

namespace AnticipatingMinds.Genesis.CodeDOM{
  /// <exclude/>
  public class CodeAssemblyTypeManager
  {
    internal CodeAssemblyTypeManager(CodeAssembly codeAssembly)
    {
      this.codeAssembly = codeAssembly;
    }

    /// <summary>
    /// Loads all the types imported or exported by assembly.
    /// </summary>
    private void BuildAssemblyTypeSystem(ManualResetEvent cancelEvent)
    {
      caseSensitiveAssebmlyTypes.Clear();
      foreach(CodeTypeInfo typeInfo in CodeTypeManagerHelper.GetAssemblyDeclaredTypes(codeAssembly,true))
      {
        if(!caseSensitiveAssebmlyTypes.Contains(typeInfo.FullName))
          caseSensitiveAssebmlyTypes[typeInfo.FullName] = typeInfo;

        if(!caseInsensitiveAssebmlyTypes.Contains(typeInfo.FullName))
          caseInsensitiveAssebmlyTypes[typeInfo.FullName] = typeInfo;
      }

      foreach(string assemblyReference in codeAssembly.ReferencedAssemblies)
      {
        if(cancelEvent!= null && cancelEvent.WaitOne(0,false))
          return;

        if(assemblyReference == null || assemblyReference.Length == 0)
          continue;

        string assemblyFileName = Path.GetFileName(assemblyReference);
        if(codeAssembly.Solution != null && codeAssembly.Solution.GetCodeAssembly(assemblyFileName) != null)
        {
          foreach(CodeTypeInfo typeInfo in CodeTypeManagerHelper.GetAssemblyDeclaredTypes(codeAssembly.Solution.GetCodeAssembly(assemblyFileName),false))
          {
            if(!caseSensitiveAssebmlyTypes.Contains(typeInfo.FullName))
              caseSensitiveAssebmlyTypes[typeInfo.FullName] = typeInfo;

            if(!caseInsensitiveAssebmlyTypes.Contains(typeInfo.FullName))
              caseInsensitiveAssebmlyTypes[typeInfo.FullName] = typeInfo;
          }
        }
        else
        {
          foreach(CodeTypeInfo typeInfo in CodeTypeManagerHelper.GetAssemblyDeclaredTypes(assemblyReference))
          {
            if(!caseSensitiveAssebmlyTypes.Contains(typeInfo.FullName))
              caseSensitiveAssebmlyTypes[typeInfo.FullName] = typeInfo;

            if(!caseInsensitiveAssebmlyTypes.Contains(typeInfo.FullName))
              caseInsensitiveAssebmlyTypes[typeInfo.FullName] = typeInfo;
          }
        }
      }
      
    }

    /// <summary>
    /// Finds type defined by its full name passed in <paramref name="typeName"/>.
    /// </summary>
    /// <param name="typeName">Full name of the type to look for.</param>
    /// <returns>Returns type information if found - null otherwise.</returns>
    public CodeTypeInfo FindType(string typeName)
    {
      return FindType(typeName,true);
    }
    
    public CodeTypeInfo FindType(string typeName,bool isCaseSensitive)
    {
      IDictionary typesDictionary = null;
      if(isCaseSensitive)
      {
        typesDictionary = caseSensitiveAssebmlyTypes;
      }
      else
      {
        typesDictionary = caseInsensitiveAssebmlyTypes;
      }

      CodeTypeInfo typeInfo = typesDictionary[typeName] as CodeTypeInfo;
      if(typeInfo != null)
        return typeInfo;

      if(typeName.LastIndexOf('[') == -1)
        return null;

      string baseTypeName = typeName.Substring(0,typeName.LastIndexOf('['));
      typeInfo = FindType(baseTypeName);
      if(typeInfo != null)
      {
        CodeTypeInfo arrayTypeInfo = typeInfo.GetArrayType();
        typesDictionary[typeName] = arrayTypeInfo;
        return arrayTypeInfo;
      }

      return null;
    }

    /// <summary>
    /// Finds a field specified by <paramref name="typeName"/> type.
    /// </summary>
    /// <param name="typeName">Full name of type that contains an field.</param>
    /// <param name="fieldName">Name of the field.</param>
    /// <param name="isStatic">True if filed shall be defined as static.</param>
    /// <returns>Returns pointer to the field information if found - null otherwise.</returns>
    public CodeFieldInfo FindField(string typeName, string fieldName,bool isStatic)
    {
      return FindField(typeName, fieldName,isStatic,true);
    }
    public CodeFieldInfo FindField(string typeName, string fieldName,bool isStatic,bool isCaseSensitive)
    {
      CodeTypeInfo typeInfo = FindType(typeName,isCaseSensitive);
      while(typeInfo != null)
      {
        CodeFieldInfo fieldInfo  = typeInfo.FindField(fieldName,isCaseSensitive);
        if(fieldInfo != null)
        {
          if((fieldInfo.IsStatic || fieldInfo.IsConst)&& isStatic)
            return fieldInfo;

          if((fieldInfo.IsStatic  || fieldInfo.IsConst) && !isStatic)
            return fieldInfo;

          if(!(fieldInfo.IsStatic  || fieldInfo.IsConst) && !isStatic)
            return fieldInfo;
        }
        if(typeInfo.GetBaseType() == null)
          return null;

        typeInfo = FindType(typeInfo.GetBaseType());
      }

      return null;
    }

    /// <summary>
    /// Finds an event specified by <paramref name="typeName"/> type.
    /// </summary>
    /// <param name="typeName">Full name of type that contains an event.</param>
    /// <param name="eventName">Name of the event.</param>
    /// <param name="isStatic">True if event shall be defined as static.</param>
    /// <returns>Returns pointer to the event information if found - null otherwise.</returns>
    public CodeEventInfo FindEvent(string typeName, string eventName,bool isStatic)
    {
      return FindEvent(typeName, eventName,isStatic,true);
    }
    public CodeEventInfo FindEvent(string typeName, string eventName,bool isStatic,bool isCaseSensitive)
    {
      CodeTypeInfo typeInfo = FindType(typeName,isCaseSensitive);
      while(typeInfo != null)
      {
        CodeEventInfo eventInfo = typeInfo.FindEvent(eventName,isCaseSensitive);
        if(eventInfo != null)
        {
          //Event static information is missing from metadata 
          //cannot check static requirement!
//          if(eventInfo.IsStatic && isStatic)
//            return eventInfo;
//
//          if(eventInfo.IsStatic && !isStatic)
//            return eventInfo;
//
//          if(!eventInfo.IsStatic && !isStatic)
//            return eventInfo;

          return eventInfo;
        }

        if(typeInfo.GetBaseType() == null)
          return null;

        typeInfo = FindType(typeInfo.GetBaseType());
      }

      return null;
    }

    /// <summary>
    /// Finds a property specified by <paramref name="typeName"/> type.
    /// </summary>
    /// <param name="typeName">Full name of type that contains the property.</param>
    /// <param name="propertyName">Name of the property.</param>
    /// <param name="isStatic">True if property shall be defined as static.</param>
    /// <returns>Returns pointer to the property information if found - null otherwise.</returns>
    public CodePropertyInfo FindProperty(string typeName, string propertyName,bool isStatic)
    {
      return FindProperty(typeName, propertyName,isStatic,true);
    }
    public CodePropertyInfo FindProperty(string typeName, string propertyName,bool isStatic,bool isCaseSensitive)
    {
      CodeTypeInfo typeInfo = FindType(typeName,isCaseSensitive);
      while(typeInfo != null)
      {
        CodePropertyInfo propertyInfo = typeInfo.FindProperty(propertyName,isCaseSensitive);
        if(propertyInfo != null)
        {
          if(propertyInfo.IsStatic && isStatic)
            return propertyInfo;

          if(propertyInfo.IsStatic && !isStatic)
            return propertyInfo;

          if(!propertyInfo.IsStatic && !isStatic)
            return propertyInfo;
        }

        if(typeInfo.GetBaseType() == null)
          return null;

        typeInfo = FindType(typeInfo.GetBaseType());
      }

      return null;
    }

    /// <summary>
    /// Determines whether the type <paramref name="typeName"/> derives from the type specified by <paramref name="derivedTypeName"/>.
    /// </summary>
    /// <param name="typeName">Tested type name.</param>
    /// <param name="baseTypeName">Targeted base class typename.</param>
    /// <returns>True is typeName derives from derivedTypeName.</returns>
    public bool IsTypeSubclassOf(string typeName, string baseTypeName)
    {
      CodeTypeInfo currentTypeInfo = FindType(typeName);
      while(currentTypeInfo != null)
      {
        if(string.Compare(currentTypeInfo.FullName,baseTypeName) == 0)
          return true;

        if(currentTypeInfo.GetBaseType() == null)
          return false;
        
        currentTypeInfo = FindType(currentTypeInfo.GetBaseType());
      }

      return false;
    }

    /// <summary>
    /// Determines if type <paramref name="typeName"/> implements interface <paramref name="interfaceName"/>.
    /// </summary>
    /// <param name="typeName">Name of the type to test.</param>
    /// <param name="interfaceName">Name of the interface to test for.</param>
    /// <returns>True if type implements specified interface.</returns>
    public bool DoesTypeImplementInterface(string typeName, string interfaceName)
    {
      CodeTypeInfo currentTypeInfo = FindType(typeName);
      while(currentTypeInfo != null)
      {
        foreach(string implementedInterfaceName in currentTypeInfo.GetInterfaces())
        {
          if(string.Compare(implementedInterfaceName,interfaceName) == 0)
            return true;
        }

        if(currentTypeInfo.GetBaseType() == null)
          return false;
        
        currentTypeInfo = FindType(currentTypeInfo.GetBaseType());
      }

      return false;
    }


    /// <summary>
    /// Checks if the implicit conversion exists between two types.
    /// </summary>
    /// <param name="typeNameFrom">Full name of the source type.</param>
    /// <param name="typeNameTo">Full name of the target type.</param>
    /// <returns>True if there is an explicit conversion defined by compiler or type specified by <paramref name="typeNameFrom"/> 
    /// to the type specified by <paramref name="typeNameTo"/>
    /// </returns>
    public bool DoesImplicitConversionExist(string typeNameFrom,string typeNameTo)
    {
      if(typeNameFrom == null || typeNameFrom.Length == 0 || typeNameTo == null || typeNameTo.Length == 0)
        return false;

//      if(typeNameFrom == "System.Decimal" && typeNameTo == "System.String")
//        Debugger.Break();

      if(string.Compare(typeNameFrom,typeNameTo) == 0)
        return true;

      //Allow conversion from null value to any reference type
      if(CodeTypeInfo.GetNullTypeInfo().FullName == typeNameFrom && !IsTypeSubclassOf(typeNameTo,"System.ValueType"))
        return true;

      //6.1.4 Implicit reference conversions
      #region 6.1.4 Implicit reference conversions
      if(IsTypeSubclassOf(typeNameFrom,typeNameTo))
        return true;

      CodeTypeInfo typeTo = FindType(typeNameTo);
      if(typeTo == null)
        return false;

      if(typeTo.IsInterface)
      {
        if(DoesTypeImplementInterface(typeNameFrom,typeNameTo))
          return true;
      }
      #endregion 
      //6.1.2 Implicit numeric conversions
      #region 6.1.2 Implicit numeric conversions
      switch(typeNameFrom)
      {
        case "System.SByte": //sbyte
          switch(typeNameTo)
          {
            case "System.Int16": //sbyte->short
              return true;
            case "System.Int32": //sbyte->int
              return true;
            case "System.Int64": //sbyte->long
              return true;
            case "System.Single": //sbyte->float
              return true;
            case "System.Double": //sbyte->double
              return true;
            case "System.Decimal": //sbyte->decimal
              return true;
          }
          break;
        case "System.Byte": //byte
          switch(typeNameTo)
          {
            case "System.Int16": //byte->short
              return true;
            case "System.UInt16": //byte->ushort
              return true;
            case "System.Int32": //byte->int
              return true;
            case "System.UInt32": //byte->uint
              return true;
            case "System.Int64": //byte->long
              return true;
            case "System.UInt64": //byte->ulong
              return true;
            case "System.Single": //byte->float
              return true;
            case "System.Double": //byte->double
              return true;
            case "System.Decimal": //byte->decimal
              return true;
          }
          break;
        case "System.Int16": //short
          switch(typeNameTo)
          {
            case "System.Int32": //short->int
              return true;
            case "System.Int64": //short->long
              return true;
            case "System.Single": //short->float
              return true;
            case "System.Double": //short->double
              return true;
            case "System.Decimal": //short->decimal
              return true;
          }
          break;
        case "System.UInt16": //ushort
          switch(typeNameTo)
          {
            case "System.Int32": //ushort->int
              return true;
            case "System.UInt32": //ushort->uint
              return true;
            case "System.Int64": //ushort->long
              return true;
            case "System.UInt64": //ushort->ulong
              return true;
            case "System.Single": //ushort->float
              return true;
            case "System.Double": //ushort->double
              return true;
            case "System.Decimal": //ushort->decimal
              return true;
          }
          break;
        case "System.Int32":  //int
          switch(typeNameTo)
          {
            case "System.Int64": //int->long
              return true;
            case "System.Single": //int->float
              return true;
            case "System.Double": //int->double
              return true;
            case "System.Decimal": //int->decimal
              return true;
          }
          break;
        case "System.UInt32": //uint
          switch(typeNameTo)
          {
            case "System.Int64": //uint->long
              return true;
            case "System.UInt64": //uint->ulong
              return true;
            case "System.Single": //uint->float
              return true;
            case "System.Double": //uint->double
              return true;
            case "System.Decimal": //uint->decimal
              return true;
          }
          break;
        case "System.Int64":  //long
        case "System.UInt64": //ulong
          switch(typeNameTo)
          {
            case "System.Single": //(u)long->float
              return true;
            case "System.Double": //(u)long->double
              return true;
            case "System.Decimal": //(u)long->decimal
              return true;
          }
          break;
        case "System.Char": //char
          switch(typeNameTo)
          {
            case "System.UInt16": //char->ushort
              return true;
            case "System.Int32": //char->int
              return true;
            case "System.UInt32": //char->uint
              return true;
            case "System.Int64": //char->long
              return true;
            case "System.UInt64": //char->ulong
              return true;
            case "System.Single": //char->float
              return true;
            case "System.Double": //char->double
              return true;
            case "System.Decimal": //char->decimal
              return true;
          }
          break;
        case "System.Single": //char
          switch(typeNameTo)
          {
            case "System.Double": //float->double
              return true;
          }
          break;
      }
      #endregion

      //6.1.7 User-defined implicit conversions
      #region 6.1.7 User-defined implicit conversions
  
      CodeTypeInfo typeFrom = FindType(typeNameFrom);
      if(typeFrom == null)
        return false;

      foreach(CodeMethodInfo methodInfo in typeFrom.GetMethods())
      {
        if(methodInfo.Name != "op_Implicit")
          continue;
        
        //If the implicit conversion type is not equal our from type
        //check if there is a possible conversion from it to the
        //targeted type.
        if(methodInfo.ReturnType != typeNameFrom)
          if(DoesImplicitConversionExist(methodInfo.ReturnType,typeNameTo))
            return true;
      }
      #endregion
      return false;
    }
    

    /// <summary>
    /// Finds an indexer defined on <paramref name="typeName"/> type.
    /// </summary>
    /// <param name="typeName">Full name of indexer container type.</param>
    /// <param name="argumentTypes">A colection full names of types passed as an indexer arguments.</param>
    /// <param name="isStatic">True if indexer shall be defined as static.</param>
    /// <returns>Returns indexer information if indexer is found - null otherwise.</returns>
    public CodePropertyInfo FindIndexer(string typeName,StringCollection argumentTypes,bool isStatic)
    {
      CodeTypeInfo typeInfo = FindType(typeName);
      while(typeInfo != null)
      {
        foreach(CodePropertyInfo property in typeInfo.GetProperties())
        {
          if(isStatic && !property.IsStatic)
            continue;

          if(!isStatic && property.IsStatic)
            continue;

          if(string.Compare(property.Name,"Item",false) != 0)
            continue;

          if(DoParametersMatchArguments(property.GetIndexParameters(),argumentTypes))
            return property;
        }
        //Lookup base type members if base type exists.
        if(typeInfo.GetBaseType() == null)
          return null;

        typeInfo = FindType(typeInfo.GetBaseType());
      }

      return null;
    }


    /// <summary>
    /// Finds a method defined on <paramref name="typeName"/> or one of its base types.
    /// </summary>
    /// <param name="typeName">Full name of the type to search.</param>
    /// <param name="methodName">Name of the method to search for.</param>
    /// <param name="argumentTypes">A collection of argument types passesd on method invokation.</param>
    /// <param name="isStatic">True if method shall be defined as static method.</param>
    /// <returns>Returns method information if found - null otherwise.</returns>
    public CodeMethodInfo FindMethod(string typeName,string methodName,StringCollection argumentTypes,bool isStatic)
    {
      return FindMethod(typeName,methodName,argumentTypes,isStatic,true);
    }
    public CodeMethodInfo FindMethod(string typeName,string methodName,StringCollection argumentTypes,bool isStatic,bool isCaseSensitive)
    {
      CodeTypeInfo typeInfo = FindType(typeName,isCaseSensitive);
      while(typeInfo != null)
      {
        
        foreach(CodeMethodInfo methodInfo in typeInfo.GetMethods())
        {
          if(isStatic && !methodInfo.IsStatic)
            continue;

          if(!isStatic && methodInfo.IsStatic)
            continue;

          if(string.Compare(methodInfo.Name,methodName,!isCaseSensitive) != 0)
            continue;

          if(DoParametersMatchArguments(methodInfo.GetParameters(),argumentTypes))
            return methodInfo;
        }

        //Lookup base type members if base type exists.
        if(typeInfo.GetBaseType() == null)
          return null;

        typeInfo = FindType(typeInfo.GetBaseType(),isCaseSensitive);
      }
      return null;
    }
    /// <summary>
    /// Finds a method defined on <paramref name="typeName"/> or one of its base types.
    /// </summary>
    /// <param name="typeName">Full name of the type to search.</param>
    /// <param name="methodName">Name of the method to search for.</param>
    /// <param name="isStatic">True if method shall be defined as static method.</param>
    /// <returns>Returns method information if found - null otherwise.</returns>
    /// <remarks>Method binding is weak as method signature comparison is not performed in this case</remarks>
    public CodeMethodInfo FindMethod(string typeName,string methodName,bool isStatic)
    {
      return FindMethod(typeName,methodName,isStatic,true);
    }
    public CodeMethodInfo FindMethod(string typeName,string methodName,bool isStatic,bool isCaseSensitive)
    {
      CodeTypeInfo typeInfo = FindType(typeName);
      while(typeInfo != null)
      {
        
        foreach(CodeMethodInfo methodInfo in typeInfo.GetMethods())
        {
          if(isStatic && !methodInfo.IsStatic)
            continue;

          if(!isStatic && methodInfo.IsStatic)
            continue;

          if(string.Compare(methodInfo.Name,methodName,!isCaseSensitive) != 0)
            continue;

          return methodInfo;
        }

        //Lookup base type members if base type exists.
        if(typeInfo.GetBaseType() == null)
          return null;

        typeInfo = FindType(typeInfo.GetBaseType(),isCaseSensitive);
      }
      return null;
    }

    public void BuildAssemblyMetadata()
    {
      BuildAssemblyMetadata(null);
    }
    public void BuildAssemblyMetadata(ManualResetEvent cancelEvent)
    {
      if(cancelEvent!= null && cancelEvent.WaitOne(0,false))
        return;

      //Collect all unused memory as building Metadata is memory hungry process 
      HelperData data = new HelperData();
      data.cancelEvent = cancelEvent;
      BuildAssemblyTypeSystem(cancelEvent);
      
      if(cancelEvent!= null && cancelEvent.WaitOne(0,false))
        return;

      //Pass one. Resolve all type references.
      ResolveTypeReferences(data);
      if(data.cancelEvent!= null && data.cancelEvent.WaitOne(0,false))
        return;
      //Pass two. Resolve expressions
      //It is important that we do it AFTER we resolved type references.
      ResolveExpressionTypes(data);
      ResolveAspNetTagProperties(data);
    }

    
    public void RegisterTypeName(string fulltypeName,CodeTypeInfo typeInfo)
    {
      if(!caseSensitiveAssebmlyTypes.Contains(fulltypeName))
        caseSensitiveAssebmlyTypes[fulltypeName] = typeInfo;

      if(!caseInsensitiveAssebmlyTypes.Contains(fulltypeName))
        caseInsensitiveAssebmlyTypes[fulltypeName] = typeInfo;
    }

    public CodeTypeInfo ResolveTypeReference(CodeTypeReference typeReference,CodeTypeDeclaration typeReferenceContainer)
    {
      HelperData data  = new HelperData();
      data.cancelEvent = new ManualResetEvent(false);
      CodeElement originalReferenceParent = typeReference.Parent;
      typeReference.Parent = typeReferenceContainer;
      data.activeNamspace = typeReferenceContainer.DeclaringNamespace;
      data.activeTypeDeclaration = typeReferenceContainer;
      typeReference.TypeInfo = ResolveTypeReference(typeReference,data);
      typeReference.Parent = originalReferenceParent;
      return typeReference.TypeInfo;
    }

    private class HelperData
    {
      public CodeNamespace activeNamspace = null;
      public CodeTypeDeclaration activeTypeDeclaration = null;
      public ManualResetEvent cancelEvent;
    }
    private void SynchronizedReplacedElement(CodeElement newElement,CodeElement oldElement)
    {
      newElement.Parent = oldElement.Parent;
      newElement.SourcePosition = oldElement.SourcePosition;
      newElement.CompileUnit = oldElement.CompileUnit;
      newElement.Comment = oldElement.Comment;
      newElement.DocumentationComment = oldElement.DocumentationComment;
    }


    private CodeTypeInfo ResolveTypeReference(CodeTypeReference typeReference, HelperData data)
    {
      bool isTypeCaseSensitive = true;
      //Type reference specified in aspx control is case insensitive!
      if(typeReference.Parent is AspNetServerControl)
        isTypeCaseSensitive = false;

      //1. Resolve arrays and pointers
      if(typeReference.IsPointer)
      {
        CodeTypeInfo pointerType = ResolveTypeReference(typeReference.PointerType,data);
        if(pointerType != null)
          return pointerType.GetPointerType();
        else
          return null;
      }

      if(typeReference.IsArray)
      {
        CodeTypeInfo elementType = ResolveTypeReference(typeReference.ArrayElementType,data);
        if(elementType != null)
          return elementType.GetArrayType();
        else
          return null;
      }
      
      string typeName = typeReference.TypeName;

      //1. Check parent/container types
      //If type reference type is equal to the name of any of those types - we found our type reference
      CodeElement parentType = typeReference;
      while(parentType != null)
      {
        if(parentType is CodeTypeDeclaration)
          if(String.Compare(typeName,(parentType as CodeTypeDeclaration).Name,!parentType.CompileUnit.IsCaseSensitive) == 0)
            return FindType((parentType as CodeTypeDeclaration).FullName,parentType.CompileUnit.IsCaseSensitive);
        
        parentType = parentType.Parent;
      }

      //2. Build table of aliases and imported namespaces
      StringCollection importedNamespaces = new StringCollection();
      NameValueCollection importedAliases = new NameValueCollection();
      CodeNamespace activeNamespace = data.activeNamspace;
      while(activeNamespace != null)
      {
        foreach(CodeNamespaceImport namespaceImport in activeNamespace.Imports)
        {
          if(namespaceImport.Alias != null && namespaceImport.Alias.Length != 0)
            importedAliases.Add(namespaceImport.Alias,namespaceImport.ImportedName);
          else
            importedNamespaces.Add(namespaceImport.ImportedName);
        }
        importedNamespaces.Add(activeNamespace.FullName);
        activeNamespace = activeNamespace.Parent as CodeNamespace;
      }

      CodeTypeInfo typeInfo = null;
      //3. Check aliases first
      foreach(string alias in importedAliases.AllKeys)
        if(typeName.StartsWith(alias + "."))
        {
          //It is aliased name - look it up 
          string modifiedTypeName = typeName.Replace(alias+".",importedAliases[alias] + ".");
          typeInfo = FindType(modifiedTypeName,isTypeCaseSensitive);
          if(typeInfo != null)
            return typeInfo;
        }

      //4. Check all imported namespaces
      foreach(string namespaceName in importedNamespaces)
      {
        StringBuilder currentNamespacePrefix = new StringBuilder();
        foreach(string subNamespacename in  namespaceName.Split('.'))
        {
          currentNamespacePrefix.Append(subNamespacename);
          string modifiedTypeName = currentNamespacePrefix.ToString()+"." + typeName;
    
          typeInfo = FindType(modifiedTypeName,isTypeCaseSensitive);
          if(typeInfo != null)
            return typeInfo;

          currentNamespacePrefix.Append('.');
        }
      }

      //5. Lookup the full type name. Who knows - maybe it is fully qulified type name
      typeInfo = FindType(typeName,isTypeCaseSensitive);
      if(typeInfo != null)
        return typeInfo;

      return null;
    }

    private void ResolveExpressionTypes(HelperData data)
    {
      foreach(CodeAssemblyFile assemblyFile in codeAssembly.AssemblyFiles)
      {
        if(data.cancelEvent!= null && data.cancelEvent.WaitOne(0,false))
          return;
        CodeDomWalker.WalkCompileUnit(assemblyFile,new CodeDomWalker.WalkerCallback(ResolveExpressionTypesCallBack),data);
      }
    }
  
    private CodeExpression ResolveExpressionType(CodeArrayInitializerExpression expression,HelperData data)
    {
      expression.ExpressionType = FindType(typeof(System.Array).FullName);
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeArrayCreateExpression expression,HelperData data)
    {
      expression.ExpressionType = expression.CreateType.TypeInfo;
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodePrimitiveExpression expression,HelperData data)
    {
      expression.ExpressionType = FindType(expression.Value.GetType().FullName);
      if(expression.ExpressionType == null)
        expression.ExpressionType = FindType(typeof(Object).FullName);
    
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeVariableReferenceExpression expression,HelperData data)
    {
      expression.ExpressionType = expression.VariableDeclaration.DeclarationType.TypeInfo;;
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeObjectCreateExpression expression,HelperData data)
    {
      expression.ExpressionType = expression.CreateType.TypeInfo;
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeIndexerInvokeExpression expression,HelperData data)
    {
      StringCollection argumentTypes = new StringCollection();
      for(int argumentIndex = 0; argumentIndex < expression.Arguments.Count; argumentIndex++)
      {
        expression.Arguments[argumentIndex].Value = ResolveExpressionType(expression.Arguments[argumentIndex].Value,data);
        //If I cannot resolve argument type - I will not be able to resolve method call - 
        //hence we can return now.
        if(expression.Arguments[argumentIndex].Value.ExpressionType == null)
          return expression;
        else
          argumentTypes.Add(expression.Arguments[argumentIndex].Value.ExpressionType.FullName);
      }

      /// This is generaly either a reference expression (this[], base[])
      /// or a named referenece Expression (item[])
      /// or a parenthesized expression (((MyType)myProperty)[MyTypeIndexerArgument]; )
      if(expression.IndexerReferenceExpression is CodeNamedReferenceExpression)
      {
        CodeNamedReferenceExpression indexerNamedReference = (expression.IndexerReferenceExpression as CodeNamedReferenceExpression);
        //If named and target equals null = than just Item on itself (probably VB syntaxis)
        if(indexerNamedReference.TargetObject == null)
        {
          indexerNamedReference.ExpressionType = FindType(data.activeTypeDeclaration.FullName);
        }
        else
        {
          if(indexerNamedReference.TargetObject.ExpressionType == null)
            indexerNamedReference.TargetObject = ResolveExpressionType(indexerNamedReference.TargetObject,data);

          indexerNamedReference.ExpressionType = indexerNamedReference.TargetObject.ExpressionType;
        }
      }
      else
      {
        if(expression.IndexerReferenceExpression.ExpressionType == null)
          expression.IndexerReferenceExpression = ResolveExpressionType(expression.IndexerReferenceExpression,data);
      }

      //If we cannot find indexer type - exit. There is nothing we can do
      if(expression.IndexerReferenceExpression.ExpressionType == null)
        return expression;

      CodePropertyInfo indexerInfo = FindIndexer(expression.IndexerReferenceExpression.ExpressionType.FullName,argumentTypes,false);
      if(indexerInfo != null)
      {
        expression.ExpressionType = FindType(indexerInfo.PropertyType);
        return expression;
      }

      //But wait we cannot find indexer! Maybe it is not an indexer? Maybe it is just a field or a property 
      //reference expression? It is just an array property or field!
      if(expression.IndexerReferenceExpression is CodeNamedReferenceExpression)
      {
        CodeExpression memberReferenceExpression = ResolveExpressionType(expression.IndexerReferenceExpression as CodeNamedReferenceExpression,data);
        if(memberReferenceExpression != null)
        {
          expression.IndexerReferenceExpression = memberReferenceExpression;
          expression.ExpressionType = memberReferenceExpression.ExpressionType;
          expression.IndexerReferenceExpression.ExpressionType = memberReferenceExpression.ExpressionType;
          SynchronizedReplacedElement(memberReferenceExpression,expression.IndexerReferenceExpression);
        }
      }
      
            
      return expression;
    }
    
    private CodeExpression ResolveExpressionType(CodeMethodInvokeExpression expression,HelperData data)
    {
      //1. Resolve invocation argument types
      StringCollection parameterTypes = new StringCollection();
      for(int argumentIndex = 0; argumentIndex < expression.Arguments.Count; argumentIndex++)
      {
        expression.Arguments[argumentIndex].Value = ResolveExpressionType(expression.Arguments[argumentIndex].Value,data);
        //If I cannot resolve argument type - I will not be able to resolve method call - 
        //hence we can return now.
        if(expression.Arguments[argumentIndex].Value.ExpressionType == null)
          return expression;
        else
        {
          string parameterTypeName = expression.Arguments[argumentIndex].Value.ExpressionType.FullName;
          if(expression.Arguments[argumentIndex].Modifier != CodeArgument.CodeArgumentModifier.None)
            parameterTypeName = parameterTypeName + "&";
                    
          parameterTypes.Add(parameterTypeName);
        }
      }

      //Can be
      //Method call foo();
      //Event call myEvent();
      //Delegate reference myDelegates[0]();

      //delegate reference in array myDelegates[0]
      if(!(expression.MethodReferenceExpression is CodeNamedReferenceExpression))
      {
        //For now resolve the method reference and see if delegate information is available to determine
        //return type
        expression.MethodReferenceExpression = ResolveExpressionType(expression.MethodReferenceExpression,data);
        if(expression.MethodReferenceExpression.ExpressionType != null)
          if(expression.MethodReferenceExpression.ExpressionType.IsDelegate)
            expression.ExpressionType = FindType(expression.MethodReferenceExpression.ExpressionType.GetDelegateReturnType());
        
        return expression;
      }

      CodeNamedReferenceExpression methodNamedReferenceExpression = expression.MethodReferenceExpression as CodeNamedReferenceExpression;

      CodeTypeInfo methodTypeInfo = null;
      bool isStatic = false;
      string methodReferenceName = (expression.MethodReferenceExpression as CodeNamedReferenceExpression).Name;
      if(methodNamedReferenceExpression.TargetObject == null)
      {
        methodTypeInfo = FindType(data.activeTypeDeclaration.FullName);
        //If there is no target object - than static if static container - otherwise instance
        //find out if static binding
        CodeElement parentElement = expression;
        while(parentElement != null && !(parentElement is CodeTypeMemberDeclaration))
          parentElement = parentElement.Parent;

        if(parentElement is CodeTypeMemberDeclaration)
          isStatic = ((parentElement as CodeTypeMemberDeclaration).Modifiers & CodeTypeMemberDeclaration.MemberDeclarationModifiers.Static) != 0;
      }
      else
      {
        //Try to resolve target type
        if(methodNamedReferenceExpression.TargetObject.ExpressionType == null)
          methodNamedReferenceExpression.TargetObject = ResolveExpressionType(methodNamedReferenceExpression.TargetObject,data);

        //If cannot resolve target type check if it is a reference to the type and we are calling static method
        if(methodNamedReferenceExpression.TargetObject != null && methodNamedReferenceExpression.TargetObject.ExpressionType == null)
        {
          //For static type reference target expression must be named reference. 
          //otherwise - we do not know what it is and should return.
          if(!(methodNamedReferenceExpression.TargetObject is CodeNamedReferenceExpression))
            return expression;
      
          string typeName = GetTargetReferencesAsString(methodNamedReferenceExpression.TargetObject as CodeNamedReferenceExpression);
          CodeTypeReference typeReference = new CodeTypeReference(typeName);

          typeReference.TypeInfo = ResolveTypeReference(typeReference,data);
          if(typeReference.TypeInfo != null)
          {
            //Determine source position of new type reference.
            CodeNamedReferenceExpression firstReference = methodNamedReferenceExpression.TargetObject as CodeNamedReferenceExpression;
            while(firstReference.TargetObject != null && firstReference.TargetObject is CodeNamedReferenceExpression)
              firstReference = firstReference.TargetObject as CodeNamedReferenceExpression;

            methodNamedReferenceExpression.TargetObject = new CodeTypeReferenceExpression(typeReference);
            SynchronizedReplacedElement(methodNamedReferenceExpression.TargetObject,firstReference);
            SynchronizedReplacedElement(typeReference,firstReference);


            methodNamedReferenceExpression.TargetObject.ExpressionType = typeReference.TypeInfo;
            isStatic = true;
          }
        }

        if(methodNamedReferenceExpression.TargetObject.ExpressionType == null) //Cannot resolve target type
          return expression;
        
        methodTypeInfo = methodNamedReferenceExpression.TargetObject.ExpressionType;
      }

      //Is it a method call?
      CodeMethodInfo methodInfo = null;
      methodInfo = FindMethod(methodTypeInfo.FullName,methodReferenceName,parameterTypes,isStatic);
      if(methodInfo != null)
      {
        expression.MethodReferenceExpression = new CodeMethodReferenceExpression(methodNamedReferenceExpression.TargetObject,methodNamedReferenceExpression.Name);
        SynchronizedReplacedElement(expression.MethodReferenceExpression,methodNamedReferenceExpression);
        (expression.MethodReferenceExpression as CodeMethodReferenceExpression).MethodInfo = methodInfo;
        expression.MethodReferenceExpression.ExpressionType = null;
        expression.ExpressionType = FindType(methodInfo.ReturnType);
        return expression;
      }

      //Is it an event activation?
      CodeEventInfo eventInfo = null;
      //The nice thing about events is that I do not need to verify argumets list.
      //compiler wount allow duplicate event names with different invokation signatures.
      eventInfo = FindEvent(methodTypeInfo.FullName,methodReferenceName,isStatic);
      if(eventInfo != null)
      {
        CodeEventReferenceExpression eventReferenceExpression = new CodeEventReferenceExpression(methodNamedReferenceExpression.TargetObject,methodNamedReferenceExpression.Name);
        SynchronizedReplacedElement(eventReferenceExpression,methodNamedReferenceExpression);
        eventReferenceExpression.ExpressionType = FindType(eventInfo.EventHandlerType);
        eventReferenceExpression.EventInfo = eventInfo;
        expression.MethodReferenceExpression = eventReferenceExpression;
        CodeTypeInfo eventHandlerType = FindType(eventInfo.EventHandlerType);
        if(eventHandlerType != null && eventHandlerType.IsDelegate)
          expression.ExpressionType = FindType(eventHandlerType.GetDelegateReturnType());

        return expression;
      }

      //Debug.Assert(expression.ExpressionType != null,"Debug purposes. If it is null it is bad but is not fatal. Just stop processing these expressions.");

      expression.ExpressionType = null;
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeNamedReferenceExpression expression,HelperData data)
    {
      return ResolveExpressionType(expression,data,true);
    }

    private CodeExpression ResolveExpressionType(CodeNamedReferenceExpression expression,HelperData data,bool isCaseSensitive)
    {
      //If target is not null and have not been resolved yet - resolve it.
      if(expression.TargetObject != null && expression.TargetObject.ExpressionType == null)
        expression.TargetObject = ResolveExpressionType(expression.TargetObject,data);

      //find out if static binding
      bool isStatic = false;
      //if target is not null and cannot be resolved - check if target is reference to a type
      //and we are reference to the statc property of the type.
      if(expression.TargetObject != null && expression.TargetObject.ExpressionType == null)
      {
        //For static type reference target expression must be named reference. 
        //otherwise - we do not know what it is and should return.
        if(!(expression.TargetObject is CodeNamedReferenceExpression))
          return expression;
      
        string typeName = GetTargetReferencesAsString(expression.TargetObject as CodeNamedReferenceExpression);
        CodeTypeReference typeReference = new CodeTypeReference(typeName);

        typeReference.TypeInfo = ResolveTypeReference(typeReference,data);
        if(typeReference.TypeInfo != null)
        {
          CodeNamedReferenceExpression firstReference = expression.TargetObject as CodeNamedReferenceExpression;
          while(firstReference.TargetObject != null && firstReference.TargetObject is CodeNamedReferenceExpression)
            firstReference = firstReference.TargetObject as CodeNamedReferenceExpression;

          expression.TargetObject = new CodeTypeReferenceExpression(typeReference);
          expression.TargetObject.ExpressionType = typeReference.TypeInfo;
          SynchronizedReplacedElement(expression.TargetObject,firstReference);
          SynchronizedReplacedElement(typeReference,firstReference);
          isStatic = true;
        }
      }

      //If I cannot determine resulting type - just exit.
      if(expression.TargetObject != null && expression.TargetObject.ExpressionType == null)
        return expression;

      if(data.activeTypeDeclaration == null)
        return expression;

      //Check if it is reference to the type/target member
      //field
      //property
      //event
      CodeTypeInfo expressionType = null;
      if(expression.TargetObject == null)
      {
        expressionType = FindType(data.activeTypeDeclaration.FullName,isCaseSensitive);
        
        //If target object is null check container type. If static than call is also static
        CodeElement parentElement = expression;
        while(parentElement != null && !(parentElement is CodeTypeMemberDeclaration))
          parentElement = parentElement.Parent;

        if(parentElement is CodeTypeMemberDeclaration)
          isStatic = ((parentElement as CodeTypeMemberDeclaration).Modifiers & CodeTypeMemberDeclaration.MemberDeclarationModifiers.Static) != 0;

      }
      else
        expressionType = expression.TargetObject.ExpressionType;

      Debug.Assert(expressionType != null,"Expression type must be defined here.");
      CodeFieldInfo filedInfo = FindField(expressionType.FullName,expression.Name,isStatic,isCaseSensitive);
      if(filedInfo != null)
      {
        CodeFieldReferenceExpression fieldReferenceExpression = null;
        if(expression is CodeFieldReferenceExpression)
          fieldReferenceExpression = (expression as CodeFieldReferenceExpression);
        else
        {
          fieldReferenceExpression = new CodeFieldReferenceExpression(expression.TargetObject,expression.Name);
          SynchronizedReplacedElement(fieldReferenceExpression,expression);
        }

        fieldReferenceExpression.ExpressionType = FindType(filedInfo.FieldType,isCaseSensitive);
        fieldReferenceExpression.FieldInfo = filedInfo;
        return fieldReferenceExpression;
      }

      CodePropertyInfo propertyInfo = FindProperty(expressionType.FullName,expression.Name,isStatic,isCaseSensitive);
      if(propertyInfo != null)
      {
        CodePropertyReferenceExpression propertyReferenceExpression;
        if(expression is CodePropertyReferenceExpression)
          propertyReferenceExpression = expression as CodePropertyReferenceExpression;
        else
        {
          propertyReferenceExpression = new CodePropertyReferenceExpression(expression.TargetObject,expression.Name);
          SynchronizedReplacedElement(propertyReferenceExpression,expression);
        }

        propertyReferenceExpression.ExpressionType = FindType(propertyInfo.PropertyType,isCaseSensitive);
        propertyReferenceExpression.PropertyInfo = propertyInfo;
        return propertyReferenceExpression;
      }

      CodeEventInfo eventInfo = FindEvent(expressionType.FullName,expression.Name,isStatic,isCaseSensitive);
      if(eventInfo != null)
      {
        CodeEventReferenceExpression eventReferenceExpression;
        if(expression is CodeEventReferenceExpression)
          eventReferenceExpression = expression as CodeEventReferenceExpression;
        else
        {
          eventReferenceExpression = new CodeEventReferenceExpression(expression.TargetObject,expression.Name);
          SynchronizedReplacedElement(eventReferenceExpression,expression);
        }

        eventReferenceExpression.ExpressionType = FindType(eventInfo.EventHandlerType,isCaseSensitive);
        eventReferenceExpression.EventInfo = eventInfo;
        return eventReferenceExpression;
      }

      //If we still could not resolve an expression
      //it looks like we have a reference to a delegate in the method
      //Try to find method and disregard any parametrs - 
      //it is for delegates only. 
      //Think if we can redo it to extend metadata and make method reference more accurate by
      //analyzing delegate signature and requiring the same signature for our method.
      if(expression is CodeUnresolvedReferenceExpression)
      {
        CodeMethodInfo methodInfo = FindMethod(expressionType.FullName,expression.Name,isStatic,isCaseSensitive);
        
        //If we checked instance method and could not find it - check if we can find static method
        //it will be as delegate reference
        if(isStatic == false && methodInfo == null)
          methodInfo = FindMethod(expressionType.FullName,expression.Name,true,isCaseSensitive);

        if(methodInfo != null)
        {
          CodeMethodReferenceExpression methodReferenceExpression = new CodeMethodReferenceExpression(expression.TargetObject,expression.Name);
          SynchronizedReplacedElement(methodReferenceExpression,expression);
          methodReferenceExpression.MethodInfo = methodInfo;
          methodReferenceExpression.ExpressionType = null;
          return methodReferenceExpression;
        }
      }

      return expression;
    }

    private string GetOperatorMethodName(CodeBinaryOperatorType binaryOperator)
    {
      switch(binaryOperator)
      {
        case CodeBinaryOperatorType.Addition:
          return "op_Addition";
        case CodeBinaryOperatorType.BitwiseAnd:
          return "op_BitwiseAnd";
        case CodeBinaryOperatorType.BitwiseOr:
          return "op_BitwiseOr";
        case CodeBinaryOperatorType.Division:
          return "op_Division";
        case CodeBinaryOperatorType.Equality:
          return "op_Equality";
        case CodeBinaryOperatorType.ExclusiveOr:
          return "op_ExclusiveOr";
        case CodeBinaryOperatorType.GreaterThan:
          return "op_GreaterThan";
        case CodeBinaryOperatorType.GreaterThanOrEqual:
          return "op_GreaterThanOrEqual";
        case CodeBinaryOperatorType.Inequality:
          return "op_Inequality";
        case CodeBinaryOperatorType.LeftShift:
          return "op_LeftShift";
        case CodeBinaryOperatorType.LessThan:
          return "op_LessThan";
        case CodeBinaryOperatorType.LessThanOrEqual:
          return "op_LessThanOrEqual";
        case CodeBinaryOperatorType.Modulus:
          return "op_Modulus";
        case CodeBinaryOperatorType.Multiply:
          return "op_Multiply";
        case CodeBinaryOperatorType.RightShift:
          return "op_RightShift";
        case CodeBinaryOperatorType.Subtraction:
          return "op_Subtraction";
      }
      return null;
    }

    private CodeExpression ResolveExpressionType(CodeTypeReferenceExpression expression,HelperData data)
    {
      expression.ExpressionType = expression.ReferencedType.TypeInfo;
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeBinaryExpression expression,HelperData data)
    {
      if(expression.RightOperand != null && expression.RightOperand.ExpressionType == null)
        expression.RightOperand = ResolveExpressionType(expression.RightOperand,data);

      if(expression.LeftOperand != null && expression.LeftOperand.ExpressionType == null)
        expression.LeftOperand = ResolveExpressionType(expression.LeftOperand,data);

      if(expression.RightOperand.ExpressionType == null || expression.LeftOperand.ExpressionType == null)
        return expression;

      switch(expression.Operator)
      {
        case CodeBinaryOperatorType.Equality:
        case CodeBinaryOperatorType.GreaterThan:
        case CodeBinaryOperatorType.GreaterThanOrEqual:
        case CodeBinaryOperatorType.Inequality:
        case CodeBinaryOperatorType.Is:
        case CodeBinaryOperatorType.LessThan:
        case CodeBinaryOperatorType.LessThanOrEqual:
        case CodeBinaryOperatorType.LogicalAnd:
        case CodeBinaryOperatorType.LogicalOr:
        {
          expression.ExpressionType = FindType("System.Boolean");
          break;
        }

        case CodeBinaryOperatorType.Assign:
        {
          expression.ExpressionType = expression.LeftOperand.ExpressionType;
          break;
        }
        case CodeBinaryOperatorType.As:
        {
          expression.ExpressionType = expression.RightOperand.ExpressionType;
          break;
        }
        case CodeBinaryOperatorType.MemberSelection:
        {
          expression.ExpressionType = null;
          break;
        }
        case CodeBinaryOperatorType.PointerToMemberSelection:
        {
          expression.ExpressionType = null;
          break;
        }
        case CodeBinaryOperatorType.Question:
        {
          expression.LeftOperand = ResolveExpressionType(expression.LeftOperand as CodeConditionalExpression,data);
          break;
        }

        default:
        {
          StringCollection arguments = new StringCollection();
          string leftArgumentTypeName = expression.LeftOperand.ExpressionType.FullName;
          string rightArgumentTypeName = expression.RightOperand.ExpressionType.FullName;
          arguments.Add(leftArgumentTypeName);
          arguments.Add(rightArgumentTypeName);

          //Check user overloadable operators first
          CodeMethodInfo opMethod = FindMethod(expression.LeftOperand.ExpressionType.FullName,GetOperatorMethodName(expression.Operator),arguments,true);
          if(opMethod != null)
            expression.ExpressionType = FindType(opMethod.ReturnType);

          //Check predefined operators 
          //it is a little cheat but it will work as almost all operators define itself 
          //in a simetrical form T (T op T)
          //except for couple of cases:
          //Two special cases for string:
          //string operator +(string x, object y);
          //string operator +(object x, string y);
          if(expression.Operator == CodeBinaryOperatorType.Addition || expression.Operator == CodeBinaryOperatorType.AdditionAssignment)
          {
            if( (DoesImplicitConversionExist(leftArgumentTypeName,"System.String") && DoesImplicitConversionExist(rightArgumentTypeName,"System.Object")) || 
              (DoesImplicitConversionExist(leftArgumentTypeName,"System.Object") && DoesImplicitConversionExist(rightArgumentTypeName,"System.String")))
            {
              expression.ExpressionType = FindType("System.String");
              break;
            }
          }
          //Another special case are delegates - they define + and - operators
          if(expression.Operator == CodeBinaryOperatorType.Addition || 
            expression.Operator == CodeBinaryOperatorType.AdditionAssignment ||
            expression.Operator == CodeBinaryOperatorType.SubtractionAssignment ||
            expression.Operator == CodeBinaryOperatorType.Subtraction)
          {
            if((DoesImplicitConversionExist(leftArgumentTypeName,"System.Delegate") && DoesImplicitConversionExist(rightArgumentTypeName,"System.Delegate")))
            {
              expression.ExpressionType = FindType(leftArgumentTypeName);
              break;
            }
          }


          string[] predefinedTypeNames = new string[] 
          {
            "System.Int32",
            "System.UInt32",
            "System.Int64",
            "System.UInt64",
            "System.Single",
            "System.Double",
            "System.Decimal",
          };

          foreach(string predefinedTypeName in predefinedTypeNames)
          {
            if(DoesImplicitConversionExist(leftArgumentTypeName,predefinedTypeName) && DoesImplicitConversionExist(rightArgumentTypeName,predefinedTypeName))
            {
              expression.ExpressionType = FindType(predefinedTypeName);
              break;
            }
          }
          break;
        }
      }

      return expression;
    }
    
    private CodeExpression ResolveExpressionType(CodeConditionalExpression expression,HelperData data)
    {
      expression.TrueExpression = ResolveExpressionType(expression.TrueExpression,data);
      expression.FalseExpression = ResolveExpressionType(expression.FalseExpression,data);

      if(expression.TrueExpression.ExpressionType != null && !(expression.TrueExpression is CodeNullReferenceExpression))
      {
        expression.ExpressionType =  expression.TrueExpression.ExpressionType;
      }
      else
      {
        expression.ExpressionType = expression.FalseExpression.ExpressionType;
      }

      return expression;
    }
    
    private CodeExpression ResolveExpressionType(CodeUnaryExpression expression,HelperData data)
    {

      if(expression.Operand != null && expression.Operand.ExpressionType == null)
        ResolveExpressionType(expression.Operand,data);

      if(expression.Operand != null)
        expression.ExpressionType = expression.Operand.ExpressionType;
      return expression;
    }
    
    private CodeExpression ResolveExpressionType(CodeMethodParameterReferenceExpression expression,HelperData data)
    {
      if(expression.MethodParameter != null && expression.MethodParameter.Type != null && expression.MethodParameter.Type.TypeInfo != null)
        expression.ExpressionType = expression.MethodParameter.Type.TypeInfo;
      else
        expression.ExpressionType = null;
      return expression;
    }
    
    private CodeExpression ResolveExpressionType(CodeParenthesizedExpression expression,HelperData data)
    {
      if(expression.Expression.ExpressionType == null)
        expression.Expression = ResolveExpressionType(expression.Expression,data);

      expression.ExpressionType = expression.Expression.ExpressionType;
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeTypeCastExpression expression,HelperData data)
    {
      //If expression to be cast has not been resolved yet - do so!
      if(expression.Expression != null && expression.Expression.ExpressionType == null)
        expression.Expression = ResolveExpressionType(expression.Expression,data);

      if(expression.TargetType.TypeInfo != null)
        expression.ExpressionType = FindType(expression.TargetType.TypeInfo.FullName);
      else
        expression.ExpressionType = null;

      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeExpression expression,HelperData data)
    {
      if(expression.ExpressionType != null)
        return expression;

      if(expression is CodeMethodParameterReferenceExpression)
        return ResolveExpressionType(expression as CodeMethodParameterReferenceExpression,data);

      if(expression is CodeParenthesizedExpression)
        return ResolveExpressionType(expression as CodeParenthesizedExpression,data);
      
      if(expression is CodeArrayInitializerExpression)
        return ResolveExpressionType(expression as CodeArrayInitializerExpression,data);

      if(expression is CodeArrayCreateExpression)
        return ResolveExpressionType(expression as CodeArrayCreateExpression,data);

      if(expression is CodeObjectCreateExpression)
        return ResolveExpressionType(expression as CodeObjectCreateExpression,data);

      if(expression is CodePrimitiveExpression)
        return ResolveExpressionType(expression as CodePrimitiveExpression,data);

      if(expression is CodeVariableReferenceExpression)
        return ResolveExpressionType(expression as CodeVariableReferenceExpression,data);

      if(expression is CodeObjectCreateExpression)
        return ResolveExpressionType(expression as CodeObjectCreateExpression,data);
      
      if(expression is CodeMethodInvokeExpression)
        return ResolveExpressionType(expression as CodeMethodInvokeExpression,data);

      if(expression is CodeNamedReferenceExpression)
        return ResolveExpressionType(expression as CodeNamedReferenceExpression,data);

      if(expression is CodeBinaryExpression)
        return ResolveExpressionType(expression as CodeBinaryExpression,data);

      if(expression is CodeThisReferenceExpression)
        return ResolveExpressionType(expression as CodeThisReferenceExpression,data);

      if(expression is CodeBaseReferenceExpression)
        return ResolveExpressionType(expression as CodeBaseReferenceExpression,data);

      if(expression is CodeTypeReferenceExpression)
        return ResolveExpressionType(expression as CodeTypeReferenceExpression,data);

      if(expression is CodeUnaryExpression)
        return ResolveExpressionType(expression as CodeUnaryExpression,data);
      
      if(expression is CodeIndexerInvokeExpression)
        return ResolveExpressionType(expression as CodeIndexerInvokeExpression,data);

      if(expression is CodeTypeCastExpression)
        return ResolveExpressionType(expression as CodeTypeCastExpression,data);

      if(expression is CodeConditionalExpression)
        return ResolveExpressionType(expression as CodeConditionalExpression,data);

      //This expression does not have a type associated with it. It can only be used with 
      //method invoke expression.
      if(expression is CodeMethodReferenceExpression)
      {
        expression.ExpressionType = null;
        return expression;
      }

      ///Null does not have a type null is null.
      if(expression is CodeNullReferenceExpression)
      {
        expression.ExpressionType = CodeTypeInfo.GetNullTypeInfo();
        return expression;
      }

      Debug.WriteLine(expression.GetType().FullName);
      return expression;
    }
    
    private CodeExpression ResolveExpressionType(CodeThisReferenceExpression expression,HelperData data)
    {
      expression.ExpressionType = FindType(data.activeTypeDeclaration.FullName);
      return expression;
    }

    private CodeExpression ResolveExpressionType(CodeBaseReferenceExpression expression,HelperData data)
    {
      string baseTypeName = string.Empty;
      CodeTypeInfo activeTypeInfo = FindType(data.activeTypeDeclaration.FullName);
      if(activeTypeInfo != null && activeTypeInfo.GetBaseType() != null)
      {
        CodeTypeInfo baseTypeInfo = FindType(activeTypeInfo.GetBaseType());
        expression.ExpressionType = baseTypeInfo;
      }

      return expression;
    }

    private void ReplaceExpression(CodeExpression oldExpression,CodeExpression newExpression)
    {
      if(oldExpression.Parent == null)
        return;

      Type elementType = oldExpression.Parent.GetType();
      foreach(PropertyInfo propertyInfo in elementType.GetProperties())
      {
        //If property does not have public getter - we are not intrested.
        if(!propertyInfo.CanRead)
          continue;
        
        object properyValue = propertyInfo.GetValue(oldExpression.Parent,null);
        if(properyValue == oldExpression)
        {
          propertyInfo.SetValue(oldExpression.Parent,newExpression,null);
          return;
        }

        if(properyValue is CodeElementCollectionBase)
        {
          MethodInfo indexOfMethod = propertyInfo.PropertyType.GetMethod("IndexOf");
          if(indexOfMethod.GetParameters().Length != 1)
            continue;

          int index = -1;
          Type parametherType = indexOfMethod.GetParameters()[0].ParameterType;
          if(parametherType == oldExpression.GetType() ||
            oldExpression.GetType().IsSubclassOf(parametherType))
          {
            index = (int) indexOfMethod.Invoke(properyValue,new object[1] {oldExpression});
          }
          if(index != -1)
          {
            MethodInfo set_ItemMethod = propertyInfo.PropertyType.GetMethod("set_Item");
            set_ItemMethod.Invoke(properyValue,new object[2] {index,newExpression});
            return;
          }
        }
      }
    }
    private CodeDomWalker.WalkerCallbackReturn ResolveExpressionTypesCallBack(CodeElement codeElement,CodeDomWalker.CallBackNotificationType notification,CodeDomWalkerContext walkerContext,object applicationData)
    {
      switch(notification)
      {
        case CodeDomWalker.CallBackNotificationType.OnElement:
        {
          if(codeElement is CodeExpression)
          {
            //Let's get it easier on CPU
            System.Threading.Thread.Sleep(0);

            CodeExpression newExpression = ResolveExpressionType(codeElement as CodeExpression,applicationData as HelperData);
            if(newExpression != codeElement)
            {
              ReplaceExpression(codeElement as CodeExpression,newExpression);
              return CodeDomWalker.WalkerCallbackReturn.NextSibling;
            }
          }
          break;
        }
        case CodeDomWalker.CallBackNotificationType.OnElementChildrenStarted:
        {
          if(codeElement is CodeTypeDeclaration)
          {
            HelperData data = applicationData as HelperData;
            data.activeTypeDeclaration = codeElement as CodeTypeDeclaration;
          }

          if(codeElement is CodeNamespace)
          {
            HelperData data = applicationData as HelperData;
            data.activeNamspace = codeElement as CodeNamespace;
          }

          break;
        }
        case CodeDomWalker.CallBackNotificationType.OnElementChildrenFinished:
        {
          if(codeElement is CodeTypeDeclaration)
          {
            HelperData data = applicationData as HelperData;
            data.activeTypeDeclaration = data.activeTypeDeclaration.DeclaringType;
          }

          if(codeElement is CodeNamespace)
          {
            HelperData data = applicationData as HelperData;
            data.activeNamspace = data.activeNamspace.DeclaringNamespace;
          }

          break;
        }
      }

      return CodeDomWalker.WalkerCallbackReturn.Next;
    }

    private void ResolveTypeReferences(HelperData data)
    {
      foreach(CodeAssemblyFile assemblyFile in codeAssembly.AssemblyFiles)
      {
        if(data.cancelEvent!= null && data.cancelEvent.WaitOne(0,false))
          return;

        CodeDomWalker.WalkCompileUnit(assemblyFile,new CodeDomWalker.WalkerCallback(UpdateCodeDomTypeReferencesCallBack),data);
      }
    }
    
    private CodeDomWalker.WalkerCallbackReturn UpdateCodeDomTypeReferencesCallBack(CodeElement codeElement,CodeDomWalker.CallBackNotificationType notification,CodeDomWalkerContext walkerContext,object applicationData)
    {
      switch(notification)
      {
        case CodeDomWalker.CallBackNotificationType.OnElement:
        {
          if(codeElement is CodeTypeReference)
          {
            CodeTypeReference typeReference = codeElement as CodeTypeReference;
            
            if(typeReference.TypeInfo != null)
              break;

            typeReference.TypeInfo = ResolveTypeReference(typeReference,applicationData as HelperData);
            if(typeReference.TypeInfo == null && codeElement.Parent is CodeAttribute)
            {
              //If this is type reference for an attribute - lets see if we forgot an atribute suffix
              if(!typeReference.TypeName.EndsWith("Attribute"))
              {
                string originalAttributeTypeName = typeReference.TypeName;
                typeReference.TypeName = originalAttributeTypeName + "Attribute";
                typeReference.TypeInfo = ResolveTypeReference(typeReference,applicationData as HelperData);
                //Restore original type name
                typeReference.TypeName = originalAttributeTypeName;
              }
            }

            //Let's get it easier on CPU
            System.Threading.Thread.Sleep(0);
          }
          break;
        }
        case CodeDomWalker.CallBackNotificationType.OnElementChildrenStarted:
        {
          if(codeElement is CodeNamespace)
          {
            HelperData data = applicationData as HelperData;
            data.activeNamspace = codeElement as CodeNamespace;
          }
          if(codeElement is CodeTypeDeclaration)
          {
            HelperData data = applicationData as HelperData;
            data.activeTypeDeclaration = codeElement as CodeTypeDeclaration;
          }
          break;
        }
        case CodeDomWalker.CallBackNotificationType.OnElementChildrenFinished:
        {
          if(codeElement is CodeNamespace)
          {
            HelperData data = applicationData as HelperData;
            data.activeNamspace = data.activeNamspace.DeclaringNamespace;
          }
          if(codeElement is CodeTypeDeclaration)
          {
            HelperData data = applicationData as HelperData;
            data.activeTypeDeclaration = data.activeTypeDeclaration.DeclaringType;
          }
          break;
        }
      }

      return CodeDomWalker.WalkerCallbackReturn.Next;
    }
  
    private string GetTargetReferencesAsString(CodeNamedReferenceExpression namedReferenceExpression)
    {
      if(namedReferenceExpression == null)
        return string.Empty;

      if(namedReferenceExpression.TargetObject == null)
        return namedReferenceExpression.Name;

      if(!(namedReferenceExpression.TargetObject is CodeNamedReferenceExpression))
        return namedReferenceExpression.Name;

      return GetTargetReferencesAsString(namedReferenceExpression.TargetObject as CodeNamedReferenceExpression) + "." + namedReferenceExpression.Name;
    }

    private void ResolveAspNetTagProperties(HelperData data)
    {
      foreach(CodeAssemblyFile assemblyFile in codeAssembly.AssemblyFiles)
      {
        if(data.cancelEvent!= null && data.cancelEvent.WaitOne(0,false))
          return;

        CodeDomWalker.WalkCompileUnit(assemblyFile,new CodeDomWalker.WalkerCallback(ResolveAspNetControlPropertiesCallBack),data);
      }
    }
    private void ResolveAspNetTagProperties(AspNetTag aspNetTag)
    {
      if(aspNetTag is AspNetServerControl)
      {
        ResolveAspNetServerControlProperties(aspNetTag as AspNetServerControl);
        return;
      }

      Debug.Assert(false,"If you have added a new type of AspNet tag add property resolution handler here");

      
    }

    private void ResolveAspNetServerControlProperties(AspNetServerControl control)
    {
      //Step 1: Find out who is our parent:
      CodeElement parent = control.Parent;
      while(parent != null && !(parent is AspNetClassDeclaration))
        parent = parent.Parent;

      //If we could not resolve type - exit
      if(parent == null || (parent as AspNetClassDeclaration).TypeInfo == null)
        return;

      AspNetClassDeclaration aspNetClass = parent as AspNetClassDeclaration;

      //Helper struct
      HelperData data = new HelperData();
      data.activeNamspace = new CodeNamespace();
      data.activeTypeDeclaration = aspNetClass;
      data.cancelEvent = new ManualResetEvent(false);

      foreach(AspNetTagAttribute attribute in control.Attributes)
      {
        string attributeName = null;
        string attributeValue = null;

        attributeName = attribute.Name.Name;
        attributeValue = attribute.Value.Name;

        if(attributeName == null || attributeValue == null)
          return;


        //Generaly speaking attributes are potential properties of control type where values are 
        //potential properties of defining (page) class. 
        //But in all known to mankind cases there is only one case when value of the attribute is 
        //a member of defining class - it is case when the attribute itself defines an event and 
        //than attribute value defines a method reference.

        //I want to use already written routin to resolve attribute types. There is only one problem
        //by default it uses type past in the declaration to resolve members - to avoid it 
        //I'll create a fake target and will set it to control's type - effectevly enabling 
        //resolution from control type's type.

        //And oh, eah one more thing: Some .... decided to name event attributes on aspx tags
        //with prefix 'On'

        CodeUnresolvedReferenceExpression fakeTarget = new CodeUnresolvedReferenceExpression();
        fakeTarget.ExpressionType = control.ControlType.TypeInfo;
        attribute.Name.TargetObject = fakeTarget;
        if(attribute.Name.Name.ToLower().StartsWith("on"))
        {
          string originalName = attribute.Name.Name;
          attribute.Name.Name = originalName.Substring(2);
          attribute.Name = ResolveExpressionType(attribute.Name,data,false) as CodeNamedReferenceExpression;
          attribute.Name.Name = originalName;
        }
        
        if(attribute.Name is CodeUnresolvedReferenceExpression)
          attribute.Name = ResolveExpressionType(attribute.Name,data,false)  as CodeNamedReferenceExpression;

        attribute.Name.TargetObject = null;

        //Now lets resolve attribute value. We only care if attribute name is an event
        if(attribute.Name is CodeEventReferenceExpression)
        {
          CodeMethodInfo methodInfo = FindMethod(aspNetClass.TypeInfo.FullName,attribute.Value.Name,false,false);
          if(methodInfo != null)
          {
            CodeMethodReferenceExpression methodReference = new CodeMethodReferenceExpression();
            SynchronizedReplacedElement(methodReference,attribute.Value);
            methodReference.Name = attribute.Value.Name;
            methodReference.MethodInfo = methodInfo;
            methodReference.ExpressionType = null;
            attribute.Value = methodReference;
          }
        }
        else
        {
          attribute.Value = ResolveExpressionType(attribute.Value,data,false)  as CodeNamedReferenceExpression;
        }
      }
      
    }

    private CodeDomWalker.WalkerCallbackReturn ResolveAspNetControlPropertiesCallBack(CodeElement codeElement,CodeDomWalker.CallBackNotificationType notification,CodeDomWalkerContext walkerContext,object applicationData)
    {
      switch(notification)
      {
        case CodeDomWalker.CallBackNotificationType.OnElement:
        {
          if(codeElement is AspNetTag)
          {
            ResolveAspNetTagProperties(codeElement as AspNetTag);
          }
          break;
        }
      }
      return CodeDomWalker.WalkerCallbackReturn.Next;
    }
    private bool DoParametersMatchArguments(CodeParameterInfo[] methodParameters,StringCollection argumentTypes)
    {
      //No one has paramethers?
      if(methodParameters.Length == 0 && argumentTypes.Count == 0)
        return true;

      //Method parameters are optional
      if(methodParameters.Length == 1 &&  methodParameters[0].IsParameterArray && argumentTypes.Count == 0)
        return true;

      for(int methodParameterIndex = 0,argumentIndex = 0; methodParameterIndex < methodParameters.Length; methodParameterIndex++,argumentIndex++)
      {
        if(argumentIndex >= argumentTypes.Count)
          return false;

        //If current methodArgument is optional array of parameters
        //then process the rest of the arguments and see if they match
        if(methodParameters[methodParameterIndex].IsParameterArray && methodParameters[methodParameterIndex].TypeName.LastIndexOf('[') != -1)
        {
          string optionalParameterType = methodParameters[methodParameterIndex].TypeName;
          optionalParameterType = optionalParameterType.Substring(0,optionalParameterType.LastIndexOf('['));

          bool signatureMistmatch = false;
          for(int optionalArgumentIndex = argumentIndex; optionalArgumentIndex < argumentTypes.Count; optionalArgumentIndex++)
            if(!DoesImplicitConversionExist(argumentTypes[optionalArgumentIndex],optionalParameterType))
            {
              signatureMistmatch = true;
              break;
            }

          if(signatureMistmatch)
            break;
          else
            return true;
              
        }

        if(!DoesImplicitConversionExist(argumentTypes[argumentIndex],methodParameters[methodParameterIndex].TypeName))
          break;

        //If we have processed all arguments - we possibly found our match
        if(argumentIndex == argumentTypes.Count-1)
        {
          //Is it the last method parameter as well?
          if(methodParameterIndex == methodParameters.Length-1)
            return true;

          //No there are more method parameters. 
          //Are they optional?
          if(methodParameters[methodParameterIndex+1].IsParameterArray)
            return true; //Yes, rest of paramethers are optional - we found out match
          else
            break; //Otherwise - signatures do not match
        }
      }

      return false;
    }


    private CodeAssembly codeAssembly;
    private Hashtable caseSensitiveAssebmlyTypes = new Hashtable();
    private Hashtable caseInsensitiveAssebmlyTypes = new Hashtable(CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.