public List <SubscriptDeclaration> AllSubscripts() { var allSubFuncs = Members.OfType <FunctionDeclaration> ().Where(decl => decl.IsSubscript).ToList(); var allSubs = new List <SubscriptDeclaration> (); while (allSubFuncs.Count > 0) { int i = allSubFuncs.Count - 1; FunctionDeclaration decl = allSubFuncs [i]; allSubFuncs.RemoveAt(i); if (decl.IsSubscriptMaterializer) { continue; } if (decl.IsSubscriptGetter) { FunctionDeclaration setter = GetAndRemoveSetter(allSubFuncs, decl); FunctionDeclaration materializer = GetAndRemoveMaterializer(allSubFuncs, decl); allSubs.Add(new SubscriptDeclaration(decl, setter, materializer)); } else if (decl.IsSubscriptSetter) { FunctionDeclaration getter = GetAndRemoveGetter(allSubFuncs, decl); FunctionDeclaration materializer = GetAndRemoveMaterializer(allSubFuncs, decl); allSubs.Add(new SubscriptDeclaration(getter, decl, materializer)); } } return(allSubs); }
public static FunctionDeclaration FuncFromXElement(XElement elem, ModuleDeclaration module, BaseDeclaration parent) { FunctionDeclaration decl = new FunctionDeclaration { Name = (string)elem.Attribute("name"), Module = module, Parent = parent, Access = TypeDeclaration.AccessibilityFromString((string)elem.Attribute("accessibility")), ReturnTypeName = Ex.ThrowOnNull((string)elem.Attribute("returnType"), "returnType"), IsProperty = elem.BoolAttribute("isProperty"), IsStatic = elem.BoolAttribute("isStatic"), IsFinal = elem.BoolAttribute("isFinal"), OperatorType = OperatorTypeFromElement((string)elem.Attribute("operatorKind")), HasThrows = elem.BoolAttribute("hasThrows"), IsDeprecated = elem.BoolAttribute("isDeprecated"), IsUnavailable = elem.BoolAttribute("isUnavailable"), IsOptional = elem.BoolAttribute("isOptional"), ObjCSelector = (string)elem.Attribute("objcSelector"), IsRequired = elem.BoolAttribute("isRequired"), IsConvenienceInit = elem.BoolAttribute("isConvenienceInit") }; decl.ParameterLists.AddRange(ParameterItem.ParameterListListFromXElement(elem.Element("parameterlists"))); if (decl.IsProperty && (decl.IsSetter || decl.IsSubscriptSetter)) { decl.ParameterLists [decl.ParameterLists.Count - 1] = MassageLastPropertySetterParameterList(decl.ParameterLists.Last()); } return(decl); }
public static BaseDeclaration FromXElement(XElement elem, ModuleDeclaration module, BaseDeclaration parent) { var generics = GenericDeclaration.FromXElement(elem.Element("genericparameters")); BaseDeclaration decl = null; switch (elem.Name.ToString()) { case "func": decl = FunctionDeclaration.FuncFromXElement(elem, module, parent); break; case "typedeclaration": decl = TypeDeclaration.TypeFromXElement(elem, module, parent); break; case "property": decl = PropertyDeclaration.PropFromXElement(elem, module, parent); break; default: decl = new BaseDeclaration { Name = (string)elem.Attribute("name"), Access = TypeDeclaration.AccessibilityFromString((string)elem.Attribute("accessibility")) }; break; } decl.Generics.AddRange(generics); return(decl); }
public static bool AreEqualIgnoreNamesReferencesInvariant(FunctionDeclaration fn1, IList <ParameterItem> pl1, FunctionDeclaration fn2, IList <ParameterItem> pl2, bool matchPartialNames) { if (pl1.Count != pl2.Count) { return(false); } for (int i = 0; i < pl1.Count; i++) { var p1 = SubstituteSelfFromParent(fn1, pl1 [i]); var p2 = SubstituteSelfFromParent(fn2, pl2 [i]); p1 = RecastAsReference(p1); p2 = RecastAsReference(p2); // Names invariant means TYPE names not parameter names if (!ParameterNamesMatch(p1, p2)) { // we give a pass on matching "self". // this is done because "self" is a keyword in swift // and when matching a wrapper function, we can't call // a parameter "self" but have to call it "thisN" where // N is either an empty string or a number. // This is because there might be a real parameter named "this" // and we had to rename it. // The end result is that we can't use a "this" test, but we // can use a "self" test. var parmName1 = p1.NameIsRequired ? p1.PublicName : p1.PrivateName; var parmName2 = p2.NameIsRequired ? p2.PublicName : p2.PrivateName; if (parmName1 != "self" && parmName2 != "self") { return(false); } } if (fn1.IsTypeSpecGeneric(p1)) { if (!fn2.IsTypeSpecGeneric(p2)) { return(false); } continue; } if (!p1.EqualsIgnoreName(p2)) { if (matchPartialNames) { if (!p1.EqualsIgnoreNamesPartialMatch(p2)) { return(false); } } else { return(false); } } } return(true); }
static ParameterItem SubstituteSelfFromParent(FunctionDeclaration func, ParameterItem p) { if (func.Parent == null || !p.TypeSpec.HasDynamicSelf) { return(p); } p = new ParameterItem(p); p.TypeSpec = p.TypeSpec.ReplaceName("Self", func.Parent.ToFullyQualifiedNameWithGenerics()); return(p); }
static FunctionDeclaration GetAndRemoveGetter(List <FunctionDeclaration> decls, FunctionDeclaration other) { var plToMatch = new List <ParameterItem> (); TypeSpec returnToMatch = null; var selfToMatch = other.Parent; if (other.IsSetter) { // setter - // The arguments to a setter are // value, arg1, arg2 ... argn // We want to match the type of the return of the getter to the value of the setter // as well as the parameters List <ParameterItem> pl = other.ParameterLists.Last(); plToMatch.AddRange(pl.GetRange(1, pl.Count - 1)); returnToMatch = pl [0].TypeSpec; } else { // materializer. // The arguments to a materializer are // buffer, callbackStoragebuffer, arg1, arg2 ... argn // We have no return to match. Oops. List <ParameterItem> pl = other.ParameterLists.Last(); plToMatch.AddRange(pl.GetRange(2, pl.Count - 2)); returnToMatch = null; } for (int i = 0; i < decls.Count; i++) { FunctionDeclaration getter = decls [i]; if (getter.Parent != selfToMatch) { return(null); } if (!getter.IsSubscriptGetter) { continue; } if ((returnToMatch != null && returnToMatch.Equals(getter.ReturnTypeSpec)) || returnToMatch == null) { List <ParameterItem> targetPl = getter.ParameterLists.Last(); if (ParmsMatch(plToMatch, targetPl)) { decls.RemoveAt(i); return(getter); } } } return(null); }
static FunctionDeclaration GetAndRemoveSetter(List <FunctionDeclaration> decls, FunctionDeclaration other) { var plToMatch = new List <ParameterItem> (); var selfToMatch = other.Parent; if (other.IsGetter) { // getter - // The arguments to a getter are // arg1, arg2 ... argn // We want to match the type of the return of the getter to the value of the setter // as well as the parameters List <ParameterItem> pl = other.ParameterLists.Last(); ParameterItem item = new ParameterItem(); item.PublicName = ""; item.PrivateName = "retval"; item.TypeSpec = other.ReturnTypeSpec; item.TypeName = other.ReturnTypeName; plToMatch.Add(item); plToMatch.AddRange(pl); } else { // we don't have enough information to match on setter // and since we don't use the materializer, NBD. // materializer. // The arguments to a materializer are // buffer, callbackStoragebuffer, arg1, arg2 ... argn // We have no return to match. Oops. return(null); } for (int i = 0; i < decls.Count; i++) { FunctionDeclaration setter = decls [i]; if (!setter.IsSubscriptGetter) { continue; } List <ParameterItem> targetPl = setter.ParameterLists.Last(); if (ParmsMatch(plToMatch, targetPl)) { decls.RemoveAt(i); return(setter); } } return(null); }
public FunctionDeclaration(FunctionDeclaration other) : base(other) { ParameterLists = CopyOf(other.ParameterLists); ReturnTypeName = other.ReturnTypeName; IsProperty = other.IsProperty; IsStatic = other.IsStatic; IsFinal = other.IsFinal; HasThrows = other.HasThrows; IsDeprecated = other.IsDeprecated; IsUnavailable = other.IsUnavailable; OperatorType = other.OperatorType; IsOptional = other.IsOptional; ObjCSelector = other.ObjCSelector; IsRequired = other.IsRequired; IsConvenienceInit = other.IsConvenienceInit; }
static bool SubscriptParametersMatch(FunctionDeclaration getter, FunctionDeclaration setter) { if (getter.ParameterLists.Count != 2 || setter.ParameterLists.Count != 2) { return(false); } TypeSpec returnType = getter.ReturnTypeSpec; if (getter.ParameterLists [1].Count != setter.ParameterLists [1].Count - 1) { return(false); } if (!returnType.Equals(setter.ParameterLists [1] [0].TypeSpec)) { return(false); } return(ParameterItem.AreEqualIgnoreNamesReferencesInvariant(getter, getter.ParameterLists [1], setter, setter.ParameterLists [1].Skip(1).ToList(), true)); }
public bool MatchesSignature(FunctionDeclaration other, bool ignoreFirstParameterListIfPresent) { if (!TypeSpec.BothNullOrEqual(this.ReturnTypeSpec, other.ReturnTypeSpec)) { return(false); } if (this.ParameterLists.Count != other.ParameterLists.Count) { return(false); } int startIndex = ignoreFirstParameterListIfPresent && this.ParameterLists.Count > 1 ? 1 : 0; for (int i = startIndex; i < this.ParameterLists.Count; i++) { if (!ParameterItem.AreEqualIgnoreNamesReferencesInvariant(this, this.ParameterLists [i], other, other.ParameterLists [i], true)) { return(false); } } return(true); }
public bool VirtualMethodExistsInInheritedBoundType(FunctionDeclaration func, TypeMapper typeMapper) { // virtual methods are only in classes if (!(this is ClassDeclaration)) { return(false); } var classInheritance = Inheritance.FirstOrDefault(inh => inh.InheritanceKind == InheritanceKind.Class); if (classInheritance == null) { return(false); } var inheritedEntity = typeMapper.GetEntityForTypeSpec(classInheritance.InheritedTypeSpec); if (inheritedEntity == null) { throw ErrorHelper.CreateError(ReflectorError.kTypeMapBase + 18, $"Unable to find type database entry for class {classInheritance.InheritedTypeName} while searching inheritance."); } // if we get here, the Type has to be a ClassDeclaration var inheritedClass = inheritedEntity.Type as ClassDeclaration; var methods = inheritedClass.AllVirtualMethods().FindAll(fn => fn.Name == func.Name && fn.ParameterLists.Last().Count == func.ParameterLists.Last().Count).ToList(); foreach (var method in methods) { if (ParmsMatchWithNames(method.ParameterLists.Last(), func.ParameterLists.Last()) && method.ReturnTypeSpec.Equals(func.ReturnTypeSpec)) { return(true); } } return(inheritedClass.VirtualMethodExistsInInheritedBoundType(func, typeMapper)); }
static FunctionDeclaration GetAndRemoveMaterializer(List <FunctionDeclaration> decls, FunctionDeclaration other) { // FIXME - materializers don't have enough to match on with 100% confidence // Materializers are (probably) not needed by tom-swifty, so no big return(null); }