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);
        }
Esempio n. 3
0
        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);
 }
Esempio n. 12
0
        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);
            }
        }
Esempio n. 13
0
        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);
        }
Esempio n. 15
0
        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);
        }