TypeSpec WrapAsBoundGeneric(TypeSpec type, string name) { var result = new NamedTypeSpec(name); result.GenericParameters.Add(type); return(result); }
static bool ReplaceName(NamedTypeSpec named, string toFind, string replacement, ref TypeSpec result) { result = named; var changed = false; if (named.Name == toFind) { changed = true; result = new NamedTypeSpec(replacement); } var resultGenerics = new List <TypeSpec> (named.GenericParameters.Count); var changedGenerics = ReplaceName(named.GenericParameters, toFind, replacement, resultGenerics); if (changedGenerics) { if (!changed) { result = new NamedTypeSpec(named.Name); } result.GenericParameters.AddRange(resultGenerics); } else { if (changed) { result.GenericParameters.AddRange(named.GenericParameters); } } return(changed || changedGenerics); }
public TypeSpec ToTypeSpec() { NamedTypeSpec ns = new NamedTypeSpec(ToFullyQualifiedName()); ns.GenericParameters.AddRange(Generics.Select(gen => new NamedTypeSpec(gen.Name))); return(ns); }
public bool IsProtocolWithAssociatedTypesFullPath(NamedTypeSpec named, TypeMapper typeMap) { if (named == null) { return(false); } return(OwningProtocolFromGenericWithFullPath(named, typeMap) != null); }
public static bool IsIntegral(TypeSpec ts) { NamedTypeSpec named = ts as NamedTypeSpec; if (named == null) { return(false); } return(Array.IndexOf(intNames, named.Name) >= 0); }
public static bool IsBoolean(TypeSpec ts) { NamedTypeSpec named = ts as NamedTypeSpec; if (named == null) { return(false); } return(named.Name == "Swift.Bool"); }
public static bool IsFloatingPoint(TypeSpec ts) { NamedTypeSpec named = ts as NamedTypeSpec; if (named == null) { return(false); } return(named.Name == "Swift.Float" || named.Name == "Swift.Double" || named.Name == "CoreGraphics.CGFloat"); }
public ProtocolDeclaration OwningProtocolFromConstrainedGeneric(NamedTypeSpec named, TypeMapper typeMap) { var depthIndex = GetGenericDepthAndIndex(named); if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) { return(null); } var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); return(OwningProtocolFromConstrainedGeneric(genDecl, typeMap)); }
public bool IsEqualityConstrainedByAssociatedType(NamedTypeSpec name, TypeMapper typeMap) { var depthIndex = GetGenericDepthAndIndex(name); if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) { return(false); } var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); return(IsEqualityConstrainedByAssociatedType(genDecl, typeMap)); }
static BaseDeclaration FindOwningContext(BaseDeclaration context, NamedTypeSpec spec) { while (context != null) { foreach (var genPart in context.Generics) { if (genPart.Name == spec.Name) { return(context); } } context = context.Parent; } return(null); }
ProtocolDeclaration OwningProtocolAndAssociateTypeFromGenericWithFullPath(NamedTypeSpec named, TypeMapper typeMap, out AssociatedTypeDeclaration assoc) { assoc = null; if (named.Name.Contains(".")) { var parts = named.Name.Split('.'); if (IsTypeSpecGeneric(parts [0])) { // I make assertions about why things can't happen. Here's why: // If we have func foo<T:SomeProtocol>(a:T b:T.Foo) // it means that if the T part of T.Foo is a generic, then T HAS to be // constrained to a protocol with associated types // If T.Foo is a path to an associated type, then it var depthIndex = GetGenericDepthAndIndex(parts [0]); if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) { return(null); } var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); if (genDecl.Constraints.Count != 1) // pretty sure this can't ever happen { return(null); } var inh = genDecl.Constraints [0] as InheritanceConstraint; if (inh == null) // pretty sure this also can't ever happen { return(null); } var entity = typeMap.GetEntityForTypeSpec(inh.InheritsTypeSpec); if (entity == null) // Also can't happen { return(null); } if (entity.EntityType != EntityType.Protocol) { return(null); // Also can't happen } var protocol = entity.Type as ProtocolDeclaration; if (protocol != null && protocol.HasAssociatedTypes && (assoc = protocol.AssociatedTypeNamed(parts [1])) != null) { return(protocol); } } } return(null); }
protected override bool LLEquals(TypeSpec other, bool partialNameMatch) { NamedTypeSpec spec = other as NamedTypeSpec; if (spec == null) { return(false); } var innersMatch = (InnerType == null && spec.InnerType == null) || (InnerType != null && InnerType.LLEquals(spec.InnerType, partialNameMatch)); if (partialNameMatch) { return(NameWithoutModule == spec.NameWithoutModule && innersMatch); } else { return(Name == spec.Name && innersMatch); } }
public bool IsBoundGeneric(BaseDeclaration context, TypeMapper mapper) { switch (this.Kind) { case TypeSpecKind.Named: NamedTypeSpec ns = (NamedTypeSpec)this; Entity en = mapper.TryGetEntityForSwiftClassName(ns.Name); if (en == null) { if (context.IsTypeSpecGeneric(ns)) { return(false); // unbound } } foreach (TypeSpec genParm in GenericParameters) { if (genParm.IsUnboundGeneric(context, mapper)) { return(false); // unbound } } return(true); case TypeSpecKind.Closure: ClosureTypeSpec cs = (ClosureTypeSpec)this; return(cs.Arguments.IsBoundGeneric(context, mapper) && cs.ReturnType.IsBoundGeneric(context, mapper)); case TypeSpecKind.Tuple: TupleTypeSpec ts = (TupleTypeSpec)this; foreach (TypeSpec elem in ts.Elements) { if (elem.IsUnboundGeneric(context, mapper)) { return(false); } } return(true); default: throw new NotSupportedException("unknown TypeSpecKind " + this.Kind.ToString()); } }
public bool IsTypeSpecAssociatedType(NamedTypeSpec named) { var proto = ThisOrParentProtocol(this); if (proto == null) { return(false); } if (named.ContainsGenericParameters) { foreach (var gen in named.GenericParameters) { if (gen is NamedTypeSpec namedGen && IsTypeSpecAssociatedType(namedGen)) { return(true); } } } return(proto.AssociatedTypeNamed(named.NameWithoutModule) != null); }
public bool IsUnboundGeneric(BaseDeclaration context, TypeMapper mapper) { switch (Kind) { case TypeSpecKind.Named: NamedTypeSpec ns = (NamedTypeSpec)this; if (context.IsTypeSpecGeneric(ns.ToString())) { return(true); } foreach (TypeSpec genparm in GenericParameters) { if (genparm.IsUnboundGeneric(context, mapper)) { return(true); } } return(false); case TypeSpecKind.Closure: ClosureTypeSpec cs = (ClosureTypeSpec)this; return(cs.Arguments.IsUnboundGeneric(context, mapper) && cs.ReturnType.IsUnboundGeneric(context, mapper)); case TypeSpecKind.Tuple: TupleTypeSpec ts = (TupleTypeSpec)this; foreach (TypeSpec elem in ts.Elements) { if (elem.IsUnboundGeneric(context, mapper)) { return(true); } } return(false); case TypeSpecKind.ProtocolList: return(false); default: throw new NotSupportedException("unknown TypeSpecKind " + this.Kind.ToString()); } }
TypeSpec ParseProtocolList(NamedTypeSpec first) { Ex.ThrowOnNull(first, nameof(first)); var protocols = new List <NamedTypeSpec> (); protocols.Add(first); while (true) { if (tokenizer.Peek().Kind != TypeTokenKind.Ampersand) { break; } tokenizer.Next(); var nextName = tokenizer.Next(); if (nextName.Kind != TypeTokenKind.TypeName) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 13, $"Unexpected token '{nextName.Value}' with kind {nextName.Kind} while parsing a protocol list"); } protocols.Add(new NamedTypeSpec(nextName.Value)); } return(new ProtocolListTypeSpec(protocols)); }
NamedTypeSpec ParseArray() { var keyType = Parse(); TypeSpec valueType = null; if (keyType == null) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 9, "Unexpected end while parsing an array or dictionary."); } if (tokenizer.Peek().Kind == TypeTokenKind.Colon) { tokenizer.Next(); valueType = Parse(); if (valueType == null) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 10, "Unexpected end while parsing a dictionary value type."); } } else if (tokenizer.Peek().Kind != TypeTokenKind.RightBracket) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 11, "Expected a right bracket after an array or dictionary."); } tokenizer.Next(); if (valueType == null) { var array = new NamedTypeSpec("Swift.Array"); array.GenericParameters.Add(keyType); return(array); } else { var dictionary = new NamedTypeSpec("Swift.Dictionary"); dictionary.GenericParameters.Add(keyType); dictionary.GenericParameters.Add(valueType); return(dictionary); } }
public ProtocolDeclaration GetConstrainedProtocolWithAssociatedType(NamedTypeSpec named, TypeMapper typeMapper) { var depthIndex = GetGenericDepthAndIndex(named); if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) { return(null); } var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); if (genDecl == null) { return(null); } if (genDecl.Constraints.Count != 1) { return(null); } var inheritance = genDecl.Constraints [0] as InheritanceConstraint; if (inheritance == null) { return(null); } var entity = typeMapper.GetEntityForTypeSpec(inheritance.InheritsTypeSpec); if (entity == null) { return(null); } var proto = entity.Type as ProtocolDeclaration; if (proto == null || !proto.HasAssociatedTypes) { return(null); } return(proto); }
static ParameterItem RecastAsReference(ParameterItem p) { if (p.IsInOut) { if (!p.TypeSpec.IsInOut) { p.TypeSpec.IsInOut = true; } return(p); } if (p.TypeSpec is NamedTypeSpec && p.TypeSpec.ContainsGenericParameters) { NamedTypeSpec named = (NamedTypeSpec)p.TypeSpec; // special case - turn UnsafePointer<T> into inout T for matching purposes if (named.Name == "Swift.UnsafePointer" || named.Name == "Swift.UnsafeMutablePointer") { p = new ParameterItem(p); p.TypeSpec = p.TypeSpec.GenericParameters [0]; p.IsInOut = true; p.TypeSpec.IsInOut = true; } } return(p); }
public GenericReferenceAssociatedTypeProtocol GetConstrainedAssociatedTypeProtocol(NamedTypeSpec spec, TypeMapper typeMap) { // we're looking for the pattern T, where T is a generic or contains a generic (Foo<T>) // and there exists a where T : SomeProtocol if (spec == null) { return(null); } GenericReferenceAssociatedTypeProtocol result = null; if (spec.ContainsGenericParameters) { foreach (var gen in spec.GenericParameters) { // recurse on generic element result = GetConstrainedAssociatedTypeProtocol(gen as NamedTypeSpec, typeMap); if (result != null) { break; } } } else { // which declaration has this generic var owningContext = FindOwningContext(this, spec); if (owningContext != null) { foreach (var genPart in Generics) { if (genPart.Name != spec.Name) { continue; } // genPart is the one we care about - now look for a constraint. foreach (var constraint in genPart.Constraints) { // Is it inheritance? if (constraint is InheritanceConstraint inheritance) { // Find the entity in the database var entity = typeMap.TypeDatabase.EntityForSwiftName(inheritance.Inherits); // Is it a protocol and it has associated types if (entity != null && entity.Type is ProtocolDeclaration proto && proto.HasAssociatedTypes) { result = new GenericReferenceAssociatedTypeProtocol() { GenericPart = spec, Protocol = proto } } ; } } if (result != null) { break; } } } } return(result); }
public AssociatedTypeDeclaration AssociatedTypeDeclarationFromNamedTypeSpec(NamedTypeSpec named) { var proto = ThisOrParentProtocol(this); return(proto.AssociatedTypeNamed(named.NameWithoutModule)); }
public AssociatedTypeDeclaration AssociatedTypeDeclarationFromConstrainedGeneric(NamedTypeSpec named, TypeMapper typeMap) { var depthIndex = GetGenericDepthAndIndex(named); if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0) { return(null); } var genDecl = GetGeneric(depthIndex.Item1, depthIndex.Item2); return(AssociatedTypeDeclarationFromConstrainedGeneric(genDecl, typeMap)); }
public AssociatedTypeDeclaration AssociatedTypeDeclarationFromGenericWithFullPath(NamedTypeSpec named, TypeMapper typeMap) { AssociatedTypeDeclaration assoc = null; OwningProtocolAndAssociateTypeFromGenericWithFullPath(named, typeMap, out assoc); return(assoc); }
TypeSpec Parse() { TypeSpecToken token = tokenizer.Peek(); TypeSpec type = null; List <TypeSpecAttribute> attrs = null; var inout = false; string typeLabel = null; // Prefix // parse any attributes if (token.Kind == TypeTokenKind.At) { attrs = ParseAttributes(); token = tokenizer.Peek(); } // looks like it's inout if (token.Kind == TypeTokenKind.TypeName && token.Value == "inout") { inout = true; tokenizer.Next(); token = tokenizer.Peek(); } if (token.Kind == TypeTokenKind.TypeLabel) { typeLabel = token.Value; tokenizer.Next(); token = tokenizer.Peek(); } // meat if (token.Kind == TypeTokenKind.LeftParenthesis) // tuple { tokenizer.Next(); TupleTypeSpec tuple = ParseTuple(); type = tuple.Elements.Count == 1 ? tuple.Elements [0] : tuple; typeLabel = type.TypeLabel; } else if (token.Kind == TypeTokenKind.TypeName) // name { tokenizer.Next(); var tokenValue = token.Value.StartsWith("ObjectiveC.", StringComparison.Ordinal) ? "Foundation" + token.Value.Substring("ObjectiveC".Length) : token.Value; type = new NamedTypeSpec(tokenValue); } else if (token.Kind == TypeTokenKind.LeftBracket) // array { tokenizer.Next(); type = ParseArray(); } else // illegal { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 0, $"Unexpected token {token.Value}."); } // look-ahead for closure if (tokenizer.Peek().Kind == TypeTokenKind.TypeName && tokenizer.Peek().Value == "throws") { tokenizer.Next(); if (tokenizer.Peek().Kind != TypeTokenKind.Arrow) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 1, $"Unexpected token {tokenizer.Peek ().Value} after a 'throws' in a closure."); } tokenizer.Next(); type = ParseClosure(type, true); } if (tokenizer.Peek().Kind == TypeTokenKind.Arrow) { tokenizer.Next(); type = ParseClosure(type, false); } else if (tokenizer.Peek().Kind == TypeTokenKind.LeftAngle) { tokenizer.Next(); type = Genericize(type); } if (tokenizer.Peek().Kind == TypeTokenKind.Period) { tokenizer.Next(); var currType = type as NamedTypeSpec; if (currType == null) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 2, $"In parsing an inner type (type.type), first element is a {type.Kind} instead of a NamedTypeSpec."); } var nextType = Parse() as NamedTypeSpec; if (nextType == null) { throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 3, $"In parsing an inner type (type.type), the second element is a {nextType.Kind} instead of a NamedTypeSpec"); } currType.InnerType = nextType; } // Postfix if (tokenizer.Peek().Kind == TypeTokenKind.Ampersand) { type = ParseProtocolList(type as NamedTypeSpec); } while (tokenizer.Peek().Kind == TypeTokenKind.QuestionMark) { tokenizer.Next(); type = WrapAsBoundGeneric(type, "Swift.Optional"); } if (tokenizer.Peek().Kind == TypeTokenKind.ExclamationPoint) { tokenizer.Next(); type = WrapAsBoundGeneric(type, "Swift.ImplicitlyUnwrappedOptional"); } type.IsInOut = inout; type.TypeLabel = typeLabel; if (type != null && attrs != null) { type.Attributes.AddRange(attrs); } return(type); }