public override void VisitTypeNodeList(TypeNodeList types) { if (types == null) { return; } for (int i = 0, n = types.Count; i < n; i++) { var type = types[i]; if (type == null) { continue; } Class c = type as Class; if (c != null && HelperMethods.IsContractTypeForSomeOtherType(c)) { types[i] = null; } else { // for nested types this.VisitTypeNode(type); } } }
public override TypeNodeList VisitTypeNodeList(TypeNodeList types) { if (types == null) { return(null); } for (int i = 0, n = types.Count; i < n; i++) { TypeNode type = types[i]; if (type == null) { continue; } if (this.Line != int.MinValue) { if (!type.SourceContext.Encloses(this.Line, this.Column)) { continue; } } else { if (!type.SourceContext.Encloses(this.SourceContext)) { continue; } } this.Visit(type); break; } return(types); }
public void PopulateTypeList(TypeNodeList types, NamespaceList namespaces) { if (types == null) { Debug.Assert(false); return; } for (int i = 0, n = namespaces == null ? 0 : namespaces.Length; i < n; i++) { Namespace ns = namespaces[i]; if (ns == null) { continue; } if (ns.NestedNamespaces != null) { this.PopulateTypeList(types, ns.NestedNamespaces); } TypeNodeList nTypes = ns.Types; for (int j = 0, m = nTypes == null ? 0 : nTypes.Length; j < m; j++) { TypeNode t = nTypes[j]; if (t == null) { continue; } this.PopulateTypeList(types, t); } } }
public static TypeNode findType(string nsName, Identifier typeName) { if (typeName == null) { return(null); } TypeNodeList ns; if (allNamespaces == null || nsCached == null) { init(); } if (!nsCached.TryGetValue(nsName, out ns)) { ns = findAll(nsName); } TypeNodeList types = nsCached[nsName]; for (int i = 0, n = types.Length; i < n; i++) { if (types[i].Name.Name == typeName.Name) { return(types[i]); } } return(null); }
private static void WriteMethod(Method method, TextWriter writer) { string name = method.Name.Name; WriteType(method.DeclaringType, writer); Method eiiMethod = null; if (method.IsPrivate && method.IsVirtual) { MethodList eiiMethods = method.ImplementedInterfaceMethods; if (eiiMethods.Count > 0) { eiiMethod = eiiMethods[0]; } } if (eiiMethod != null) //explicitly implemented interface { TypeNode eiiType = eiiMethod.DeclaringType; TextWriter eiiWriter = new StringWriter(); //we need to keep the param names instead of turning them into numbers //get the template to the right format if (eiiType != null && eiiType.Template != null) { writer.Write("."); WriteTemplate(eiiType, writer); } else //revert back to writing the type the old way if there is no template { WriteType(eiiType, eiiWriter); writer.Write("."); writer.Write(eiiWriter.ToString().Replace('.', '#')); } writer.Write("#"); writer.Write(eiiMethod.Name.Name); } else { writer.Write(".{0}", name); } if (method.IsGeneric) { TypeNodeList genericParameters = method.TemplateParameters; if (genericParameters != null) { writer.Write("``{0}", genericParameters.Count); } } WriteParameters(method.Parameters, writer); // add ~ for conversion operators if ((name == "op_Implicit") || (name == "op_Explicit")) { writer.Write("~"); WriteType(method.ReturnType, writer); } }
/// <summary> /// /// </summary> /// <param name="writer"></param> /// <param name="type">the current type being extended</param> /// <param name="extensionMethodTemplate">A reference to the extension method. For generic methods, this is a reference to the /// non-specialized method, e.g. System.Linq.Enumerable.Select``2. /// </param> /// <param name="specialization">When the current type implements or inherits from a specialization of a generic type, /// this parameter has a TypeNode for the type used as apecialization of the generic type's first template param. /// </param> private void AddExtensionMethod(XmlWriter writer, TypeNode type, Method extensionMethodTemplate, TypeNode specialization) { // If this is a specialization of a generic method, construct a Method object that describes the specialization Method extensionMethodTemplate2 = extensionMethodTemplate; if (extensionMethodTemplate2.IsGeneric && (specialization != null)) { // the specialization type is the first of the method's template arguments TypeNodeList templateArgs = new TypeNodeList(); templateArgs.Add(specialization); // add any additional template arguments for (int i = 1; i < extensionMethodTemplate.TemplateParameters.Count; i++) { templateArgs.Add(extensionMethodTemplate.TemplateParameters[i]); } extensionMethodTemplate2 = extensionMethodTemplate.GetTemplateInstance(type, templateArgs); } TypeNode extensionMethodTemplateReturnType = extensionMethodTemplate2.ReturnType; ParameterList extensionMethodTemplateParameters = extensionMethodTemplate2.Parameters; ParameterList extensionMethodParameters = new ParameterList(); for (int i = 1; i < extensionMethodTemplateParameters.Count; i++) { Parameter extensionMethodParameter = extensionMethodTemplateParameters[i]; extensionMethodParameters.Add(extensionMethodParameter); } Method extensionMethod = new Method(extensionMethodTemplate.DeclaringType, new AttributeList(), extensionMethodTemplate.Name, extensionMethodParameters, extensionMethodTemplate.ReturnType, null); extensionMethod.Flags = extensionMethodTemplate.Flags & ~MethodFlags.Static; // for generic methods, set the template args and params so the template data is included in the id and the method data if (extensionMethodTemplate2.IsGeneric) { extensionMethod.IsGeneric = true; if (specialization != null) { // set the template args for the specialized generic method extensionMethod.TemplateArguments = extensionMethodTemplate2.TemplateArguments; } else { // set the generic template params for the non-specialized generic method extensionMethod.TemplateParameters = extensionMethodTemplate2.TemplateParameters; } } // Get the id string extensionMethodTemplateId = reflector.ApiNamer.GetMemberName(extensionMethodTemplate); // write the element node writer.WriteStartElement("element"); writer.WriteAttributeString("api", extensionMethodTemplateId); writer.WriteAttributeString("source", "extension"); isExtensionMethod = true; reflector.WriteMember(extensionMethod); isExtensionMethod = false; writer.WriteEndElement(); }
private void StoreTypes(TypeNodeList types) { //Console.WriteLine("{0} types", types.Length); for (int i = 0; i < types.Count; i++) { StoreType(types[i]); } }
protected virtual void VisitNamespace(Namespace space) { //Console.WriteLine("Visit Entity {0}",space.FullName); VisitEntity(space); TypeNodeList types = space.Types; VisitTypes(types); }
public Specializer(Module targetModule, TypeNodeList pars, TypeNodeList args) { Debug.Assert(pars != null && pars.Count > 0); Debug.Assert(args != null && args.Count > 0); this.pars = pars; this.args = args; this.TargetModule = targetModule; }
public override void LookupAnonymousTypes(Identifier ns, TypeNodeList atypes) { // 21 June 2005 -- For now, remove functionality of finding anonyous members: too slow, // and not needed for now since we are not allowing general quantifiers in contracts // But keep commented code in case we want to go back to it. return; //SpecSharpCompilerOptions coptions = this.currentOptions as SpecSharpCompilerOptions; //if (coptions != null && coptions.Compatibility) return; //base.LookupAnonymousTypes(ns, atypes); }
private readonly TypeNode declaringType; // needed to copy anonymous delegates into public ReplaceResult(Method containingMethod, Local originalLocalForResult, Module assemblyBeingRewritten) { Contract.Requires(containingMethod != null); this.assemblyBeingRewritten = assemblyBeingRewritten; this.declaringType = containingMethod.DeclaringType; this.topLevelMethodFormals = containingMethod.TemplateParameters; this.originalLocalForResult = originalLocalForResult; this.delegateNestingLevel = 0; }
/// <summary> /// /// </summary> /// <param name="writer"></param> /// <param name="type">the current type being extended</param> /// <param name="extensionMethodTemplate">A reference to the extension method. For generic methods, this is a reference to the /// non-specialized method, e.g. System.Linq.Enumerable.Select``2. /// </param> /// <param name="specialization">When the current type implements or inherits from a specialization of a generic type, /// this parameter has a TypeNode for the type used as apecialization of the generic type's first template param. /// </param> private void AddExtensionMethod(XmlWriter writer, TypeNode type, Method extensionMethodTemplate, TypeNode specialization) { // If this is a specialization of a generic method, construct a Method object that describes the specialization Method extensionMethodTemplate2 = extensionMethodTemplate; if (extensionMethodTemplate2.IsGeneric && (specialization != null)) { // the specialization type is the first of the method's template arguments TypeNodeList templateArgs = new TypeNodeList(); templateArgs.Add(specialization); // add any additional template arguments for (int i = 1; i < extensionMethodTemplate.TemplateParameters.Count; i++) templateArgs.Add(extensionMethodTemplate.TemplateParameters[i]); extensionMethodTemplate2 = extensionMethodTemplate.GetTemplateInstance(type, templateArgs); } TypeNode extensionMethodTemplateReturnType = extensionMethodTemplate2.ReturnType; ParameterList extensionMethodTemplateParameters = extensionMethodTemplate2.Parameters; ParameterList extensionMethodParameters = new ParameterList(); for (int i = 1; i < extensionMethodTemplateParameters.Count; i++) { Parameter extensionMethodParameter = extensionMethodTemplateParameters[i]; extensionMethodParameters.Add(extensionMethodParameter); } Method extensionMethod = new Method(extensionMethodTemplate.DeclaringType, new AttributeList(), extensionMethodTemplate.Name, extensionMethodParameters, extensionMethodTemplate.ReturnType, null); extensionMethod.Flags = extensionMethodTemplate.Flags & ~MethodFlags.Static; // for generic methods, set the template args and params so the template data is included in the id and the method data if (extensionMethodTemplate2.IsGeneric) { extensionMethod.IsGeneric = true; if (specialization != null) { // set the template args for the specialized generic method extensionMethod.TemplateArguments = extensionMethodTemplate2.TemplateArguments; } else { // set the generic template params for the non-specialized generic method extensionMethod.TemplateParameters = extensionMethodTemplate2.TemplateParameters; } } // Get the id string extensionMethodTemplateId = reflector.ApiNamer.GetMemberName(extensionMethodTemplate); // write the element node writer.WriteStartElement("element"); writer.WriteAttributeString("api", extensionMethodTemplateId); writer.WriteAttributeString("source", "extension"); isExtensionMethod = true; reflector.WriteMember(extensionMethod); isExtensionMethod = false; writer.WriteEndElement(); }
private static bool IsSpecialized(TypeNode type) { for (TypeNode t = type; t != null; t = t.DeclaringType) { TypeNodeList templates = t.TemplateArguments; if ((templates != null) && (templates.Count > 0)) { return(true); } } return(false); }
public Checker(ErrorHandler errorHandler, TypeSystem typeSystem, TrivialHashtable scopeFor, TrivialHashtable ambiguousTypes, TrivialHashtable referencedLabels) : base(errorHandler) { this.typeSystem = typeSystem; this.Errors = errorHandler == null ? null : errorHandler.Errors; this.scopeFor = scopeFor; this.ambiguousTypes = ambiguousTypes; this.referencedLabels = referencedLabels; this.MayNotReferenceThisFromFieldInitializer = true; this.allowedExceptions = new TypeNodeList(); this.useGenerics = TargetPlatform.UseGenerics; this.AllowPropertiesIndexersAsRef = true; }
/// <summary> /// This is used to build the catalog of types in the parsed assemblies /// </summary> /// <param name="types">The list of types from an assembly</param> private void StoreTypes(TypeNodeList types) { for (int i = 0; i < types.Count; i++) { this.StoreType(types[i]); if (this.Canceled) { break; } } }
public override TypeNodeList VisitTypeNodeList(TypeNodeList types){ if (types == null) return null; for (int i = 0, n = types.Count; i < n; i++){ TypeNode type = types[i]; if (type == null) continue; if (this.Line != int.MinValue){ if (!type.SourceContext.Encloses(this.Line, this.Column)) continue; }else{ if (!type.SourceContext.Encloses(this.SourceContext)) continue; } this.Visit(type); break; } return types; }
internal static TypeNodeList GetTypeList(string typeList, IDebugContext context){ TypeNodeList list = new TypeNodeList(); int startIndex = typeList.LastIndexOf(".")+1; int endIndex; IDebugType typ; while((endIndex = typeList.IndexOf("Or", startIndex)) > 0){ typ = context.GetType(typeList.Substring(startIndex, endIndex - startIndex)); if (typ != null) list.Add(typ.CompilerType); startIndex = endIndex+2; } typ = context.GetType(typeList.Substring(startIndex)); if (typ != null) list.Add(typ.CompilerType); return list; }
/** <summary>Check for any exposed members in any of the types. * Returns true if the type has an exposed memeber filter and * it is matched. This is used to determine if the namespace * should be visited if the namespace and all types are set to * false for exposed, we still want to visit them if any members * are set to true. * </summary> */ private bool NamespaceContainsExposedMembers(Namespace space) { TypeNodeList types = space.Types; for (int i = 0; i < types.Count; i++) { TypeNode type = types[i]; if (HasExposedMembers(type)) { return(true); } } return(false); }
/// <summary> /// This is used to visit a list of types /// </summary> /// <param name="types">The list of types to visit</param> protected virtual void VisitTypes(TypeNodeList types) { // Visit the types in sorted order foreach (TypeNode type in types.OrderBy(t => t.FullName)) { if (filter.IsExposedType(type) || filter.HasExposedMembers(type)) { this.VisitType(type); } if (this.Canceled) { break; } } }
public void PopulateTypeList(TypeNodeList types, TypeNode t) { if (types == null || t == null) { Debug.Assert(false); return; } types.Add(t); MemberList members = t.Members; for (int i = 0, n = members == null ? 0 : members.Length; i < n; i++) { t = members[i] as TypeNode; if (t == null) { continue; } this.PopulateTypeList(types, t); } }
private static TypeNodeList CreateTemplateParameters(Class closureClass, Method @from, TypeNode declaringType) { var dup = new Duplicator(declaringType.DeclaringModule, declaringType); var templateParameters = new TypeNodeList(); var parentCount = declaringType.ConsolidatedTemplateParameters.CountOrDefault(); for (int i = 0; i < from.TemplateParameters.Count; i++) { var tp = HelperMethods.NewEqualTypeParameter( dup, (ITypeParameter)from.TemplateParameters[i], closureClass, parentCount + i); templateParameters.Add(tp); } return(templateParameters); }
protected virtual void VisitTypes(TypeNodeList types) { // sort types by name TypeNode[] sorted_types = new TypeNode[types.Count]; for (int i = 0; i < types.Count; i++) { sorted_types[i] = types[i]; } Array.Sort <TypeNode>(sorted_types, typeComparison); // visit them foreach (TypeNode type in sorted_types) { //Console.WriteLine("visiting {0}", type.Name); //visit this type if it is exposed, or has members that are set as exposed if (filter.IsExposedType(type) || filter.HasExposedMembers(type)) { VisitType(type); //visit type and members } } }
private bool?NamespaceContainesExposedTypes(Namespace space) { TypeNodeList types = space.Types; for (int i = 0; i < types.Count; i++) { TypeNode type = types[i]; if (IsExposedType(type)) { return(true); } } if (apiFilter.NamespaceFilterCount < 1) { return(null); //this apiFilter does not contain any namespaces } return(false); }
public override void VisitTypeNodeList(TypeNodeList types) { if (types == null) return; for (int i = 0, n = types.Count; i < n; i++) { var type = types[i]; if (type == null) continue; Class c = type as Class; if (c != null && HelperMethods.IsContractTypeForSomeOtherType(c)) { types[i] = null; } else { // for nested types this.VisitTypeNode(type); } } }
public override TypeNodeList VisitTypeParameterList(TypeNodeList typeParameters) { typeParameters = base.VisitTypeParameterList(typeParameters); for (int i = 0, n = typeParameters == null ? 0 : typeParameters.Count; i < n; i++) { TypeNode tp = typeParameters[i]; if (tp == null) { continue; } ClassParameter cp = tp as ClassParameter; if (cp != null) { if (cp.BaseClass == null) { cp.BaseClass = this.VisitTypeReference(cp.BaseClassExpression) as Class; } } typeParameters[i] = base.VisitTypeParameter(tp); } return(typeParameters); }
private static void WriteMethod(Method method, TextWriter writer) { string name = method.Name.Name; WriteType(method.DeclaringType, writer); writer.Write(".{0}", name); if (method.IsGeneric) { TypeNodeList genericParameters = method.TemplateParameters; if (genericParameters != null) { writer.Write("``{0}", genericParameters.Count); } } WriteParameters(method.Parameters, writer); // add ~ for conversion operators if ((name == "op_Implicit") || (name == "op_Explicit")) { writer.Write("~"); WriteType(method.ReturnType, writer); } }
//---------------------------------------------------------------------- private static TypeNodeList findAll(string name) { if (allNamespaces == null) { init(); } TypeNodeList nsl = new TypeNodeList(); nsCached.Add(name, nsl); for (int i = 0, n = allNamespaces.Length; i < n; i++) { if (allNamespaces[i].Name.Name == name) { Namespace ns = allNamespaces[i]; TypeNodeList tnls = ns.Types; for (int k = 0; k < tnls.Length; k++) { nsl.Add(tnls[k]); } } } return(nsl); }
public virtual TypeNodeList VisitTypeReferenceList(TypeNodeList typeReferences, TypeNodeList changes, TypeNodeList deletions, TypeNodeList insertions){ if (typeReferences == null) return changes; if (changes != null){ if (deletions == null || insertions == null) Debug.Assert(false); else{ } }else if (deletions != null) return null; return typeReferences; }
//===================================================================== /// <summary> /// This finds all extension methods, adds information about them to the types, and tracks /// them for adding to the reflection data later in the other callbacks. /// </summary> /// <param name="writer">The reflection data XML writer</param> /// <param name="info">For this callback, the information object is a namespace list</param> private void RecordExtensionMethods(XmlWriter writer, object info) { NamespaceList spaces = (NamespaceList)info; foreach (Namespace space in spaces) { // !EFW - Don't bother checking unexposed namespaces if (!mrw.ApiFilter.IsExposedNamespace(space)) { continue; } TypeNodeList types = space.Types; foreach (TypeNode type in types) { // !EFW - Don't bother checking unexposed types if (!mrw.ApiFilter.IsExposedType(type)) { continue; } // Go through the members looking for fields signaling extension methods. Members may be // added so convert to a list first to avoid enumeration issues. foreach (Member member in type.Members.ToList()) { Method method = member as Method; if (method == null || !mrw.ApiFilter.IsExposedMember(method) || !method.Attributes.Any(a => a.Type.FullName == "System.Runtime.CompilerServices.ExtensionAttribute")) { continue; } ParameterList parameters = method.Parameters; // !EFW - This fix was reported without an example. Sometimes, there are no parameters. // In such cases, ignore it to prevent a crash. if (parameters == null || parameters.Count == 0) { continue; } TypeNode extendedType = parameters[0].Type; // Recognize generic extension methods where the extended type is a specialization of a // generic type and the extended type's specialized template argument is a type parameter // declared by the generic extension method. In this case, we need to save a TypeNode // for the non-specialized type in the index because a TypeNode for the specialized type // won't match correctly in AddExtensionMethods(). NOTE: we are not interested in // extended types that are specialized by a specific type rather than by the extension // method's template parameter. if (method.IsGeneric && method.TemplateParameters.Count > 0) { if (extendedType.IsGeneric && extendedType.TemplateArguments != null && extendedType.TemplateArguments.Count == 1) { // Is the extended type's template argument a template parameter rather than a // specialized type? TypeNode arg = extendedType.TemplateArguments[0]; if (arg.IsTemplateParameter) { // Is the template parameter declared on the extension method ITypeParameter gtp = (ITypeParameter)arg; if (gtp.DeclaringMember == method && gtp.ParameterListIndex == 0) { // Get a TypeNode for the non-specialized type extendedType = extendedType.GetTemplateType(); } } } } List <Method> methods = null; if (!index.TryGetValue(extendedType, out methods)) { methods = new List <Method>(); index.Add(extendedType, methods); } methods.Add(method); } } } }
/// <summary> /// This is used to visit a list of types /// </summary> /// <param name="types">The list of types to visit</param> protected virtual void VisitTypes(TypeNodeList types) { // Visit the types in sorted order foreach(TypeNode type in types.OrderBy(t => t.FullName)) { if(filter.IsExposedType(type) || filter.HasExposedMembers(type)) this.VisitType(type); if(this.Canceled) break; } }
public EmitAsyncClosure(Method from, Rewriter rewriter) { Contract.Requires(from != null); Contract.Requires(from.DeclaringType != null); Contract.Requires(rewriter != null); if (TaskExtensionsTypeNode == null) { throw new InvalidOperationException( "Can't generate async closure because System.Threading.Tasks.TaskExceptions class is unavailable."); } this.rewriter = rewriter; this.declaringType = from.DeclaringType; var closureName = HelperMethods.NextUnusedMemberName(declaringType, "<" + from.Name.Name + ">AsyncContractClosure"); this.closureClass = new Class( declaringModule: declaringType.DeclaringModule, declaringType: declaringType, attributes: null, flags: TypeFlags.NestedPrivate, Namespace: null, name: Identifier.For(closureName), baseClass: SystemTypes.Object, interfaces: null, members: null); declaringType.Members.Add(this.closureClass); RewriteHelper.TryAddCompilerGeneratedAttribute(this.closureClass); var taskType = from.ReturnType; this.aggregateExceptionType = new Cache <TypeNode>(() => HelperMethods.FindType(rewriter.AssemblyBeingRewritten, StandardIds.System, Identifier.For("AggregateException"))); this.func2Type = new Cache <TypeNode>(() => HelperMethods.FindType(SystemTypes.SystemAssembly, StandardIds.System, Identifier.For("Func`2"))); if (from.IsGeneric) { this.closureClass.TemplateParameters = CreateTemplateParameters(closureClass, from, declaringType); this.closureClass.IsGeneric = true; this.closureClass.EnsureMangledName(); this.forwarder = new Specializer( targetModule: this.declaringType.DeclaringModule, pars: from.TemplateParameters, args: this.closureClass.TemplateParameters); this.forwarder.VisitTypeParameterList(this.closureClass.TemplateParameters); taskType = this.forwarder.VisitTypeReference(taskType); } else { this.closureClassInstance = this.closureClass; } this.checkMethodTaskType = taskType; // Emiting CheckPost method declaration EmitCheckPostMethodCore(checkMethodTaskType); // Generate closure constructor. // Constructor should be generated AFTER visiting type parameters in // the previous block of code. Otherwise current class would not have // appropriate number of generic arguments! var ctor = CreateConstructor(closureClass); closureClass.Members.Add(ctor); // Now that we added the ctor and the check method, let's instantiate the closure class if necessary if (this.closureClassInstance == null) { var consArgs = new TypeNodeList(); var args = new TypeNodeList(); var parentCount = this.closureClass.DeclaringType.ConsolidatedTemplateParameters == null ? 0 : this.closureClass.DeclaringType.ConsolidatedTemplateParameters.Count; for (int i = 0; i < parentCount; i++) { consArgs.Add(this.closureClass.DeclaringType.ConsolidatedTemplateParameters[i]); } var methodCount = from.TemplateParameters == null ? 0 : from.TemplateParameters.Count; for (int i = 0; i < methodCount; i++) { consArgs.Add(from.TemplateParameters[i]); args.Add(from.TemplateParameters[i]); } this.closureClassInstance = (Class) this.closureClass.GetConsolidatedTemplateInstance(this.rewriter.AssemblyBeingRewritten, closureClass.DeclaringType, closureClass.DeclaringType, args, consArgs); } // create closure initializer for context method this.closureLocal = new Local(this.ClosureClass); this.ClosureInitializer = new Block(new StatementList()); // TODO: What is this? // Add ClosureLocal instantiation? this.ClosureInitializer.Statements.Add( new AssignmentStatement( this.closureLocal, new Construct(new MemberBinding(null, this.Ctor), new ExpressionList()))); }
public virtual Differences VisitTypeNodeList(TypeNodeList list1, TypeNodeList list2, out TypeNodeList changes, out TypeNodeList deletions, out TypeNodeList insertions){ changes = list1 == null ? null : list1.Clone(); deletions = list1 == null ? null : list1.Clone(); insertions = list1 == null ? new TypeNodeList() : list1.Clone(); //^ assert insertions != null; Differences differences = new Differences(); //Compare definitions that have matching key attributes TrivialHashtable matchingPosFor = new TrivialHashtable(); TrivialHashtable matchedNodes = new TrivialHashtable(); for (int j = 0, n = list2 == null ? 0 : list2.Count; j < n; j++){ //^ assert list2 != null; TypeNode nd2 = list2[j]; if (nd2 == null || nd2.Name == null) continue; string fullName = nd2.FullName; if (fullName == null) continue; matchingPosFor[Identifier.For(fullName).UniqueIdKey] = j; insertions.Add(null); } for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; TypeNode nd1 = list1[i]; if (nd1 == null || nd1.Name == null) continue; string fullName = nd1.FullName; if (fullName == null) continue; object pos = matchingPosFor[Identifier.For(fullName).UniqueIdKey]; if (!(pos is int)) continue; //^ assert pos != null; //^ assume list2 != null; //since there was entry int matchingPosFor int j = (int)pos; TypeNode nd2 = list2[j]; //^ assume nd2 != null; //nd1 and nd2 have the same key attributes and are therefore treated as the same entity matchedNodes[nd1.UniqueKey] = nd1; matchedNodes[nd2.UniqueKey] = nd2; //nd1 and nd2 may still be different, though, so find out how different Differences diff = this.VisitTypeNode(nd1, nd2); if (diff == null){Debug.Assert(false); continue;} if (diff.NumberOfDifferences != 0){ changes[i] = diff.Changes as TypeNode; deletions[i] = diff.Deletions as TypeNode; insertions[i] = diff.Insertions as TypeNode; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation //Debug.Assert(diff.Changes == changes[i] && diff.Deletions == deletions[i] && diff.Insertions == insertions[i]); differences.NumberOfDifferences += diff.NumberOfDifferences; differences.NumberOfSimilarities += diff.NumberOfSimilarities; if (nd1.DeclaringModule == this.OriginalModule || (nd1.DeclaringType != null && nd1.DeclaringType.DeclaringModule == this.OriginalModule)){ if (this.MembersThatHaveChanged == null) this.MembersThatHaveChanged = new MemberList(); this.MembersThatHaveChanged.Add(nd1); } continue; } changes[i] = null; deletions[i] = null; insertions[i] = null; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation } //Find deletions for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; TypeNode nd1 = list1[i]; if (nd1 == null) continue; if (matchedNodes[nd1.UniqueKey] != null) continue; changes[i] = null; deletions[i] = nd1; insertions[i] = null; differences.NumberOfDifferences += 1; if (nd1.DeclaringModule == this.OriginalModule || (nd1.DeclaringType != null && nd1.DeclaringType.DeclaringModule == this.OriginalModule)){ if (this.MembersThatHaveChanged == null) this.MembersThatHaveChanged = new MemberList(); this.MembersThatHaveChanged.Add(nd1); } } //Find insertions for (int j = 0, n = list1 == null ? 0 : list1.Count, m = list2 == null ? 0 : list2.Count; j < m; j++){ //^ assert list2 != null; TypeNode nd2 = list2[j]; if (nd2 == null) continue; if (matchedNodes[nd2.UniqueKey] != null) continue; insertions[n+j] = nd2; //Records nd2 as an insertion into list1, along with its position in list2 differences.NumberOfDifferences += 1; //REVIEW: put the size of the tree here? } if (differences.NumberOfDifferences == 0){ changes = null; deletions = null; insertions = null; } return differences; }
public override TypeNodeList VisitTypeParameterList(TypeNodeList typeParameters) { typeParameters = base.VisitTypeParameterList(typeParameters); for (int i = 0, n = typeParameters == null ? 0 : typeParameters.Count; i < n; i++) { TypeNode tp = typeParameters[i]; if (tp == null) continue; ClassParameter cp = tp as ClassParameter; if (cp != null) { if (cp.BaseClass == null) cp.BaseClass = this.VisitTypeReference(cp.BaseClassExpression) as Class; } typeParameters[i] = base.VisitTypeParameter(tp); } return typeParameters; }
public virtual TypeNodeList VisitTypeNodeList(TypeNodeList types) { if (types == null) return null; for (int i = 0; i < types.Count; i++) //Visiting a type may result in a new type being appended to this list types[i] = (TypeNode)this.Visit(types[i]); return types; }
private static void TransformOriginalConsolidatedTypeFormalsIntoMethodFormals(Method dupMethod, Method closureMethod, Method closureInstanceMethod, out TypeNodeList actuals) { // make sure that if we copy it from a generic context, the method becomes generic in the target context // if we are copying from the same declaring type (not instantiated), then don't add enclosing type parameters. var originals = closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments == null ? null : closureMethod.DeclaringType.ConsolidatedTemplateParameters; if (originals != null) { originals = originals.Clone(); } if (closureMethod.TemplateParameters != null && closureMethod.TemplateParameters.Count > 0) { if (originals == null) { originals = closureMethod.TemplateParameters.Clone(); } else { foreach (var tp in closureMethod.TemplateParameters) { originals.Add(tp); } } } if (originals == null) { actuals = null; return; } actuals = closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments == null ? null : closureInstanceMethod.DeclaringType.ConsolidatedTemplateArguments.Clone(); if (closureInstanceMethod.TemplateArguments != null && closureInstanceMethod.TemplateArguments.Count > 0) { if (actuals == null) { actuals = closureInstanceMethod.TemplateArguments.Clone(); } else { foreach (var tp in closureInstanceMethod.TemplateArguments) { actuals.Add(tp); } } } var declaringModule = dupMethod.DeclaringType.DeclaringModule; // new method formals var tparams = originals.Clone(); for (int i = 0; i < originals.Count; i++) { // setup forwarding of tparams to method params ITypeParameter tp = originals[i] as ITypeParameter; TypeNode mtp = NewEqualMethodTypeParameter(tp, dupMethod, i); tparams[i] = mtp; } var specializer = new Specializer(declaringModule, originals, tparams); // System.Console.WriteLine("Made {0} a generic method", dupMethod.FullName); dupMethod.TemplateParameters = tparams; dupMethod.IsGeneric = true; specializer.VisitMethod(dupMethod); var bodySpecializer = new MethodBodySpecializer(declaringModule, originals, tparams); bodySpecializer.CurrentType = dupMethod.DeclaringType; bodySpecializer.CurrentMethod = dupMethod; bodySpecializer.VisitBlock(dupMethod.Body); }
public static bool IsNullOrEmpty(this TypeNodeList list) { return(list == null || list.Count == 0); }
// TODO: retire this method ater moving to C# 6.0 public static int CountOrDefault(this TypeNodeList list) { return(list == null ? 0 : list.Count); }
public virtual void VisitResolvedTypeReferenceList(TypeNodeList resolvedTypeList, TypeNodeList typeExpressionList){ if (resolvedTypeList == null || typeExpressionList == null) return; int n = resolvedTypeList.Count; if (n > typeExpressionList.Count){Debug.Assert(false); n = typeExpressionList.Count;} for (int i = 0; i < n; i++){ TypeNode resolvedType = resolvedTypeList[i]; if (resolvedType == null) continue; TypeNode reference = typeExpressionList[i]; if (reference == null) continue; this.VisitResolvedTypeReference(resolvedType, reference); } }
public override Expression VisitConstructArray(ConstructArray consArr){ if (consArr == null) return consArr; TypeNode et = consArr.ElementType = this.VisitTypeReference(consArr.ElementType); ExpressionList dims = consArr.Operands = this.VisitExpressionList(consArr.Operands); consArr.Initializers = this.VisitExpressionList(consArr.Initializers); if (et == null && consArr.ElementTypeExpression == null) { TypeNodeList tl = new TypeNodeList(); for (int i = 0, n = consArr.Initializers == null ? 0 : consArr.Initializers.Count; i < n; i++) { Expression e = consArr.Initializers[i]; if (e == null || e.Type == null) continue; Literal lit = e as Literal; if (lit != null && lit.Value == null) continue; //This prevents null from participating in the type unification, which is by design. if (e.Type == null) continue; //e is a bad expression tl.Add(e.Type); } et = this.typeSystem.UnifiedType(tl, this.TypeViewer); if (et == null) et = SystemTypes.Object; consArr.ElementType = et; } if (et is DelegateNode) { for (int i = 0, n = consArr.Initializers == null ? 0 : consArr.Initializers.Count; i < n; i++) { Expression e = consArr.Initializers[i]; if (e is MemberBinding && ((MemberBinding)e).BoundMember is Method) consArr.Initializers[i] = this.VisitExpression(new Construct(new MemberBinding(null, et), new ExpressionList(e))); } } consArr.Owner = this.VisitExpression(consArr.Owner); consArr.Type = SystemTypes.Object; if (et == null) return null; consArr.Type = et.GetArrayType(consArr.Rank); if (this.currentPreprocessorDefinedSymbols != null && this.NonNullChecking) consArr.Type = OptionalModifier.For(SystemTypes.NonNullType, consArr.Type); return consArr; }
/// <summary> /// If type has an explicit or implicit implementation of a method that has an out-of-band contract, /// then need to create a proxy that has the same signature as the "real" interface /// method and have it call the one the programmer wrote. /// </summary> /// <param name="type">The type whose members should be checked to find such methods.</param> public virtual void CheckForInterfaceImplementationsOfOutOfBandContractedMethods(TypeNode type) { MemberList members = this.GetTypeView(type).Members; // do we need to check all methods? for (int i = 0, n = members == null ? 0 : members.Count; i < n; i++) { Method method = members[i] as Method; if (method == null) continue; // If a method is a proxy (created in CheckAbstractMethods), then it can be ignored. ProxyMethod pMethod = method as ProxyMethod; if (pMethod != null) continue; #region Implicit implementation // If the method isn't virtual, then it will have been given a proxy as part of CheckAbstractMethods if (method.IsVirtual && method.ImplicitlyImplementedInterfaceMethods != null) { MethodList remainingImplicitImplementedInterfaceMethods = new MethodList(method.ImplicitlyImplementedInterfaceMethods.Count); for (int j = 0, m = method.ImplicitlyImplementedInterfaceMethods.Count; j < m; j++) { Method ifaceMethod = method.ImplicitlyImplementedInterfaceMethods[j]; if (ifaceMethod != null && ifaceMethod.HasOutOfBandContract) { this.CreateProxy(type, ifaceMethod, method); } else { remainingImplicitImplementedInterfaceMethods.Add(ifaceMethod); } } method.ImplicitlyImplementedInterfaceMethods = remainingImplicitImplementedInterfaceMethods; } #endregion Implicit implementation #region Explicit implementation if (method.ImplementedInterfaceMethods != null) { MethodList remainingImplementedInterfaceMethods = new MethodList(method.ImplementedInterfaceMethods.Count); TypeNodeList remainingImplementedTypes = new TypeNodeList(method.ImplementedTypes.Count); for (int j = 0, m = method.ImplementedInterfaceMethods.Count; j < m; j++) { Method ifaceMethod = method.ImplementedInterfaceMethods[j]; TypeNode ifaceType = method.ImplementedTypes[j]; if (ifaceMethod != null && ifaceMethod.HasOutOfBandContract) { this.CreateProxy(type, ifaceMethod, method); // We may need to modify the name if there is another method // in the type that has the same name. That is, method's name // was written by the programmer as I.f where I is the name of // the interface. But since it no longer implements the interface // (the proxy does instead), its name will be just "f" in the // assembly. If there is another method in the same type with // that name, the IL will be bad. So just to play it safe, make // the name "fully qualified", i.e., I.f. method.Name = new Identifier(ifaceMethod.FullName, method.Name.SourceContext); } else { remainingImplementedInterfaceMethods.Add(ifaceMethod); remainingImplementedTypes.Add(ifaceType); } } method.ImplementedInterfaceMethods = remainingImplementedInterfaceMethods; method.ImplementedTypes = remainingImplementedTypes; } #endregion Explicit implementation } }
public override TypeNode VisitTypeReference(TypeNode type) { //TODO: break up this method if (type == null) return null; TypeNodeList pars = this.pars; TypeNodeList args = this.args; switch (type.NodeType) { case NodeType.ArrayType: ArrayType arrType = (ArrayType)type; TypeNode elemType = this.VisitTypeReference(arrType.ElementType); if (elemType == arrType.ElementType || elemType == null) return arrType; if (arrType.IsSzArray()) return elemType.GetArrayType(1); return elemType.GetArrayType(arrType.Rank, arrType.Sizes, arrType.LowerBounds); case NodeType.DelegateNode: { FunctionType ftype = type as FunctionType; if (ftype == null) goto default; TypeNode referringType = ftype.DeclaringType == null ? this.CurrentType : this.VisitTypeReference(ftype.DeclaringType); return FunctionType.For(this.VisitTypeReference(ftype.ReturnType), this.VisitParameterList(ftype.Parameters), referringType); } case NodeType.Pointer: Pointer pType = (Pointer)type; elemType = this.VisitTypeReference(pType.ElementType); if (elemType == pType.ElementType || elemType == null) return pType; return elemType.GetPointerType(); case NodeType.Reference: Reference rType = (Reference)type; elemType = this.VisitTypeReference(rType.ElementType); if (elemType == rType.ElementType || elemType == null) return rType; return elemType.GetReferenceType(); case NodeType.ArrayTypeExpression: ArrayTypeExpression aExpr = (ArrayTypeExpression)type; aExpr.ElementType = this.VisitTypeReference(aExpr.ElementType); return aExpr; case NodeType.BoxedTypeExpression: BoxedTypeExpression bExpr = (BoxedTypeExpression)type; bExpr.ElementType = this.VisitTypeReference(bExpr.ElementType); return bExpr; case NodeType.ClassExpression: { ClassExpression cExpr = (ClassExpression)type; cExpr.Expression = this.VisitTypeExpression(cExpr.Expression); Literal lit = cExpr.Expression as Literal; //Could happen if the expression is a template parameter if (lit != null) return lit.Value as TypeNode; cExpr.TemplateArguments = this.VisitTypeReferenceList(cExpr.TemplateArguments); return cExpr; } case NodeType.ClassParameter: case NodeType.TypeParameter: int key = type.UniqueKey; for (int i = 0, n = pars == null ? 0 : pars.Count, m = args == null ? 0 : args.Count; i < n && i < m; i++) { //^ assert pars != null && args != null; TypeNode tp = pars[i]; if (tp == null) continue; if (tp.UniqueKey == key) return args[i]; if (tp.Name.UniqueIdKey == type.Name.UniqueIdKey && (tp is ClassParameter && type is TypeParameter)) { //This shouldn't really happen, but in practice it does. Hack past it. return args[i]; } } return type; case NodeType.FlexArrayTypeExpression: FlexArrayTypeExpression flExpr = (FlexArrayTypeExpression)type; flExpr.ElementType = this.VisitTypeReference(flExpr.ElementType); return flExpr; case NodeType.FunctionTypeExpression: FunctionTypeExpression ftExpr = (FunctionTypeExpression)type; ftExpr.Parameters = this.VisitParameterList(ftExpr.Parameters); ftExpr.ReturnType = this.VisitTypeReference(ftExpr.ReturnType); return ftExpr; case NodeType.InvariantTypeExpression: InvariantTypeExpression invExpr = (InvariantTypeExpression)type; invExpr.ElementType = this.VisitTypeReference(invExpr.ElementType); return invExpr; case NodeType.InterfaceExpression: InterfaceExpression iExpr = (InterfaceExpression)type; if (iExpr.Expression == null) goto default; iExpr.Expression = this.VisitTypeExpression(iExpr.Expression); iExpr.TemplateArguments = this.VisitTypeReferenceList(iExpr.TemplateArguments); return iExpr; case NodeType.NonEmptyStreamTypeExpression: NonEmptyStreamTypeExpression neExpr = (NonEmptyStreamTypeExpression)type; neExpr.ElementType = this.VisitTypeReference(neExpr.ElementType); return neExpr; case NodeType.NonNullTypeExpression: NonNullTypeExpression nnExpr = (NonNullTypeExpression)type; nnExpr.ElementType = this.VisitTypeReference(nnExpr.ElementType); return nnExpr; case NodeType.NonNullableTypeExpression: NonNullableTypeExpression nbExpr = (NonNullableTypeExpression)type; nbExpr.ElementType = this.VisitTypeReference(nbExpr.ElementType); return nbExpr; case NodeType.NullableTypeExpression: NullableTypeExpression nuExpr = (NullableTypeExpression)type; nuExpr.ElementType = this.VisitTypeReference(nuExpr.ElementType); return nuExpr; case NodeType.OptionalModifier: { TypeModifier modType = (TypeModifier)type; TypeNode modifiedType = this.VisitTypeReference(modType.ModifiedType); TypeNode modifierType = this.VisitTypeReference(modType.Modifier); if (modifiedType == null || modifierType == null) { return type; } return OptionalModifier.For(modifierType, modifiedType); } case NodeType.RequiredModifier: { TypeModifier modType = (TypeModifier)type; TypeNode modifiedType = this.VisitTypeReference(modType.ModifiedType); TypeNode modifierType = this.VisitTypeReference(modType.Modifier); if (modifiedType == null || modifierType == null) { Debug.Fail(""); return type; } return RequiredModifier.For(modifierType, modifiedType); } case NodeType.OptionalModifierTypeExpression: OptionalModifierTypeExpression optmodType = (OptionalModifierTypeExpression)type; optmodType.ModifiedType = this.VisitTypeReference(optmodType.ModifiedType); optmodType.Modifier = this.VisitTypeReference(optmodType.Modifier); return optmodType; case NodeType.RequiredModifierTypeExpression: RequiredModifierTypeExpression reqmodType = (RequiredModifierTypeExpression)type; reqmodType.ModifiedType = this.VisitTypeReference(reqmodType.ModifiedType); reqmodType.Modifier = this.VisitTypeReference(reqmodType.Modifier); return reqmodType; case NodeType.PointerTypeExpression: PointerTypeExpression pExpr = (PointerTypeExpression)type; pExpr.ElementType = this.VisitTypeReference(pExpr.ElementType); return pExpr; case NodeType.ReferenceTypeExpression: ReferenceTypeExpression rExpr = (ReferenceTypeExpression)type; rExpr.ElementType = this.VisitTypeReference(rExpr.ElementType); return rExpr; case NodeType.StreamTypeExpression: StreamTypeExpression sExpr = (StreamTypeExpression)type; sExpr.ElementType = this.VisitTypeReference(sExpr.ElementType); return sExpr; case NodeType.TupleTypeExpression: TupleTypeExpression tuExpr = (TupleTypeExpression)type; tuExpr.Domains = this.VisitFieldList(tuExpr.Domains); return tuExpr; case NodeType.TypeExpression: { TypeExpression tExpr = (TypeExpression)type; tExpr.Expression = this.VisitTypeExpression(tExpr.Expression); if (tExpr.Expression is Literal) return type; tExpr.TemplateArguments = this.VisitTypeReferenceList(tExpr.TemplateArguments); return tExpr; } case NodeType.TypeIntersectionExpression: TypeIntersectionExpression tiExpr = (TypeIntersectionExpression)type; tiExpr.Types = this.VisitTypeReferenceList(tiExpr.Types); return tiExpr; case NodeType.TypeUnionExpression: TypeUnionExpression tyuExpr = (TypeUnionExpression)type; tyuExpr.Types = this.VisitTypeReferenceList(tyuExpr.Types); return tyuExpr; default: TypeNode declaringType = this.VisitTypeReference(type.DeclaringType); if (declaringType != null) { Identifier tname = type.Name; if (type.Template != null && type.IsGeneric) tname = type.Template.Name; TypeNode nt = declaringType.GetNestedType(tname); if (nt != null) { TypeNodeList arguments = type.TemplateArguments; type = nt; if (TargetPlatform.UseGenerics) { if (arguments != null && arguments.Count > 0 && nt.ConsolidatedTemplateParameters != null && nt.ConsolidatedTemplateParameters.Count > 0) type = nt.GetTemplateInstance(this.TargetModule, this.CurrentType, declaringType, arguments); } } } if(type.Template != null && (type.ConsolidatedTemplateParameters == null || type.ConsolidatedTemplateParameters.Count == 0)) { if(!type.IsNotFullySpecialized && (!type.IsNormalized || (this.CurrentType != null && type.DeclaringModule == this.CurrentType.DeclaringModule))) { return type; } // Type is a template instance, but some of its arguments were themselves parameters. // See if any of these parameters are to be specialized by this specializer. bool mustSpecializeFurther = false; TypeNodeList targs = type.TemplateArguments; int numArgs = targs == null ? 0 : targs.Count; if(targs != null) { targs = new TypeNodeList(targs); for(int i = 0; i < numArgs; i++) { TypeNode targ = targs[i]; ITypeParameter tparg = targ as ITypeParameter; if(tparg != null) { for(int j = 0, np = pars == null ? 0 : pars.Count, m = args == null ? 0 : args.Count; j < np && j < m; j++) { //^ assert pars != null && args != null; if(TargetPlatform.UseGenerics) { ITypeParameter par = pars[j] as ITypeParameter; if(par == null) continue; if(tparg == par || (tparg.ParameterListIndex == par.ParameterListIndex && tparg.DeclaringMember == par.DeclaringMember)) { targ = this.args[j]; break; } } else { if(targ == pars[j]) { targ = this.args[j]; break; } } } } else { if(targ != type) targ = this.VisitTypeReference(targ); if(targ == type) continue; } mustSpecializeFurther |= targs[i] != targ; targs[i] = targ; } } if(targs == null || !mustSpecializeFurther) return type; return type.Template.GetTemplateInstance(this.TargetModule, this.CurrentType, declaringType, targs); } TypeNodeList tPars = type.TemplateParameters; if (tPars == null || tPars.Count == 0) return type; //Not a parameterized type. No need to get an instance. TypeNodeList tArgs = new TypeNodeList(); for (int i = 0, n = tPars.Count; i < n; i++) { TypeNode tPar = tPars[i]; tArgs.Add(tPar); //Leave parameter in place if there is no match if (tPar == null || tPar.Name == null) continue; int idKey = tPar.Name.UniqueIdKey; for (int j = 0, m = pars == null ? 0 : pars.Count, k = args == null ? 0 : args.Count; j < m && j < k; j++) { //^ assert pars != null && args != null; TypeNode par = pars[j]; if (par == null || par.Name == null) continue; if (par.Name.UniqueIdKey == idKey) { tArgs[i] = args[j]; break; } } } return type.GetTemplateInstance(this.TargetModule, this.CurrentType, this.VisitTypeReference(type.DeclaringType), tArgs); } }
public virtual TypeNodeList VisitTypeParameterList(TypeNodeList typeParameters) { if (typeParameters == null) return null; for (int i = 0, n = typeParameters.Count; i < n; i++) typeParameters[i] = this.VisitTypeParameter(typeParameters[i]); return typeParameters; }
public override Method VisitMethod(Method method) { if (method == null) return null; if (method.IsNormalized) return method; this.MayReferenceThisAndBase = !(method is InstanceInitializer) || method.DeclaringType == null || method.DeclaringType.IsValueType; if (method.Name != null && method.Name.UniqueIdKey == StandardIds.Finalize.UniqueIdKey && method.HasCompilerGeneratedSignature && method.DeclaringType is Class && ((Class)method.DeclaringType).IsAbstractSealedContainerForStatics) this.HandleError(method.Name, Error.DestructorInAbstractSealedClass); method.Attributes = this.VisitAttributeList(method.Attributes, method); method.ReturnAttributes = this.VisitAttributeList(method.ReturnAttributes); method.SecurityAttributes = this.VisitSecurityAttributeList(method.SecurityAttributes); if ((method.ReturnType == SystemTypes.DynamicallyTypedReference || method.ReturnType == SystemTypes.ArgIterator) && (this.currentOptions == null || !this.currentOptions.NoStandardLibrary) ) { this.HandleError(method.Name, Error.CannotReturnTypedReference, this.GetTypeName(method.ReturnType)); method.ReturnType = SystemTypes.Object; } if (method.Body != null) { if (method.DeclaringType is Interface && !method.IsStatic) { this.HandleError(method.Name, Error.InterfaceMemberHasBody, this.GetMethodSignature(method)); method.Body = null; } else if (method.IsAbstract) { this.HandleError(method.Name, Error.AbstractHasBody, this.GetMethodSignature(method)); method.Body = null; } } else if (!method.IsAbstract && !method.IsExtern && !this.isCompilingAContractAssembly) { this.HandleError(method.Name, Error.ConcreteMissingBody, this.GetMethodSignature(method)); return null; } else if (method.TemplateParameters != null && method.TemplateParameters.Count > 0 && !this.useGenerics) { SourceContext ctx = method.TemplateParameters[0].SourceContext; ctx.EndPos = method.TemplateParameters[method.TemplateParameters.Count-1].SourceContext.EndPos; Debug.Assert(ctx.EndPos >= ctx.StartPos); Node n = new UnaryExpression(); n.SourceContext = ctx; if (method.DeclaringType is Interface) this.HandleError(n, Error.AbstractInterfaceMethod); else this.HandleError(n, Error.AbstractMethodTemplate); return null; } BlockScope savedCurrentFinallyClause = this.currentFinallyClause; Method savedCurrentMethod = this.currentMethod; Return savedReturnNode = this.returnNode; Yield savedYieldNode = this.yieldNode; this.currentFinallyClause = null; this.currentMethod = method; this.returnNode = null; this.yieldNode = null; MethodScope scope = method.Scope; this.CheckForDuplicateDeclarations(scope); if ((this.currentPreprocessorDefinedSymbols != null && this.currentPreprocessorDefinedSymbols.ContainsKey("DefaultExposeBlocks")) && !method.IsStatic && !(method is InstanceInitializer) && method.DeclaringType is Class && !method.IsAbstract && method.CciKind == CciMemberKind.Regular && method.ApplyDefaultContract) { This thisOb = method.ThisParameter; MethodCall thisIsExposable = new MethodCall( new MemberBinding(null, SystemTypes.Guard.GetMethod(Identifier.For("FrameIsExposable"), SystemTypes.Object, SystemTypes.Type)), new ExpressionList(thisOb, new UnaryExpression(new Literal(method.DeclaringType, SystemTypes.Type), NodeType.Typeof, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Type))), NodeType.Call, SystemTypes.Boolean, method.Body.SourceContext); Assumption assumption = new Assumption(thisIsExposable); Expose expose = new Expose(NodeType.Write); expose.SourceContext = method.Body.SourceContext; expose.Instance = thisOb; expose.Body = method.Body; if (this.currentOptions != null && this.currentOptions.DisableGuardedClassesChecks) method.Body = new Block(new StatementList(assumption, expose)); else method.Body = new Block(new StatementList(expose)); } #region Check contract rules for all interface methods and base methods this method implements/overrides bool ok = true; if (method.IsVirtual && !method.IsCompilerControlled) { // use FindNearest..., can't rely on method.OverriddenMethod since it might not be set further up the chain Method overridden = method.DeclaringType.FindNearestOverriddenMethod(method); if (overridden != null) { ok &= this.CheckContractRules(overridden, method, method.DeclaringType); } for (int i = 0, n = method.ImplementedInterfaceMethods == null ? 0 : method.ImplementedInterfaceMethods.Count; i < n; i++) { Method ifaceMethod = method.ImplementedInterfaceMethods[i]; ok &= this.CheckContractRules(ifaceMethod, method, method.DeclaringType); } for (int i = 0, n = method.ImplicitlyImplementedInterfaceMethods == null ? 0 : method.ImplicitlyImplementedInterfaceMethods.Count; i < n; i++) { Method ifaceMethod = method.ImplicitlyImplementedInterfaceMethods[i]; ok &= this.CheckContractRules(ifaceMethod, method, method.DeclaringType); } } #endregion #region Contract Inheritance for method overrides and interface implementations (do this somewhere else?) // This needs to be done here (and not in VisitMethodContract) because method might not even have a contract if (method.IsVirtual && ok && !method.IsCompilerControlled) { // use FindNearest..., can't rely on method.OverriddenMethod since it might not be set further up the chain Method overridden = method.DeclaringType.FindNearestOverriddenMethod(method); // FindNearestOverriddenMethod doesn't care if method is "new" or an "override", so explicity test IsVirtual property MethodContract cumulativeContract = method.Contract == null ? new MethodContract(method) : method.Contract; bool somethingWasCopied = false; while (overridden != null && overridden.IsVirtual) { if (overridden.Contract != null) { cumulativeContract.CopyFrom(overridden.Contract); somethingWasCopied = true; break; } overridden = overridden.DeclaringType.FindNearestOverriddenMethod(overridden); } // Can inherit from at most one interface method bool ifaceContractWasCopied = false; for (int i = 0, n = method.ImplementedInterfaceMethods == null ? 0 : method.ImplementedInterfaceMethods.Count; i < n; i++) { Method ifaceMethod = method.ImplementedInterfaceMethods[i]; if (ifaceMethod == null) continue; if (ifaceMethod.Contract != null) { if (ifaceContractWasCopied) { this.HandleError(method, Error.RequiresNotAllowedInInterfaceImplementation, this.GetMethodSignature(ifaceMethod)); break; } cumulativeContract.CopyFrom(ifaceMethod.Contract); somethingWasCopied = true; ifaceContractWasCopied = true; } } for (int i = 0, n = method.ImplicitlyImplementedInterfaceMethods == null ? 0 : method.ImplicitlyImplementedInterfaceMethods.Count; i < n; i++) { Method ifaceMethod = method.ImplicitlyImplementedInterfaceMethods[i]; if (ifaceMethod == null) continue; if (ifaceMethod.Contract != null) { if (ifaceContractWasCopied) { this.HandleError(method, Error.RequiresNotAllowedInInterfaceImplementation, this.GetMethodSignature(ifaceMethod)); break; } cumulativeContract.CopyFrom(ifaceMethod.Contract); somethingWasCopied = true; ifaceContractWasCopied = true; } } if (method.Contract == null && somethingWasCopied) { // otherwise it was already copied into the method's contract method.Contract = cumulativeContract; } } #endregion // For checked exceptions, the actual exceptions thrown must be a subset of the allowed exceptions TypeNodeList aes = new TypeNodeList(); if (method.Contract != null && method.Contract.Ensures != null) { for (int i = 0, n = method.Contract.Ensures.Count; i < n; i++) { EnsuresExceptional ee = method.Contract.Ensures[i] as EnsuresExceptional; if (ee == null || ee.Inherited) continue; aes.Add(ee.Type); } } TypeNodeList saveAllowedExceptions = this.allowedExceptions; this.allowedExceptions = aes; // don't check method body of proxy methods. Method result = (method is ProxyMethod) ? method : base.VisitMethod(method); this.allowedExceptions = saveAllowedExceptions; if (this.yieldNode != null && TypeNode.StripModifiers(method.ReturnType) is Interface) { StatementList statements = new StatementList(1); TypeNode elementType = SystemTypes.Object; Interface stype = (Interface)TypeNode.StripModifiers(method.ReturnType); if (stype.TemplateArguments != null && stype.TemplateArguments.Count == 1) elementType = stype.TemplateArguments[0]; Class state = scope.ClosureClass; elementType = scope.FixTypeReference(elementType); state.Flags |= TypeFlags.Abstract; //So that no complaints are given about missing methods added by Normalizer state.Interfaces = new InterfaceList(5); state.Interfaces.Add(SystemTypes.IEnumerable); state.Interfaces.Add((Interface)SystemTypes.GenericIEnumerator.GetTemplateInstance(this.currentType, elementType)); state.Interfaces.Add(SystemTypes.IEnumerator); state.Interfaces.Add(SystemTypes.IDisposable); state.Interfaces.Add((Interface)SystemTypes.GenericIEnumerable.GetTemplateInstance(this.currentType, elementType)); //Add these methods so that Normalizer can find them even when reference to iterator is forward Method moveNext = new Method(state, null, StandardIds.MoveNext, null, SystemTypes.Boolean, null); moveNext.CallingConvention = CallingConventionFlags.HasThis; moveNext.Flags = MethodFlags.Public|MethodFlags.Virtual; moveNext.Body = new Block(new StatementList()); state.Members.Add(moveNext); Method getCurrent = new Method(state, null, StandardIds.getCurrent, null, elementType, null); getCurrent.CallingConvention = CallingConventionFlags.HasThis; getCurrent.Flags = MethodFlags.Public|MethodFlags.Virtual|MethodFlags.SpecialName; getCurrent.Body = new Block(new StatementList()); state.Members.Add(getCurrent); Return ret = new Return(new ConstructIterator(state, method.Body, elementType, state)); if (method.Name.SourceContext.Document != null) { ret.SourceContext = method.SourceContext; ret.SourceContext.EndPos = method.Name.SourceContext.EndPos; Debug.Assert(ret.SourceContext.EndPos >= ret.SourceContext.StartPos); } statements.Add(ret); method.Body = new Block(statements); method.Body.Scope = new BlockScope(scope, method.Body); } if (method.IsStatic && method.IsVirtual && !method.IsSpecialName) { method.Flags &= ~MethodFlags.Static; this.HandleError(method.Name, Error.StaticNotVirtual, this.GetMethodSignature(method)); } if (!method.OverridesBaseClassMember) { if (method.NodeType == NodeType.InstanceInitializer || !method.IsSpecialName) { if (!(method.DeclaringType is Interface) && !(method.DeclaringType is DelegateNode)) { if (this.IsLessAccessible(method.ReturnType, method)) { this.HandleError(method.Name, Error.ReturnTypeLessAccessibleThanMethod, this.GetTypeName(method.ReturnType), this.GetMethodSignature(method)); this.HandleRelatedError(method.ReturnType); } this.CheckParameterTypeAccessibility(method.Parameters, method); } } else { if (method.Name != null && Checker.OperatorName[method.Name.UniqueIdKey] != null) { if (this.IsLessAccessible(method.ReturnType, method)) { this.HandleError(method.Name, Error.ReturnTypeLessAccessibleThanOperator, this.GetTypeName(method.ReturnType), this.GetMethodSignature(method)); this.HandleRelatedError(method.ReturnType); } this.CheckParameterTypeAccessibility(method.Parameters, method); } } } if (!method.IsSpecialName) { TypeNodeList implementedTypes = method.ImplementedTypes; if (implementedTypes != null) { InterfaceList declaringTypeInterfaces = this.GetTypeView(method.DeclaringType).Interfaces; for (int i = 0, n = implementedTypes.Count; i < n; i++) { Interface iface = implementedTypes[i] as Interface; if (iface == null) continue; if (!this.IsAllowedAsImplementedType(declaringTypeInterfaces, iface)) { Node offendingNode = method.ImplementedTypeExpressions[i]; this.HandleError(offendingNode, Error.ContainingTypeDoesNotImplement, this.GetMethodSignature(method), this.GetTypeName(iface)); this.HandleRelatedError(iface); implementedTypes = null; break; } } } MethodList implementedMethods = method.ImplementedInterfaceMethods; for (int i = 0, n = implementedTypes == null ? 0 : implementedTypes.Count; i < n; i++) { Interface iface = implementedTypes[i] as Interface; if (iface == null) continue; Method m = implementedMethods == null ? null : implementedMethods[i]; if (m == null) { this.HandleError(method.Name, Error.InterfaceMemberNotFound, this.GetMemberSignature(method), this.GetTypeName(iface)); this.HandleRelatedError(iface); } else if (m.IsSpecialName) this.HandleError(method.Name, Error.CannotExplicitlyImplementAccessor, this.GetMethodSignature(method), this.GetMethodSignature(m)); } } if ((method.Flags & MethodFlags.PInvokeImpl) != 0) { Error e = Error.None; if (this.shadowedAssembly != null) { // Make sure this method has a counterpart in the shadowed method TypeNode type = this.GetCorrespondingShadowedTypeNode(method.DeclaringType); if (type == null) { this.HandleError(method.DeclaringType, Error.TypeMissingInShadowedAssembly, this.GetTypeName(method.DeclaringType)); } else { int numParams = method.Parameters == null ? 0 : method.Parameters.Count; TypeNode[] types = new TypeNode[numParams]; for (int i = 0; i < numParams; i++) { types[i] = this.GetCorrespondingShadowedTypeNode(TypeNode.StripModifiers(method.Parameters[i].Type)); } if (this.GetTypeView(type).GetMethod(method.Name, types) == null) { this.HandleError(method, Error.MethodMissingInShadowedAssembly, this.GetMethodSignature(method)); } } } else if (this.isCompilingAContractAssembly) e = Error.None; else if (method.Body != null) e = Error.PInvokeHasBody; else if (method.IsAbstract) e = Error.AbstractAndExtern; else if (method.PInvokeImportName == null || method.PInvokeModule == null) { if (method.Attributes == null || method.Attributes.Count == 0) e = Error.PInvokeWithoutModuleOrImportName; else method.Flags &= ~MethodFlags.PInvokeImpl; } if (e != Error.None) this.HandleError(method.Name, e, this.GetMethodSignature(method)); } if (method.IsPropertySetter && (method.IsPure || method.IsConfined || method.IsStateIndependent)) { this.HandleError(method, Error.MemberCannotBeAnnotatedAsPure, this.GetMethodSignature(method)); } this.currentFinallyClause = savedCurrentFinallyClause; this.currentMethod = savedCurrentMethod; this.returnNode = savedReturnNode; this.yieldNode = savedYieldNode; return result; }
public virtual TypeNodeList VisitTypeReferenceList(TypeNodeList typeReferences) { if (typeReferences == null) return null; for (int i = 0, n = typeReferences.Count; i < n; i++) typeReferences[i] = this.VisitTypeReference(typeReferences[i]); return typeReferences; }
private static TypeNodeList DuplicateTypeParameterList(TypeNodeList typeParameters, int offsetIndex, TypeNode declaringType) { if (typeParameters == null) return null; Duplicator dup = new Duplicator(declaringType.DeclaringModule, null); dup.FindTypesToBeDuplicated(typeParameters); TypeNodeList result = dup.VisitTypeParameterList(typeParameters); for (int i = 0; i < result.Count; i++) { TypeNode tn = result[i]; tn.DeclaringType = declaringType; tn.DeclaringModule = declaringType.DeclaringModule; ITypeParameter tp = (ITypeParameter) tn; tp.ParameterListIndex = offsetIndex + i; tp.DeclaringMember = declaringType; } return result; }
public MyMethodBodySpecializer(Module module, TypeNodeList source, TypeNodeList target) : base(module, source, target) { }
public override void LookupAnonymousTypes(Identifier ns, TypeNodeList atypes){ // 21 June 2005 -- For now, remove functionality of finding anonyous members: too slow, // and not needed for now since we are not allowing general quantifiers in contracts // But keep commented code in case we want to go back to it. return; //SpecSharpCompilerOptions coptions = this.currentOptions as SpecSharpCompilerOptions; //if (coptions != null && coptions.Compatibility) return; //base.LookupAnonymousTypes(ns, atypes); }
private static MapClosureExpressionToOriginalExpression BuildMappingFromClosureToOriginal(TypeNode ClosureClass, Method MoveNextMethod, Method OriginalMethod) { Contract.Ensures(Contract.Result<MapClosureExpressionToOriginalExpression>() != null); Dictionary<string, Parameter> closureFieldsMapping = GetClosureFieldsMapping(ClosureClass, OriginalMethod); TypeNodeList TPListSource = ClosureClass.ConsolidatedTemplateParameters; if (TPListSource == null) TPListSource = new TypeNodeList(); TypeNodeList TPListTarget = new TypeNodeList(); if (OriginalMethod.DeclaringType != null && OriginalMethod.DeclaringType.ConsolidatedTemplateParameters != null) { foreach (TypeNode tn in OriginalMethod.DeclaringType.ConsolidatedTemplateParameters) TPListTarget.Add(tn); } if (OriginalMethod.TemplateParameters != null) { foreach (TypeNode tn in OriginalMethod.TemplateParameters) { TPListTarget.Add(tn); } } Debug.Assert((TPListSource == null && TPListTarget == null) || TPListSource.Count == TPListTarget.Count); return new MapClosureExpressionToOriginalExpression( ClosureClass, closureFieldsMapping, TPListSource, TPListTarget, OriginalMethod); }
/// <summary> /// This is used to build the catalog of types in the parsed assemblies /// </summary> /// <param name="types">The list of types from an assembly</param> private void StoreTypes(TypeNodeList types) { for(int i = 0; i < types.Count; i++) { this.StoreType(types[i]); if(this.Canceled) break; } }
public MapClosureExpressionToOriginalExpression(TypeNode Closure, Dictionary<string, Parameter> closureParametersMapping, TypeNodeList TPListSource, TypeNodeList TPListTarget, Method method) { this.closureParametersMapping = closureParametersMapping; if (TPListTarget == null || TPListSource == null || TPListSource.Count == 0 || TPListTarget.Count == 0) specializer = null; else specializer = new MyMethodBodySpecializer(Closure.DeclaringModule, TPListSource, TPListTarget); this.method = method; this.closureUnspec = HelperMethods.Unspecialize(Closure); }
private void RecordExtensionMethods(XmlWriter writer, Object info) { NamespaceList spaces = (NamespaceList)info; foreach (Namespace space in spaces) { TypeNodeList types = space.Types; foreach (TypeNode type in types) { MemberList members = type.Members; // go through the members, looking for fields signaling extension methods foreach (Member member in members) { Method method = member as Method; if (method == null) { continue; } if (!reflector.ApiFilter.IsExposedMember(method)) { continue; } if (!HasExtensionAttribute(method)) { continue; } ParameterList parameters = method.Parameters; TypeNode extendedType = parameters[0].Type; // recognize generic extension methods where the extended type is a specialization of a generic type, // and the extended type's specialized template arg is a type parameter declared by the generic extension method // In this case, we need to save a TypeNode for the non-specialized type in the index, // because a TypeNode for the specialized type won't match correctly in AddExtensionMethods // Note: we are not interested in extended types that are specialized by a specific type rather than by the extension method's template param. if (method.IsGeneric && (method.TemplateParameters.Count > 0)) { if (extendedType.IsGeneric && (extendedType.TemplateArguments != null) && (extendedType.TemplateArguments.Count == 1)) { // is the extended type's template arg a template parameter, rather than a specialized type? TypeNode arg = extendedType.TemplateArguments[0]; if (arg.IsTemplateParameter) { // is the template parameter declared on the extension method ITypeParameter gtp = (ITypeParameter)arg; if ((gtp.DeclaringMember == method) && (gtp.ParameterListIndex == 0)) { // get a TypeNode for the non-specialized type extendedType = ReflectionUtilities.GetTemplateType(extendedType); } } } } List <Method> methods = null; if (!index.TryGetValue(extendedType, out methods)) { methods = new List <Method>(); index.Add(extendedType, methods); } methods.Add(method); } } } }
/// <summary> /// Write out a method name /// </summary> /// <param name="method">The method for which to write out the name</param> /// <param name="sb">The string builder to which the name is written</param> private static void WriteMethod(Method method, StringBuilder sb) { string name = method.Name.Name; WriteType(method.DeclaringType, sb); Method eiiMethod = null; if (method.IsPrivate && method.IsVirtual) { eiiMethod = method.ImplementedInterfaceMethods.FirstOrDefault(); } if (eiiMethod != null) { TypeNode eiiType = eiiMethod.DeclaringType; if (eiiType != null) { if (eiiType.Template != null) { sb.Append("."); WriteTemplate(eiiType, sb); } else { StringBuilder eiiName = new StringBuilder(); WriteType(eiiType, eiiName); sb.Append("."); sb.Append(eiiName.ToString().Replace('.', '#')); } } sb.Append("#"); sb.Append(eiiMethod.Name.Name); } else { sb.Append('.'); sb.Append(name); } if (method.IsGeneric) { TypeNodeList genericParameters = method.TemplateParameters; if (genericParameters != null) { sb.Append("``"); sb.Append(genericParameters.Count); } } WriteParameters(method.Parameters, sb); // Add ~ for conversion operators if (name == "op_Implicit" || name == "op_Explicit") { sb.Append("~"); WriteType(method.ReturnType, sb); } }
//===================================================================== /// <summary> /// This finds all attached properties and events, adds information about them to the types, and tracks /// them for adding to the reflection data later in the other callbacks. /// </summary> /// <param name="writer">The reflection data XML writer</param> /// <param name="info">For this callback, the information object is a namespace list</param> private void AddAttachedMembers(XmlWriter writer, object info) { NamespaceList spaces = (NamespaceList)info; foreach (Namespace space in spaces) { TypeNodeList types = space.Types; foreach (TypeNode type in types) { MemberList members = new MemberList(type.Members); // Go through the members looking for fields signaling attached properties foreach (Member member in members) { // We need a visible, static, field... if (!member.IsStatic || !member.IsVisibleOutsideAssembly || member.NodeType != NodeType.Field) { continue; } Field field = (Field)member; // ... of type dependency property ... if (field.Type.FullName != dependencyPropertyTypeName) { continue; } // ... with a name ending in "Property". string name = field.Name.Name; if (!name.EndsWith(dependencyPropertySuffix, StringComparison.Ordinal)) { continue; } name = name.Substring(0, name.Length - dependencyPropertySuffix.Length); // Look for a getter and/or a setter Method getter = null; MemberList candidateGetters = type.GetMembersNamed(new Identifier("Get" + name)); foreach (var candidateGetter in candidateGetters) { if (candidateGetter.NodeType == NodeType.Method && candidateGetter.IsStatic && candidateGetter.IsVisibleOutsideAssembly) { getter = (Method)candidateGetter; } } Method setter = null; MemberList candidateSetters = type.GetMembersNamed(new Identifier("Set" + name)); foreach (var candidateSetter in candidateSetters) { if (candidateSetter.NodeType == NodeType.Method && candidateSetter.IsStatic && candidateSetter.IsVisibleOutsideAssembly) { setter = (Method)candidateSetter; } } if (getter == null && setter == null) { continue; } // Make sure there isn't already such a property Property existingProperty = type.GetProperty(new Identifier(name), new TypeNode[0]); if (existingProperty != null && existingProperty.IsVisibleOutsideAssembly) { continue; } // Okay, this really is an indication of an attached property, so create one Property attachedProperty = new Property(type, null, PropertyFlags.None, new Identifier(name), getter, setter); // Attached properties have no parameters attachedProperty.Parameters = ParameterList.Empty; // Attached properties are instance properties type.Members.Add(attachedProperty); attachedMembers.Add(attachedProperty, field); } // Go through the members, looking for fields signaling attached events foreach (Member member in members) { // Follow a similar approach as above but for an event if (!member.IsStatic || !member.IsVisibleOutsideAssembly) { continue; } if (member.NodeType != NodeType.Field) { continue; } Field field = (Field)member; if (field.Type.FullName != routedEventTypeName) { continue; } string name = field.Name.Name; if (!name.EndsWith(routedEventSuffix, StringComparison.Ordinal)) { continue; } name = name.Substring(0, name.Length - routedEventSuffix.Length); Method adder = null; MemberList candidateAdders = type.GetMembersNamed(new Identifier("Add" + name + "Handler")); foreach (var candidateAdder in candidateAdders) { if (candidateAdder.NodeType == NodeType.Method && candidateAdder.IsStatic) { adder = (Method)candidateAdder; } } Method remover = null; MemberList candidateRemovers = type.GetMembersNamed(new Identifier("Remove" + name + "Handler")); foreach (var candidateRemover in candidateRemovers) { if (candidateRemover.NodeType == NodeType.Method && candidateRemover.IsStatic) { remover = (Method)candidateRemover; } } if (adder == null || remover == null) { continue; } // Make sure there isn't already such an event Event existingEvent = type.GetEvent(new Identifier(name)); if (existingEvent != null && existingEvent.IsVisibleOutsideAssembly) { continue; } // Okay, this really is an indication of an attached event, so create one TypeNode handler = adder.Parameters[1].Type; Event attachedEvent = new Event(type, null, EventFlags.None, new Identifier(name), adder, null, remover, handler); attachedEvent.HandlerFlags = adder.Flags; type.Members.Add(attachedEvent); attachedMembers.Add(attachedEvent, field); } } } }
//===================================================================== /// <summary> /// Write out a type name /// </summary> /// <param name="type">The type for which to write out the name</param> /// <param name="sb">The string builder to which the name is written</param> private static void WriteType(TypeNode type, StringBuilder sb) { switch (type.NodeType) { case NodeType.ArrayType: ArrayType array = (ArrayType)type; WriteType(array.ElementType, sb); sb.Append("["); if (array.Rank > 1) { for (int i = 0; i < array.Rank; i++) { if (i > 0) { sb.Append(","); } sb.Append("0:"); } } sb.Append("]"); break; case NodeType.Reference: Reference reference = (Reference)type; WriteType(reference.ElementType, sb); sb.Append("@"); break; case NodeType.Pointer: Pointer pointer = (Pointer)type; WriteType(pointer.ElementType, sb); sb.Append("*"); break; case NodeType.OptionalModifier: TypeModifier optionalModifierClause = (TypeModifier)type; WriteType(optionalModifierClause.ModifiedType, sb); sb.Append("!"); WriteType(optionalModifierClause.Modifier, sb); break; case NodeType.RequiredModifier: TypeModifier requiredModifierClause = (TypeModifier)type; WriteType(requiredModifierClause.ModifiedType, sb); // !EFW - Skip writing out the modifier if it's an InAttribute. Not sure if this is the best // way to handle this so we'll have to wait and see. if (requiredModifierClause.Modifier.Name.Name != "InAttribute") { sb.Append("|"); WriteType(requiredModifierClause.Modifier, sb); } break; default: if (type.IsTemplateParameter) { ITypeParameter gtp = (ITypeParameter)type; if (gtp.DeclaringMember is TypeNode) { sb.Append("`"); } else if (gtp.DeclaringMember is Method) { sb.Append("``"); } else { throw new InvalidOperationException("Generic parameter not on type or method"); } sb.Append(gtp.ParameterListIndex); } else { // Namespace TypeNode declaringType = type.DeclaringType; if (declaringType != null) { // Names of nested types begin with outer type name WriteType(declaringType, sb); sb.Append("."); } else { // Otherwise just prefix with the namespace Identifier space = type.Namespace; if (space != null && !String.IsNullOrEmpty(space.Name)) { sb.Append(space.Name); sb.Append("."); } } // Name sb.Append(type.GetUnmangledNameWithoutTypeParameters()); // Generic parameters if (type.IsGeneric) { // Number of parameters TypeNodeList parameters = type.TemplateParameters; if (parameters != null) { sb.Append('`'); sb.Append(parameters.Count); } // Arguments TypeNodeList arguments = type.TemplateArguments; if (arguments != null && arguments.Count > 0) { sb.Append("{"); for (int i = 0; i < arguments.Count; i++) { if (i > 0) { sb.Append(","); } WriteType(arguments[i], sb); } sb.Append("}"); } } } break; } }
public static TypeNode GetTemplateType(TypeNode type) { if (type == null) { throw new ArgumentNullException("type"); } // Console.WriteLine(type.FullName); // only generic types have templates if (!type.IsGeneric) { return(type); } if (type.DeclaringType == null) { // if the type is not nested, life is simpler // if the type is not specified, the type is the template if (type.TemplateArguments == null) { return(type); } // otherwise, construct the template type identifier and use it to fetch the template type Module templateModule = type.DeclaringModule; Identifier name = new Identifier(String.Format("{0}`{1}", type.GetUnmangledNameWithoutTypeParameters(), type.TemplateArguments.Count)); Identifier space = type.Namespace; TypeNode template = templateModule.GetType(space, name); return(template); } else { // if the type is nested, life is harder; we have to walk up the chain, constructing // un-specialized identifiers as we go, then walk back down the chain, fetching // template types as we go // create a stack to keep track of identifiers Stack <Identifier> identifiers = new Stack <Identifier>(); // populate the stack with the identifiers of all the types up to the outermost type TypeNode current = type; while (true) { int count = 0; if ((current.TemplateArguments != null) && (current.TemplateArguments.Count > count)) { count = current.TemplateArguments.Count; } if ((current.TemplateParameters != null) && (current.TemplateParameters.Count > count)) { count = current.TemplateParameters.Count; } TypeNodeList arguments = current.TemplateParameters; if (count == 0) { identifiers.Push(new Identifier(current.GetUnmangledNameWithoutTypeParameters())); } else { identifiers.Push(new Identifier(String.Format("{0}`{1}", current.GetUnmangledNameWithoutTypeParameters(), count))); } // Console.WriteLine("U {0} {1}", identifiers.Peek(), CountArguments(current)); if (current.DeclaringType == null) { break; } current = current.DeclaringType; } // fetch a TypeNode representing that outermost type Module module = current.DeclaringModule; Identifier space = current.Namespace; current = module.GetType(space, identifiers.Pop()); // move down the stack to the inner type we want while (identifiers.Count > 0) { current = (TypeNode)current.GetMembersNamed(identifiers.Pop())[0]; // Console.WriteLine("D {0} {1}", current.GetFullUnmangledNameWithTypeParameters(), CountArguments(current)); } // whew, finally we've got it return(current); } }
private static void DuplicateMember(DuplicatorForContractsAndClosures dup, FindClosurePartsToDuplicate fmd, int memindex, TypeNode targetType) { Member mem = fmd.MembersToDuplicate[memindex]; TypeNode nestedType = mem as TypeNode; Method closureInstanceMethod = mem as Method; Method closureMethodTemplate = closureInstanceMethod; while (closureMethodTemplate != null && closureMethodTemplate.Template != null) { closureMethodTemplate = closureMethodTemplate.Template; } if (nestedType != null) { // if nested type is nested inside another type to be duplicated, skip it if (nestedType.DeclaringType != null && fmd.MembersToDuplicate.Contains(nestedType.DeclaringType)) return; // For call-site wrappers, we end up having multiple methods from the same original contract method // thus we have to avoid duplicating the same closure type multiple times. var duplicatedNestedType = FindExistingClosureType(targetType, nestedType); if (duplicatedNestedType == null) { dup.FindTypesToBeDuplicated(new TypeNodeList(nestedType)); // if parent type is generic and different from the target type, then we may have to include all the // consolidated type parameters excluding the ones from the target type. TypeNodeList originalTemplateParameters = FindNonStandardTypeParametersToBeDuplicated(fmd, nestedType, targetType); duplicatedNestedType = dup.Visit(mem) as TypeNode; if (originalTemplateParameters != null) { int parentParameters = (targetType.ConsolidatedTemplateParameters == null) ? 0 : targetType.ConsolidatedTemplateParameters.Count; if (parentParameters > 0 && (nestedType.DeclaringType.ConsolidatedTemplateParameters == null || nestedType.DeclaringType.ConsolidatedTemplateParameters.Count == 0)) { // type is turning from non-generic to generic Debug.Assert(false); } TypeNodeList dupTPs = DuplicateTypeParameterList(originalTemplateParameters, parentParameters, duplicatedNestedType); duplicatedNestedType.TemplateParameters = dupTPs; dup.SafeAddMember(targetType, duplicatedNestedType, mem); // populate the self specialization forwarding // OriginalDecl<X,Y,Z>.NestedType<A,B,C> -> WrapperType<U,V,W>.NewNestedType<X,Y,Z,A,B,C> //var oldSelfInstanceType = nestedType.GetGenericTemplateInstance(targetModule, nestedType.ConsolidatedTemplateParameters); //var newSelfInstanceType = duplicatedNestedType.GetGenericTemplateInstance(targetModule, duplicatedNestedType.ConsolidatedTemplateParameters); //dup.DuplicateFor[oldSelfInstanceType.UniqueKey] = newSelfInstanceType; // specialize duplicated type var specializer = new Specializer(targetType.DeclaringModule, originalTemplateParameters, dupTPs); specializer.VisitTypeParameterList(dupTPs); // for constraints etc. specializer.VisitTypeNode(duplicatedNestedType); var bodySpecializer = new MethodBodySpecializer(targetType.DeclaringModule, originalTemplateParameters, dupTPs); bodySpecializer.Visit(duplicatedNestedType); // after copying the closure class, clear the self specialization forwarding // OriginalDecl<X,Y,Z>.NestedType<A,B,C> -> WrapperType<U,V,W>.NewNestedType<X,Y,Z,A,B,C> //dup.DuplicateFor[oldSelfInstanceType.UniqueKey] = null; } else { dup.SafeAddMember(targetType, duplicatedNestedType, mem); } } else { // already copied type previously dup.DuplicateFor[nestedType.UniqueKey] = duplicatedNestedType; #if false if (nestedType.ConsolidatedTemplateArguments != null) { // populate the self specialization forwarding // NestedType<Self1,Self2> -> NewNestedType<NewSelf1,NewSelf2> var origSelfInstantiation = nestedType.DeclaringType.GetTemplateInstance(nestedType, nestedType.DeclaringType.TemplateParameters).GetNestedType(nestedType.Name); var newSelfInstantiation = duplicatedNestedType.GetGenericTemplateInstance(targetModule, duplicatedNestedType.ConsolidatedTemplateParameters); dup.DuplicateFor[origSelfInstantiation.UniqueKey] = newSelfInstantiation; // Also forward ContractType<A,B>.NestedType instantiated at target ContractType<X,Y>.NestedType to // TargetType<X,Y,Z>.NewNestedType<X,Y>, since this reference may appear in the contract itself. var consolidatedContractTemplateArguments = sourceMethod.DeclaringType.ConsolidatedTemplateArguments; var instantiatedNestedOriginal = nestedType.DeclaringType.GetGenericTemplateInstance(targetModule, consolidatedContractTemplateArguments).GetNestedType(nestedType.Name); dup.DuplicateFor[instantiatedNestedOriginal.UniqueKey] = duplicatedNestedType.GetTemplateInstance(targetType, consolidatedContractTemplateArguments); } else { Debugger.Break(); } #endif } } else if (closureInstanceMethod != null && closureMethodTemplate != null && !fmd.MembersToDuplicate.Contains(closureMethodTemplate.DeclaringType)) { Method closureMethod = closureMethodTemplate; Debug.Assert(closureMethod.Template == null); //var m = FindExistingClosureMethod(targetType, closureMethod); Method m = null; // why did we ever try to find an existing one? This can capture a completely unrelated closure that happens to match by name. if (m == null) { Method dupMethod = dup.Visit(closureMethod) as Method; TypeNodeList actuals; TransformOriginalConsolidatedTypeFormalsIntoMethodFormals(dupMethod, closureMethod, closureInstanceMethod, out actuals); // now setup a forwarding from the closureInstanceMethod to the new instance Method newInstance = dupMethod.GetTemplateInstance(dupMethod.DeclaringType, actuals); newInstance.Name = dupMethod.Name; dup.DuplicateFor[closureInstanceMethod.UniqueKey] = newInstance; dup.SafeAddMember(targetType, dupMethod, closureMethod); // special case when resulting method is generic and instance, then we need to make "this" a parameter // and the method static, otherwise, there's a type mismatch between the "this" and the explicitly generic parameter types used // in arguments. var originalParentTemplateParameters = closureMethod.DeclaringType.ConsolidatedTemplateParameters; if (!dupMethod.IsStatic && originalParentTemplateParameters != null && originalParentTemplateParameters.Count > 0) { var oldThis = dupMethod.ThisParameter; oldThis.Type = dup.PossiblyRemapContractClassToInterface(oldThis.Type); dupMethod.Flags |= MethodFlags.Static; dupMethod.CallingConvention &= ~CallingConventionFlags.HasThis; var oldParameters = dupMethod.Parameters; dupMethod.Parameters = new ParameterList(oldParameters.Count + 1); dupMethod.Parameters.Add(oldThis); // make explicit for (int i = 0; i < oldParameters.Count; i++) { dupMethod.Parameters.Add(oldParameters[i]); } // now need to specialize transforming original parameters into first n method template parameters var targetTypeParameters = new TypeNodeList(originalParentTemplateParameters.Count); for (int i = 0; i < originalParentTemplateParameters.Count; i++) { targetTypeParameters.Add(dupMethod.TemplateParameters[i]); } var specializer = new Specializer(targetType.DeclaringModule, originalParentTemplateParameters, targetTypeParameters); specializer.VisitMethod(dupMethod); var bodySpecializer = new MethodBodySpecializer(targetType.DeclaringModule, originalParentTemplateParameters, targetTypeParameters); bodySpecializer.VisitMethod(dupMethod); } } } else if (closureInstanceMethod != null) { var m = FindExistingClosureMethod(targetType, closureInstanceMethod); if (m == null) { Member duplicatedMember = dup.Visit(mem) as Member; dup.SafeAddMember(targetType, duplicatedMember, mem); } } else { Member duplicatedMember = dup.Visit(mem) as Member; dup.SafeAddMember(targetType, duplicatedMember, mem); } }
public override TypeNodeList VisitTypeNodeList(TypeNodeList types) { if (types == null) return null; for (int i = 0; i < types.Count; i++) { types[i] = (TypeNode)this.Visit(types[i]); if (this.options.BlankLinesBetweenMembers && (i + 1 < types.Count)) WriteLine(string.Empty); } return types; }
/// <summary> /// If source type is insided target type, only grab the type parameters up to the target type. Otherwise, grab consolidated. /// </summary> private static TypeNodeList FindNonStandardTypeParametersToBeDuplicated(FindClosurePartsToDuplicate fmd, TypeNode sourceType, TypeNode targetType) { Debug.Assert(TypeNode.IsCompleteTemplate(sourceType)); Debug.Assert(TypeNode.IsCompleteTemplate(targetType)); TypeNodeList result = null; if (sourceType.DeclaringType != null) { if (fmd.MembersToDuplicate.Contains(sourceType.DeclaringType)) { Debug.Assert(false); return null; } if (sourceType.DeclaringType == targetType) return null; if (IsInsideOf(sourceType, targetType)) { // difficult case. Grab consolidated type parameters, except the ones up from the target type var sourceConsolidated = sourceType.ConsolidatedTemplateParameters; if (sourceConsolidated == null || sourceConsolidated.Count == 0) return null; var targetConsolidated = targetType.ConsolidatedTemplateParameters; if (targetConsolidated == null || targetConsolidated.Count == 0) return sourceConsolidated; if (sourceConsolidated.Count == targetConsolidated.Count) return null; // no extra type parameters result = new TypeNodeList(sourceConsolidated.Count - targetConsolidated.Count); for (int i = 0; i < sourceConsolidated.Count; i++) { if (i < targetConsolidated.Count) continue; result.Add(sourceConsolidated[i]); return result; } } else { // For Roslyn-based closures we need to combine all the types from source and target types together. if (sourceType.IsRoslynBasedStaticClosure()) { var sourceConsolidated = sourceType.ConsolidatedTemplateParameters; if (sourceConsolidated == null || sourceConsolidated.Count == 0) return null; var targetConsolidated = targetType.ConsolidatedTemplateParameters; if (targetConsolidated == null || targetConsolidated.Count == 0) return sourceConsolidated; if (sourceConsolidated.Count == targetConsolidated.Count) return null; // no extra type parameters result = new TypeNodeList(sourceConsolidated.Count + targetConsolidated.Count); for (int i = 0; i < targetConsolidated.Count; i++) { result.Add(targetConsolidated[i]); } for (int i = 0; i < sourceConsolidated.Count; i++) { result.Add(sourceConsolidated[i]); } return result; } result = sourceType.ConsolidatedTemplateParameters; } } return result; }
public virtual bool ImplementedTypesOverlap(TypeNodeList types1, TypeNodeList types2) { if (types1 == types2) return true; //usually means they are both null if (types1 == null || types2 == null) return false; for (int i = 0, n = types1.Count; i < n; i++) { TypeNode t1 = types1[i]; if (t1 == null) continue; for (int j = 0, m = types2.Count; j < m; j++) { TypeNode t2 = types2[j]; if (t2 == null) continue; if (t1 == t2) return true; } } return false; }
public override Statement VisitTry(Try Try) { if (Try == null) return null; bool savedInsideTryBlock = this.insideTryBlock; this.insideTryBlock = true; // when visiting the try block, use a newly computed set of allowed exceptions. // the set is whatever the current set is augmented with the set of exceptions listed in the // catch clauses TypeNodeList newAllowedExceptions = this.allowedExceptions.Clone(); CatchList cl = Try.Catchers; if (cl != null) { for (int i = 0, n = cl.Count; i < n; i++) { Catch c = cl[i]; if (c == null) continue; // BUGBUG? In both cases, should we just automatically add to the list or first see if // some exception already in the list is a supertype of the one that is currently added? if (c.Type == null) // then this was "catch { }" meaning catch everything, so all checked exceptions will be caught newAllowedExceptions.Add(SystemTypes.ICheckedException); else if (this.GetTypeView(c.Type).IsAssignableTo(SystemTypes.ICheckedException)) newAllowedExceptions.Add(c.Type); } } TypeNodeList saveAllowedExceptions = this.allowedExceptions; this.allowedExceptions = newAllowedExceptions; /* can't call the base visitor because after visiting the try block, the allowedExceptions * need to be restored before visiting the catchers. * So this is a copy of the body of StandardVisitor.VisitTry. If that ever changes, this * will need to be changed too! Statement result = base.VisitTry(Try); */ Try.TryBlock = this.VisitBlock(Try.TryBlock); /* restore the list of allowed exceptions */ this.allowedExceptions = saveAllowedExceptions; Try.Catchers = this.VisitCatchList(Try.Catchers); Try.Filters = this.VisitFilterList(Try.Filters); Try.FaultHandlers = this.VisitFaultHandlerList(Try.FaultHandlers); Try.Finally = (Finally)this.VisitFinally(Try.Finally); this.insideTryBlock = savedInsideTryBlock; CatchList catchers = Try.Catchers; if (catchers != null) { for (int i = 0, n = catchers.Count; i < n; i++) { Catch c = catchers[i]; if (c == null) continue; if (c.Type == null) continue; for (int j = 0; j < i; j++) { Catch c0 = catchers[j]; if (c0 == null || c0.Type == null) continue; if (this.GetTypeView(c.Type).IsAssignableTo(c0.Type)) this.HandleError(c.TypeExpression, Error.UnreachableCatch, this.GetTypeName(c0.Type)); } } } return Try; }