The Labs \ Source Viewer \ SSCLI \ Microsoft.JScript \ TypeExpression

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace Microsoft.JScript
  16. {
  17.    
  18.     using System;
  19.     using System.Collections;
  20.     using System.Reflection;
  21.     using System.Reflection.Emit;
  22.     using System.Text;
  23.    
  24.     internal sealed class TypeExpression : AST
  25.     {
  26.         internal AST expression;
  27.         internal bool isArray;
  28.         internal int rank;
  29.         private bool recursive;
  30.         private IReflect cachedIR;
  31.        
  32.         internal TypeExpression(AST expression) : base(expression.context)
  33.         {
  34.             this.expression = expression;
  35.             this.isArray = false;
  36.             this.rank = 0;
  37.             this.recursive = false;
  38.             this.cachedIR = null;
  39.             if (expression is Lookup) {
  40.                 string name = expression.ToString();
  41.                 object ptype = Globals.TypeRefs.GetPredefinedType(name);
  42.                 if (ptype != null)
  43.                     this.expression = new ConstantWrapper(ptype, expression.context);
  44.             }
  45.         }
  46.        
  47.         internal override object Evaluate()
  48.         {
  49.             return this.ToIReflect();
  50.         }
  51.        
  52.         internal override IReflect InferType(JSField inference_target)
  53.         {
  54.             return this.ToIReflect();
  55.         }
  56.        
  57.         // has to be called after partially evaluate
  58.         internal bool IsCLSCompliant()
  59.         {
  60.             object value = this.expression.Evaluate();
  61.             return TypeExpression.TypeIsCLSCompliant(value);
  62.         }
  63.        
  64.         internal override AST PartiallyEvaluate()
  65.         {
  66.             if (this.recursive) {
  67.                 if (this.expression is ConstantWrapper)
  68.                     return this;
  69.                 this.expression = new ConstantWrapper(Typeob.Object, this.context);
  70.                 return this;
  71.             }
  72.             Member member = this.expression as Member;
  73.             if (member != null) {
  74.                 //Dealing with a qualified name. See if there is a type/class with such a name, bypassing normal scope lookup.
  75.                 object type = member.EvaluateAsType();
  76.                 if (type != null) {
  77.                     this.expression = new ConstantWrapper(type, member.context);
  78.                     return this;
  79.                 }
  80.             }
  81.             this.recursive = true;
  82.             this.expression = this.expression.PartiallyEvaluate();
  83.             this.recursive = false;
  84.             if (this.expression is TypeExpression)
  85.                 return this;
  86.             //Make sure that the expression represents a Type
  87.             Type t = null;
  88.             if (this.expression is ConstantWrapper) {
  89.                 object val = this.expression.Evaluate();
  90.                 if (val == null) {
  91.                     this.expression.context.HandleError(JSError.NeedType);
  92.                     this.expression = new ConstantWrapper(Typeob.Object, this.context);
  93.                     return this;
  94.                 }
  95.                 t = Globals.TypeRefs.ToReferenceContext(val.GetType());
  96.                 Binding.WarnIfObsolete(val as Type, this.expression.context);
  97.             }
  98.             else {
  99.                 if (this.expression.OkToUseAsType())
  100.                     t = Globals.TypeRefs.ToReferenceContext(this.expression.Evaluate().GetType());
  101.                 else {
  102.                     this.expression.context.HandleError(JSError.NeedCompileTimeConstant);
  103.                     this.expression = new ConstantWrapper(Typeob.Object, this.expression.context);
  104.                     return this;
  105.                 }
  106.             }
  107.             if (t == null || (t != Typeob.ClassScope && t != Typeob.TypedArray && !Typeob.Type.IsAssignableFrom(t))) {
  108.                 this.expression.context.HandleError(JSError.NeedType);
  109.                 this.expression = new ConstantWrapper(Typeob.Object, this.expression.context);
  110.             }
  111.             return this;
  112.         }
  113.        
  114.         internal IReflect ToIReflect()
  115.         {
  116.             if (!(this.expression is ConstantWrapper))
  117.                 this.PartiallyEvaluate();
  118.             IReflect result = this.cachedIR;
  119.             if (result != null)
  120.                 return result;
  121.             object value = this.expression.Evaluate();
  122.             if (value is ClassScope || value is TypedArray || this.context == null)
  123.                 result = (IReflect)value;
  124.             else
  125.                 result = Convert.ToIReflect((Type)value, this.Engine);
  126.             if (this.isArray)
  127.                 return this.cachedIR = new TypedArray(result, this.rank);
  128.             else
  129.                 return this.cachedIR = result;
  130.         }
  131.        
  132.         internal Type ToType()
  133.         {
  134.             if (!(this.expression is ConstantWrapper))
  135.                 this.PartiallyEvaluate();
  136.             object value = this.expression.Evaluate();
  137.             Type result = null;
  138.             if (value is ClassScope)
  139.                 result = ((ClassScope)value).GetTypeBuilderOrEnumBuilder();
  140.             else if (value is TypedArray)
  141.                 result = Convert.ToType((TypedArray)value);
  142.             else
  143.                 result = Globals.TypeRefs.ToReferenceContext((Type)value);
  144.             if (this.isArray) {
  145.                 return Convert.ToType(TypedArray.ToRankString(this.rank), result);
  146.             }
  147.             else
  148.                 return result;
  149.         }
  150.        
  151.         internal override void TranslateToIL(ILGenerator il, Type rtype)
  152.         {
  153.             this.expression.TranslateToIL(il, rtype);
  154.         }
  155.        
  156.         internal override void TranslateToILInitializer(ILGenerator il)
  157.         {
  158.             this.expression.TranslateToILInitializer(il);
  159.         }
  160.        
  161.         static internal bool TypeIsCLSCompliant(object type)
  162.         {
  163.             if (type is ClassScope)
  164.                 return ((ClassScope)type).IsCLSCompliant();
  165.             else if (type is TypedArray) {
  166.                 object et = ((TypedArray)type).elementType;
  167.                 if (et is TypedArray || (et is Type && ((Type)et).IsArray))
  168.                     return false;
  169.                 return TypeExpression.TypeIsCLSCompliant(et);
  170.             }
  171.             else {
  172.                 Type t = (Type)type;
  173.                 if (t.IsPrimitive)
  174.                     if (t == Typeob.Boolean || t == Typeob.Byte || t == Typeob.Char || t == Typeob.Double || t == Typeob.Int16 || t == Typeob.Int32 || t == Typeob.Int64 || t == Typeob.Single)
  175.                         return true;
  176.                     else
  177.                         return false;
  178.                 else {
  179.                     if (t.IsArray) {
  180.                         Type et = t.GetElementType();
  181.                         if (et.IsArray)
  182.                             return false;
  183.                         return TypeExpression.TypeIsCLSCompliant(t);
  184.                     }
  185.                     object[] attr = CustomAttribute.GetCustomAttributes(t, typeof(CLSCompliantAttribute), false);
  186.                     if (attr.Length > 0)
  187.                         return ((CLSCompliantAttribute)attr[0]).IsCompliant;
  188.                     else {
  189.                         Module m = t.Module;
  190.                         attr = CustomAttribute.GetCustomAttributes(m, typeof(CLSCompliantAttribute), false);
  191.                         if (attr.Length > 0)
  192.                             return ((CLSCompliantAttribute)attr[0]).IsCompliant;
  193.                         else {
  194.                             Assembly a = m.Assembly;
  195.                             attr = CustomAttribute.GetCustomAttributes(a, typeof(CLSCompliantAttribute), false);
  196.                             if (attr.Length > 0)
  197.                                 return ((CLSCompliantAttribute)attr[0]).IsCompliant;
  198.                             else
  199.                                 return false;
  200.                         }
  201.                     }
  202.                 }
  203.             }
  204.         }
  205.        
  206.     }
  207. }

Developer Fusion