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

  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.    
  23.     internal sealed class ClassScope : ActivationObject, IComparable
  24.     {
  25.         internal string name;
  26.         internal Type classwriter;
  27.         internal Class owner;
  28.         internal ConstructorInfo[] constructors;
  29.         internal bool noExpando;
  30.         internal PackageScope package;
  31.         internal JSProperty itemProp;
  32.         //Holds the expando property if present
  33.         internal FieldInfo outerClassField;
  34.         //Holds a reference to the outer class instance of a nested class instance
  35.         internal bool inStaticInitializerCode;
  36.         //Set this to true when partially evaluating the initializer of a static variable, false otherwise
  37.         internal bool staticInitializerUsesEval;
  38.         // True if a static member initializer calls eval and thus needs the scope setup
  39.         internal bool instanceInitializerUsesEval;
  40.         // True if in instance member initializer calls eval and thus needs the scope setup
  41.         internal ClassScope(AST name, GlobalScope scope) : base(scope)
  42.         {
  43.             //The parent must be set to a proper value before the class can be used.
  44.             this.name = name.ToString();
  45.             this.engine = scope.engine;
  46.             this.fast = scope.fast;
  47.             this.noExpando = true;
  48.             this.isKnownAtCompileTime = true;
  49.             this.owner = null;
  50.             //set by Class constructor
  51.             this.constructors = new JSConstructor[0];
  52.             ScriptObject enclosingScope = this.engine.ScriptObjectStackTop();
  53.             while (enclosingScope is WithObject)
  54.                 enclosingScope = enclosingScope.GetParent();
  55.             if (enclosingScope is ClassScope)
  56.                 this.package = ((ClassScope)enclosingScope).GetPackage();
  57.             else if (enclosingScope is PackageScope)
  58.                 this.package = (PackageScope)enclosingScope;
  59.             else
  60.                 this.package = null;
  61.             this.itemProp = null;
  62.             this.outerClassField = null;
  63.             this.inStaticInitializerCode = false;
  64.             this.staticInitializerUsesEval = false;
  65.             this.instanceInitializerUsesEval = false;
  66.         }
  67.        
  68.         internal void AddClassesFromInheritanceChain(string name, ArrayList result)
  69.         {
  70.             IReflect ir = this;
  71.             bool noMatch = true;
  72.             while (ir is ClassScope) {
  73.                 if (ir.GetMember(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly).Length > 0) {
  74.                     result.Add(ir);
  75.                     noMatch = false;
  76.                 }
  77.                 if (ir is ClassScope)
  78.                     ir = ((ClassScope)ir).GetSuperType();
  79.                 else
  80.                     ir = ((Type)ir).BaseType;
  81.             }
  82.             if (noMatch && ir is Type && ir.GetMember(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Length > 0)
  83.                 result.Add(ir);
  84.         }
  85.        
  86.         static internal ClassScope ScopeOfClassMemberInitializer(ScriptObject scope)
  87.         {
  88.             while (scope != null) {
  89.                 if (scope is FunctionScope)
  90.                     return null;
  91.                 ClassScope cscope = scope as ClassScope;
  92.                 if (cscope != null)
  93.                     return cscope;
  94.                 scope = scope.GetParent();
  95.             }
  96.             return null;
  97.         }
  98.        
  99.         //A class is always less than its superclass
  100.         public int CompareTo(object ob)
  101.         {
  102.             if (ob == this)
  103.                 return 0;
  104.             if (ob is ClassScope && ((ClassScope)ob).IsSameOrDerivedFrom(this))
  105.                 return 1;
  106.             return -1;
  107.         }
  108.        
  109.         protected override JSVariableField CreateField(string name, FieldAttributes attributeFlags, object value)
  110.         {
  111.             return new JSMemberField(this, name, value, attributeFlags);
  112.         }
  113.        
  114.         internal object FakeCallToTypeMethod(MethodInfo method, object[] arguments, Exception e)
  115.         {
  116.             ParameterInfo[] pars = method.GetParameters();
  117.             int n = pars.Length;
  118.             Type[] parTypes = new Type[n];
  119.             for (int i = 0; i < n; i++)
  120.                 parTypes[i] = pars[i].ParameterType;
  121.             MethodInfo fakeMethod = typeof(ClassScope).GetMethod(method.Name, parTypes);
  122.             if (fakeMethod != null)
  123.                 return fakeMethod.Invoke(this, arguments);
  124.             throw e;
  125.         }
  126.        
  127.         public object[] GetCustomAttributes(bool inherit)
  128.         {
  129.             CustomAttributeList caList = this.owner.customAttributes;
  130.             if (caList == null)
  131.                 return new object[0];
  132.             else
  133.                 return (object[])caList.Evaluate();
  134.         }
  135.        
  136.         public ConstructorInfo[] GetConstructors()
  137.         {
  138.             return this.constructors;
  139.         }
  140.        
  141.         public FieldInfo GetField(string name)
  142.         {
  143.             return this.GetField(name, BindingFlags.Public | BindingFlags.Instance);
  144.         }
  145.        
  146.         public MethodInfo GetMethod(string name)
  147.         {
  148.             return this.GetMethod(name, BindingFlags.Public | BindingFlags.Instance);
  149.         }
  150.        
  151.         public PropertyInfo GetProperty(string name)
  152.         {
  153.             return this.GetProperty(name, BindingFlags.Public | BindingFlags.Instance);
  154.         }
  155.        
  156.         internal override object GetDefaultValue(PreferredType preferred_type)
  157.         {
  158.             return this.GetFullName();
  159.         }
  160.        
  161.         internal override void GetPropertyEnumerator(ArrayList enums, ArrayList objects)
  162.         {
  163.         }
  164.        
  165.         internal string GetFullName()
  166.         {
  167.             PackageScope package = this.GetPackage();
  168.             if (package != null)
  169.                 return package.GetName() + "." + this.name;
  170.             else if (this.owner.enclosingScope is ClassScope)
  171.                 return ((ClassScope)this.owner.enclosingScope).GetFullName() + "." + this.name;
  172.             else
  173.                 return this.name;
  174.         }
  175.        
  176.         public override MemberInfo[] GetMember(string name, BindingFlags bindingAttr)
  177.         {
  178.             MemberInfoList mems = new MemberInfoList();
  179.             FieldInfo field = (FieldInfo)(this.name_table[name]);
  180.             if (field != null) {
  181.                 if (field.IsPublic) {
  182.                     if ((bindingAttr & BindingFlags.Public) == 0)
  183.                         goto parent;
  184.                 }
  185.                 else {
  186.                     if ((bindingAttr & BindingFlags.NonPublic) == 0)
  187.                         goto parent;
  188.                 }
  189.                 if (field.IsLiteral) {
  190.                     object val = ((JSMemberField)field).value;
  191.                     if (val is FunctionObject) {
  192.                         FunctionObject func = (FunctionObject)val;
  193.                         if (func.isConstructor)
  194.                             return new MemberInfo[0];
  195.                         //Suppress constructors, they are awkward to handle. The compiler always obtains them via GetConstructor
  196.                         if (func.isExpandoMethod) {
  197.                             if ((bindingAttr & BindingFlags.Instance) == 0)
  198.                                 goto parent;
  199.                             mems.Add(field);
  200.                         }
  201.                         else
  202.                             ((JSMemberField)field).AddOverloadedMembers(mems, this, bindingAttr | BindingFlags.DeclaredOnly);
  203.                         goto parent;
  204.                     }
  205.                     else if (val is JSProperty) {
  206.                         JSProperty prop = (JSProperty)val;
  207.                         MethodInfo getterOrSetter = prop.getter != null ? prop.getter : prop.setter;
  208.                         if (getterOrSetter.IsStatic) {
  209.                             if ((bindingAttr & BindingFlags.Static) == 0)
  210.                                 goto parent;
  211.                         }
  212.                         else {
  213.                             if ((bindingAttr & BindingFlags.Instance) == 0)
  214.                                 goto parent;
  215.                         }
  216.                         mems.Add(prop);
  217.                         goto parent;
  218.                     }
  219.                     else if (val is ClassScope) {
  220.                         if ((bindingAttr & BindingFlags.Instance) != 0) {
  221.                             if (!((ClassScope)val).owner.isStatic) {
  222.                                 mems.Add(field);
  223.                                 goto parent;
  224.                             }
  225.                         }
  226.                     }
  227.                 }
  228.                 if (field.IsStatic) {
  229.                     if ((bindingAttr & BindingFlags.Static) == 0)
  230.                         goto parent;
  231.                 }
  232.                 else {
  233.                     if ((bindingAttr & BindingFlags.Instance) == 0)
  234.                         goto parent;
  235.                 }
  236.                 mems.Add(field);
  237.             }
  238.             parent:
  239.             if (this.owner != null && this.owner.isInterface && ((bindingAttr & BindingFlags.DeclaredOnly) == 0))
  240.                 return this.owner.GetInterfaceMember(name);
  241.             if (this.parent != null && ((bindingAttr & BindingFlags.DeclaredOnly) == 0)) {
  242.                 //Add any members found on the superclass
  243.                 MemberInfo[] supMembers = this.parent.GetMember(name, bindingAttr);
  244.                 if (supMembers != null)
  245.                     foreach (MemberInfo mem in supMembers) {
  246.                         if (mem.MemberType == MemberTypes.Field) {
  247.                             field = (FieldInfo)mem;
  248.                             if (!field.IsStatic && !field.IsLiteral && !(field is JSWrappedField))
  249.                                 field = new JSWrappedField(field, this.parent);
  250.                             mems.Add(field);
  251.                         }
  252.                         else
  253.                             mems.Add(ScriptObject.WrapMember(mem, this.parent));
  254.                     }
  255.             }
  256.             return mems.ToArray();
  257.         }
  258.        
  259.         internal bool HasInstance(object ob)
  260.         {
  261.             if (!(ob is JSObject))
  262.                 return false;
  263.             ScriptObject parent = ((JSObject)ob).GetParent();
  264.             while (parent != null) {
  265.                 if (parent == this)
  266.                     return true;
  267.                 else if (parent is WithObject) {
  268.                     object wob = ((WithObject)parent).contained_object;
  269.                     if (wob == this)
  270.                         return true;
  271.                 }
  272.                 parent = parent.GetParent();
  273.             }
  274.             return false;
  275.         }
  276.        
  277.         internal JSMemberField[] GetMemberFields()
  278.         {
  279.             int n = this.field_table.Count;
  280.             JSMemberField[] result = new JSMemberField[n];
  281.             for (int i = 0; i < n; i++)
  282.                 result[i] = (JSMemberField)this.field_table[i];
  283.             return result;
  284.         }
  285.        
  286.         //Called when class is used as a base class. Need to give the same information as the type would, once this is compiled to IL.
  287.         //However, bindingAttr is ignored because this method is never legitimately called by something other than the compiler.
  288.         public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
  289.         {
  290.             MemberInfoList mems = new MemberInfoList();
  291.             IEnumerator enu = this.field_table.GetEnumerator();
  292.             while (enu.MoveNext()) {
  293.                 FieldInfo field = (FieldInfo)enu.Current;
  294.                 if (field.IsLiteral && field is JSMemberField) {
  295.                     object val = null;
  296.                     if ((val = ((JSMemberField)field).value) is FunctionObject) {
  297.                         if (((FunctionObject)val).isConstructor)
  298.                             continue;
  299.                         //Suppress constructors, they are awkward to handle. The compiler always obtains them via GetConstructor
  300.                         ((JSMemberField)field).AddOverloadedMembers(mems, this, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
  301.                     }
  302.                     else if (val is JSProperty) {
  303.                         mems.Add((MemberInfo)val);
  304.                     }
  305.                     else
  306.                         mems.Add(field);
  307.                 }
  308.                 else
  309.                     mems.Add(field);
  310.             }
  311.             if (this.parent != null)
  312.                 //Add any members found on the prototype
  313.                 mems.AddRange(this.parent.GetMembers(bindingAttr));
  314.             return mems.ToArray();
  315.         }
  316.        
  317.         internal override string GetName()
  318.         {
  319.             return this.name;
  320.         }
  321.        
  322.         internal Type GetBakedSuperType()
  323.         {
  324.             this.owner.PartiallyEvaluate();
  325.             if (this.owner is EnumDeclaration)
  326.                 return ((EnumDeclaration)this.owner).baseType.ToType();
  327.             object supertype = ((WithObject)this.parent).contained_object;
  328.             if (supertype is ClassScope)
  329.                 return ((ClassScope)supertype).GetBakedSuperType();
  330.             else if (supertype is Type)
  331.                 return (Type)supertype;
  332.             else
  333.                 return Globals.TypeRefs.ToReferenceContext(supertype.GetType());
  334.         }
  335.        
  336.         internal PackageScope GetPackage()
  337.         {
  338.             return this.package;
  339.         }
  340.        
  341.         internal IReflect GetSuperType()
  342.         {
  343.             this.owner.PartiallyEvaluate();
  344.             return (IReflect)((WithObject)this.parent).contained_object;
  345.         }
  346.        
  347.         internal Type GetTypeBuilderOrEnumBuilder()
  348.         {
  349.             if (this.classwriter == null)
  350.                 this.classwriter = this.owner.GetTypeBuilderOrEnumBuilder();
  351.             return this.classwriter;
  352.         }
  353.        
  354.         internal TypeBuilder GetTypeBuilder()
  355.         {
  356.             return (TypeBuilder)this.GetTypeBuilderOrEnumBuilder();
  357.         }
  358.        
  359.         internal IReflect GetUnderlyingTypeIfEnum()
  360.         {
  361.             if (this.owner is EnumDeclaration)
  362.                 return ((EnumDeclaration)this.owner.PartiallyEvaluate()).baseType.ToIReflect();
  363.             else
  364.                 return this;
  365.         }
  366.        
  367.         internal bool ImplementsInterface(IReflect iface)
  368.         {
  369.             this.owner.PartiallyEvaluate();
  370.             object supertype = ((WithObject)this.parent).contained_object;
  371.             if (supertype is ClassScope)
  372.                 return ((ClassScope)supertype).ImplementsInterface(iface) || this.owner.ImplementsInterface(iface);
  373.             else if (supertype is Type && iface is Type)
  374.                 return ((Type)iface).IsAssignableFrom((Type)supertype) || this.owner.ImplementsInterface(iface);
  375.             else
  376.                 return this.owner.ImplementsInterface(iface);
  377.         }
  378.        
  379.         internal bool IsCLSCompliant()
  380.         {
  381.             this.owner.PartiallyEvaluate();
  382.             TypeAttributes visibility = this.owner.attributes & TypeAttributes.VisibilityMask;
  383.             if (visibility != TypeAttributes.Public && visibility != TypeAttributes.NestedPublic)
  384.                 return false;
  385.             else if (this.owner.clsCompliance == CLSComplianceSpec.NotAttributed)
  386.                 return this.owner.Engine.isCLSCompliant;
  387.             else if (this.owner.clsCompliance == CLSComplianceSpec.CLSCompliant)
  388.                 return true;
  389.             else
  390.                 return false;
  391.         }
  392.        
  393.         internal bool IsNestedIn(ClassScope other, bool isStatic)
  394.         {
  395.             if (this.parent == null)
  396.                 return false;
  397.             this.owner.PartiallyEvaluate();
  398.             if (this.owner.enclosingScope == other)
  399.                 return isStatic || !this.owner.isStatic;
  400.             else if (this.owner.enclosingScope is ClassScope)
  401.                 return ((ClassScope)this.owner.enclosingScope).IsNestedIn(other, isStatic);
  402.             else
  403.                 return false;
  404.         }
  405.        
  406.         internal bool IsSameOrDerivedFrom(ClassScope other)
  407.         {
  408.             if (this == other)
  409.                 return true;
  410.             if (other.owner.isInterface)
  411.                 return this.ImplementsInterface(other);
  412.             if (this.parent == null)
  413.                 return false;
  414.             this.owner.PartiallyEvaluate();
  415.             object supertype = ((WithObject)this.parent).contained_object;
  416.             if (supertype is ClassScope)
  417.                 return ((ClassScope)supertype).IsSameOrDerivedFrom(other);
  418.             else
  419.                 return false;
  420.         }
  421.        
  422.         internal bool IsSameOrDerivedFrom(Type other)
  423.         {
  424.             if (this.owner.GetTypeBuilder() == other)
  425.                 return true;
  426.             if (this.parent == null)
  427.                 return false;
  428.             this.owner.PartiallyEvaluate();
  429.             object supertype = ((WithObject)this.parent).contained_object;
  430.             if (supertype is ClassScope)
  431.                 return ((ClassScope)supertype).IsSameOrDerivedFrom(other);
  432.             else
  433.                 return other.IsAssignableFrom((Type)supertype);
  434.         }
  435.        
  436.         internal bool IsPromotableTo(Type other)
  437.         {
  438.             Type st = this.GetBakedSuperType();
  439.             if (other.IsAssignableFrom(st))
  440.                 return true;
  441.             if (other.IsInterface && this.ImplementsInterface(other))
  442.                 return true;
  443.             EnumDeclaration ed = this.owner as EnumDeclaration;
  444.             if (ed != null && Convert.IsPromotableTo(ed.baseType.ToType(), other))
  445.                 return true;
  446.             return false;
  447.         }
  448.        
  449.         internal bool ParentIsInSamePackage()
  450.         {
  451.             object supertype = ((WithObject)this.parent).contained_object;
  452.             if (supertype is ClassScope)
  453.                 return ((ClassScope)supertype).package == this.package;
  454.             return false;
  455.         }
  456.     }
  457. }

Developer Fusion