Example #1
0
        static AbstractType DeduceEponymousTemplate(EponymousTemplateType ept, ResolutionContext ctxt)
        {
            if (ept.Definition.Initializer == null &&
                ept.Definition.Type == null)
            {
                ctxt.LogError(ept.Definition, "Can't deduce type from empty initializer!");
                return(null);
            }

            // Introduce the deduced params to the current resolution context
            ctxt.CurrentContext.IntroduceTemplateParameterTypes(ept);

            // Get actual overloads
            AbstractType deducedType = null;
            var          def         = ept.Definition;

            deducedType = new MemberSymbol(def, def.Type != null ?
                                           TypeDeclarationResolver.ResolveSingle(def.Type, ctxt) :
                                           ExpressionTypeEvaluation.EvaluateType(def.Initializer, ctxt), null, ept.DeducedTypes); //ept; //ExpressionTypeEvaluation.EvaluateType (ept.Definition.Initializer, ctxt);

            deducedType.Tag = ept.Tag;                                                                                            // Currently requried for proper UFCS resolution - sustain ept's Tag

            // Undo context-related changes
            ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(ept);

            return(deducedType);
        }
Example #2
0
        void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null)
        {
            if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null)
            {
                var pop = ctxt.ScopedBlock != dm;
                if (pop)
                {
                    ctxt.PushNewScope(dm);
                }

                var t = TypeDeclarationResolver.ResolveSingle(dm.Parameters [0].Type, ctxt);
                if (ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt))
                {
                    var res = alreadyResolvedMethod ?? new MemberSymbol(dm, null, sr);
                    res.Tag = new UfcsTag {
                        firstArgument = firstArgument
                    };
                    matches.Add(res);
                }

                if (pop)
                {
                    ctxt.Pop();
                }
            }
        }
Example #3
0
            public AbstractType Visit(DEnum de)
            {
                AbstractType bt;

                if (de.Type == null)
                {
                    bt = new PrimitiveType(DTokens.Int);
                }
                else
                {
                    var pop = de.Parent is IBlockNode && ctxt.ScopedBlock != de.Parent;
                    if (pop)
                    {
                        ctxt.PushNewScope(de.Parent as IBlockNode);
                    }

                    var bts = TypeDeclarationResolver.Resolve(de.Type, ctxt);

                    if (pop)
                    {
                        ctxt.Pop();
                    }

                    ctxt.CheckForSingleResult(bts, de.Type);

                    bt = bts != null && bts.Length != 0 ? bts[0] : null;
                }

                return(new EnumType(de, bt, typeBase));
            }
        static AbstractType[] TryGetImplicitProperty(TemplateType template, ResolutionContext ctxt)
        {
            // Get actual overloads
            var matchingChild = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(template.NameHash, new[] { template }, ctxt, template.DeclarationOrExpressionBase, false);

            if (matchingChild != null)             // Currently requried for proper UFCS resolution - sustain template's Tag
            {
                foreach (var ch in matchingChild)
                {
                    var ds = ch as DSymbol;

                    if (ds != null)
                    {
                        var newDeducedTypes = new DeducedTypeDictionary(ds);
                        foreach (var tps in template.DeducedTypes)
                        {
                            newDeducedTypes[tps.Parameter] = tps;
                        }
                        ds.DeducedTypes = newDeducedTypes.ToReadonly();
                    }
                    ch.Tag = template.Tag;
                }
            }

            return(matchingChild);
        }
Example #5
0
        protected override bool HandleItem(INode n)
        {
            if (ctxt.CancelOperation)
            {
                return(true);
            }

            if ((nameFilterHash != 0 && n.NameHash != nameFilterHash) || (!(n is ImportSymbolNode) && !(n.Parent is DModule)))
            {
                return(false);
            }
            DSymbol   ds;
            DVariable dv;
            var       dc = n as DClassLike;

            if (dc != null && dc.ClassType == DTokens.Template)
            {
                if (sr is TemplateInstanceExpression || nameFilterHash == 0)
                {
                    var templ = TypeDeclarationResolver.HandleNodeMatch(dc, ctxt, null, sr);
                    templ.Tag = new UfcsTag {
                        firstArgument = firstArgument
                    };
                    matches.Add(templ);
                }
            }
            else if (n is DMethod)
            {
                HandleMethod(n as DMethod);
            }
            else if ((dv = n as DVariable) != null && dv.IsAlias)
            {
                var t = TypeDeclarationResolver.HandleNodeMatch(n, ctxt, null, sr);

                foreach (var ov in AmbiguousType.TryDissolve(t))
                {
                    ds = ov as DSymbol;
                    if (ds is MemberSymbol && ds.Definition is DMethod)
                    {
                        HandleMethod(ds.Definition as DMethod, ov as MemberSymbol);
                    }
                    else if (ds != null && (dc = ds.Definition as DClassLike) != null && dc.ClassType == DTokens.Template)
                    {
                        if (sr is TemplateInstanceExpression || nameFilterHash == 0)
                        {
                            ds.Tag = new UfcsTag {
                                firstArgument = firstArgument
                            };
                            matches.Add(ds);
                        }
                    }
                    // Perhaps other types may occur here as well - but which remain then to be added?
                }
            }

            return(false);
        }
Example #6
0
        public static List <ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolverContextStack ctxt)
        {
            // Resolve given argument expressions
            var templateArguments = new List <ISemantic>();

            if (tix != null && tix.Arguments != null)
            {
                foreach (var arg in tix.Arguments)
                {
                    if (arg is TypeDeclarationExpression)
                    {
                        var tde = (TypeDeclarationExpression)arg;

                        var res = TypeDeclarationResolver.Resolve(tde.Declaration, ctxt);

                        if (ctxt.CheckForSingleResult(res, tde.Declaration) || res != null)
                        {
                            var mr = res[0] as MemberSymbol;
                            if (mr != null && mr.Definition is DVariable)
                            {
                                var dv = (DVariable)mr.Definition;

                                if (dv.IsAlias || dv.Initializer == null)
                                {
                                    templateArguments.Add(mr);
                                    continue;
                                }

                                ISemantic eval = null;

                                try
                                {
                                    eval = new StandardValueProvider(ctxt)[dv];
                                }
                                catch (System.Exception ee)                                // Should be a non-const-expression error here only
                                {
                                    ctxt.LogError(dv.Initializer, ee.Message);
                                }

                                templateArguments.Add(eval == null ? (ISemantic)mr : eval);
                            }
                            else
                            {
                                templateArguments.Add(res[0]);
                            }
                        }
                    }
                    else
                    {
                        templateArguments.Add(Evaluation.EvaluateValue(arg, ctxt));
                    }
                }
            }

            return(templateArguments);
        }
Example #7
0
        protected override bool HandleItem(INode n)
        {
            if ((nameFilterHash != 0 && n.NameHash != nameFilterHash) || !(n.Parent is DModule))
            {
                return(false);
            }

            DVariable dv;
            var       dc = n as DClassLike;

            if (dc != null && dc.ClassType == DTokens.Template)
            {
                if (sr is TemplateInstanceExpression || nameFilterHash == 0)
                {
                    var templ = TypeDeclarationResolver.HandleNodeMatch(dc, ctxt, null, sr);
                    templ.Tag = new UfcsTag {
                        firstArgument = firstArgument
                    };
                    matches.Add(templ);
                }
            }
            else if (n is DMethod)
            {
                HandleMethod(n as DMethod);
            }
            else if ((dv = n as DVariable) != null && dv.IsAlias)
            {
                var t = TypeDeclarationResolver.HandleNodeMatch(n, ctxt, null, sr);

                var t_ = DResolver.StripAliasSymbol(t) as DSymbol;
                if (t_ != null)
                {
                    if (t_ is MemberSymbol && t_.Definition is DMethod)
                    {
                        HandleMethod(t_.Definition as DMethod, t_ as MemberSymbol);
                    }
                    else if (t_.Definition is DClassLike)
                    {
                        t_.Tag = new UfcsTag {
                            firstArgument = firstArgument
                        };
                        matches.Add(t_);
                    }
                    // Perhaps other types may occur here as well - but which remain then to be added?
                }
            }

            return(false);
        }
Example #8
0
        static AbstractType[] TryGetImplicitProperty(TemplateType template, ResolutionContext ctxt)
        {
            // Prepare a new context
            bool pop = !ctxt.ScopedBlockIsInNodeHierarchy(template.Definition);

            if (pop)
            {
                ctxt.PushNewScope(template.Definition);
            }

            // Introduce the deduced params to the current resolution context
            ctxt.CurrentContext.IntroduceTemplateParameterTypes(template);

            // Get actual overloads
            var matchingChild = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(template.NameHash, new[] { template }, ctxt);

            if (matchingChild != null)             // Currently requried for proper UFCS resolution - sustain template's Tag
            {
                foreach (var ch in matchingChild)
                {
                    var ds = ch as DSymbol;

                    if (ds != null)
                    {
                        var newDeducedTypes = new DeducedTypeDictionary(ds);
                        foreach (var tps in template.DeducedTypes)
                        {
                            newDeducedTypes[tps.Parameter] = tps;
                        }
                        ds.DeducedTypes = newDeducedTypes.ToReadonly();
                    }
                    ch.Tag = template.Tag;
                }
            }

            // Undo context-related changes
            if (pop)
            {
                ctxt.Pop();
            }
            else
            {
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals(template);
            }

            return(matchingChild);
        }
Example #9
0
        /// <summary>
        /// http://dlang.org/operatoroverloading.html#Dispatch
        /// Check for the existence of an opDispatch overload.
        /// Important: Because static opDispatches are allowed as well, do check whether we can access non-static overloads from non-instance expressions or such
        /// </summary>
        public static IEnumerable <AbstractType> TryResolveFurtherIdViaOpDispatch(ResolutionContext ctxt, int nextIdentifierHash, UserDefinedType b)
        {
            // The usual SO prevention
            if (nextIdentifierHash == opDispatchId || b == null)
            {
                yield break;
            }

            var pop = ctxt.ScopedBlock != b.Definition;

            if (pop)
            {
                // Mainly required for not resolving opDispatch's return type, as this will be performed later on in higher levels
                var opt = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.PushNewScope(b.Definition as IBlockNode);
                ctxt.CurrentContext.IntroduceTemplateParameterTypes(b);
                ctxt.CurrentContext.ContextDependentOptions = opt;
            }

            // Look for opDispatch-Members inside b's Definition
            var overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(opDispatchId, new[] { b }, ctxt);

            if (pop)
            {
                ctxt.Pop();
            }

            if (overloads == null || overloads.Length < 0)
            {
                yield break;
            }

            var av = new ArrayValue(Evaluation.GetStringType(ctxt), Strings.TryGet(nextIdentifierHash));

            foreach (DSymbol o in overloads)
            {
                var dn = o.Definition;
                if (dn.TemplateParameters != null && dn.TemplateParameters.Length > 0 &&
                    dn.TemplateParameters[0] is TemplateValueParameter)
                {
                    //TODO: Test parameter types for being a string value
                    o.DeducedTypes = new System.Collections.ObjectModel.ReadOnlyCollection <TemplateParameterSymbol> (
                        new[] { new TemplateParameterSymbol(dn.TemplateParameters[0], av) });
                    yield return(o);
                }
            }
        }
Example #10
0
            public AbstractType Visit(DVariable variable)
            {
                AbstractType bt;

                if (CanResolveBase(variable))
                {
                    var bts = TypeDeclarationResolver.Resolve(variable.Type, ctxt);

                    if (bts != null && bts.Length != 0)
                    {
                        bt = bts[0];
                    }

                    // For auto variables, use the initializer to get its type
                    else if (variable.Initializer != null)
                    {
                        bt = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(variable.Initializer, ctxt));
                    }
                    else
                    {
                        bt = null;
                    }

                    // Check if inside an foreach statement header
                    if (bt == null && ctxt.ScopedStatement != null)
                    {
                        bt = GetForeachIteratorType(variable);
                    }

                    if (bt == null)
                    {
                        ctxt.CheckForSingleResult(bts, variable.Type as ISyntaxRegion ?? variable.Initializer);
                    }
                }
                else
                {
                    bt = null;
                }

                // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type
                return(variable.IsAlias ?
                       new AliasedType(variable, bt, typeBase) :
                       new MemberSymbol(variable, bt, typeBase));
            }
Example #11
0
 void HandleMethod(DMethod dm, MemberSymbol alreadyResolvedMethod = null)
 {
     if (dm != null && dm.Parameters.Count > 0 && dm.Parameters[0].Type != null)
     {
         var loc = dm.Body != null ? dm.Body.Location : dm.Location;
         using (alreadyResolvedMethod != null ? ctxt.Push(alreadyResolvedMethod, loc) : ctxt.Push(dm, loc))
         {
             var t = TypeDeclarationResolver.ResolveSingle(dm.Parameters[0].Type, ctxt);
             if (ResultComparer.IsImplicitlyConvertible(firstArgument, t, ctxt))
             {
                 var res = alreadyResolvedMethod ?? TypeDeclarationResolver.HandleNodeMatch(dm, ctxt, typeBase: sr);
                 res.Tag = new UfcsTag {
                     firstArgument = firstArgument
                 };
                 matches.Add(res);
             }
         }
     }
 }
Example #12
0
        public static AbstractType[] ResolveType(IEditorData editor, ResolverContextStack ctxt, AstReparseOptions Options = 0)
        {
            if (ctxt == null)
            {
                return(null);
            }

            var o = GetScopedCodeObject(editor, ctxt, Options);

            if (o is IExpression)
            {
                return(Evaluation.EvaluateTypes((IExpression)o, ctxt));
            }
            else if (o is ITypeDeclaration)
            {
                return(TypeDeclarationResolver.Resolve((ITypeDeclaration)o, ctxt));
            }
            else
            {
                return(null);
            }
        }
Example #13
0
        public static AbstractType[] ResolveType(IEditorData editor, ResolutionContext ctxt = null)
        {
            if (ctxt == null)
            {
                ctxt = ResolutionContext.Create(editor);
            }

            var o = GetScopedCodeObject(editor);

            var optionBackup = ctxt.CurrentContext.ContextDependentOptions;

            ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly;

            AbstractType[] ret;

            if (o is IExpression)
            {
                ret = ExpressionTypeEvaluation.EvaluateTypes((IExpression)o, ctxt);
            }
            else if (o is ITypeDeclaration)
            {
                ret = TypeDeclarationResolver.Resolve((ITypeDeclaration)o, ctxt);
            }
            else if (o is INode)
            {
                ret = new[] { TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt) }
            }
            ;
            else
            {
                ret = null;
            }

            ctxt.CurrentContext.ContextDependentOptions = optionBackup;

            return(ret);
        }
Example #14
0
        public static AbstractType ResolveType(IEditorData editor, ResolutionContext ctxt = null)
        {
            var o = GetScopedCodeObject(editor);

            if (ctxt == null)
            {
                ctxt = ResolutionContext.Create(editor, false);
            }

            AbstractType ret = null;

            CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () =>
            {
                ctxt.Push(editor);

                var optionBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly;

                if (o is IExpression)
                {
                    ret = ExpressionTypeEvaluation.EvaluateType((IExpression)o, ctxt, false);
                }
                else if (o is ITypeDeclaration)
                {
                    ret = TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)o, ctxt);
                }
                else if (o is INode)
                {
                    ret = TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt);
                }

                ctxt.CurrentContext.ContextDependentOptions = optionBackup;
            });

            return(ret);
        }
Example #15
0
        public static MemberSymbol[] TryResolveUFCS(
            ISemantic firstArgument,
            PostfixExpression_Access acc,
            ResolverContextStack ctxt)
        {
            if (ctxt == null)
            {
                return(null);
            }

            var name = "";

            if (acc.AccessExpression is IdentifierExpression)
            {
                name = ((IdentifierExpression)acc.AccessExpression).Value as string;
            }
            else if (acc.AccessExpression is TemplateInstanceExpression)
            {
                name = ((TemplateInstanceExpression)acc.AccessExpression).TemplateIdentifier.Id;
            }
            else
            {
                return(null);
            }

            var methodMatches = new List <MemberSymbol>();

            if (ctxt.ParseCache != null)
            {
                foreach (var pc in ctxt.ParseCache)
                {
                    var tempResults = pc.UfcsCache.FindFitting(ctxt, acc.Location, firstArgument, name);

                    if (tempResults != null)
                    {
                        foreach (var m in tempResults)
                        {
                            ctxt.PushNewScope(m);

                            if (m.TemplateParameters != null && m.TemplateParameters.Length != 0)
                            {
                                var ov = TemplateInstanceHandler.DeduceParamsAndFilterOverloads(
                                    new[] { new MemberSymbol(m, null, acc) },
                                    new[] { firstArgument }, true, ctxt);

                                if (ov == null || ov.Length == 0)
                                {
                                    continue;
                                }

                                var ms = (DSymbol)ov[0];
                                ctxt.CurrentContext.IntroduceTemplateParameterTypes(ms);
                            }

                            var mr = TypeDeclarationResolver.HandleNodeMatch(m, ctxt, null, acc) as MemberSymbol;
                            ctxt.Pop();
                            if (mr != null)
                            {
                                mr.IsUFCSResult = true;
                                methodMatches.Add(mr);
                            }
                        }
                    }
                }
            }

            return(methodMatches.Count == 0 ? null : methodMatches.ToArray());
        }
Example #16
0
        private static List <AbstractType> DeduceOverloads(
            IEnumerable <AbstractType> rawOverloadList,
            IEnumerable <ISemantic> givenTemplateArguments,
            bool isMethodCall,
            ResolutionContext ctxt)
        {
            bool hasTemplateArgsPassed = givenTemplateArguments != null && givenTemplateArguments.FirstOrDefault() != null;

            var filteredOverloads = new List <AbstractType>();

            if (rawOverloadList == null)
            {
                return(filteredOverloads);
            }

            foreach (var o in rawOverloadList)
            {
                var overload = o as DSymbol;
                while (overload is TemplateParameterSymbol)
                {
                    overload = overload.Base as DSymbol;
                }
                if (overload == null)
                {
                    if (!hasTemplateArgsPassed)
                    {
                        filteredOverloads.Add(o);
                    }
                    continue;
                }
                else if (overload.Tag is TypeDeclarationResolver.AliasTag &&
                         (hasTemplateArgsPassed || !(overload.DeclarationOrExpressionBase is TemplateInstanceExpression)))
                {
                    TypeDeclarationResolver.ResetDeducedSymbols(overload);
                }

                var tplNode = overload.Definition;

                // Generically, the node should never be null -- except for TemplateParameterNodes that encapsule such params
                if (tplNode == null)
                {
                    filteredOverloads.Add(o);
                    continue;
                }

                bool ignoreOtherOverloads;
                var  hook = D_Parser.Resolver.ResolutionHooks.HookRegistry.TryDeduce(overload, givenTemplateArguments, out ignoreOtherOverloads);
                if (hook != null)
                {
                    filteredOverloads.Add(hook);
                    if (ignoreOtherOverloads)
                    {
                        break;
                    }
                    continue;
                }

                // If the type or method has got no template parameters and if there were no args passed, keep it - it's legit.
                if (tplNode.TemplateParameters == null)
                {
                    if (!hasTemplateArgsPassed || isMethodCall)
                    {
                        filteredOverloads.Add(o);
                    }
                    continue;
                }

                var deducedTypes = new DeducedTypeDictionary(overload);

                if (deducedTypes.AllParamatersSatisfied)                 // Happens e.g. after resolving a class/interface definition
                {
                    filteredOverloads.Add(o);
                }
                else if (DeduceParams(givenTemplateArguments, isMethodCall, ctxt, overload, tplNode, deducedTypes))
                {
                    overload.DeducedTypes = deducedTypes.ToReadonly();                     // Assign calculated types to final result
                    filteredOverloads.Add(o);
                }
                else
                {
                    overload.DeducedTypes = null;
                }
            }
            return(filteredOverloads);
        }
Example #17
0
        public static List <ISemantic> PreResolveTemplateArgs(TemplateInstanceExpression tix, ResolutionContext ctxt, out bool hasNonFinalArgument)
        {
            hasNonFinalArgument = false;
            // Resolve given argument expressions
            var templateArguments = new List <ISemantic>();

            if (tix != null && tix.Arguments != null)
            {
                foreach (var arg in tix.Arguments)
                {
                    if (arg is TypeDeclarationExpression)
                    {
                        var tde = (TypeDeclarationExpression)arg;

                        var res = TypeDeclarationResolver.Resolve(tde.Declaration, ctxt);

                        // Might be a simple symbol without any applied template arguments that is then passed to an template alias parameter
                        if (res == null && tde.Declaration is IdentifierDeclaration)
                        {
                            res = TypeDeclarationResolver.Resolve(tde.Declaration as IdentifierDeclaration, ctxt, null, false);
                        }

                        if (ctxt.CheckForSingleResult(res, tde.Declaration) || (res != null && res.Length > 0))
                        {
                            var mr = res[0] as MemberSymbol;
                            if (mr != null && mr.Definition is DVariable)
                            {
                                var dv = (DVariable)mr.Definition;

                                if (dv.IsAlias || dv.Initializer == null)
                                {
                                    templateArguments.Add(mr);
                                    continue;
                                }

                                ISemantic eval = null;

                                try
                                {
                                    eval = new StandardValueProvider(ctxt)[dv];
                                }
                                catch (System.Exception ee)                                // Should be a non-const-expression error here only
                                {
                                    ctxt.LogError(dv.Initializer, ee.Message);
                                }

                                templateArguments.Add(eval ?? (ISemantic)mr);
                            }
                            else
                            {
                                if (!hasNonFinalArgument)
                                {
                                    hasNonFinalArgument = IsNonFinalArgument(res[0]);
                                }
                                templateArguments.Add(res[0]);
                            }
                        }
                    }
                    else
                    {
                        ISemantic v = Evaluation.EvaluateValue(arg, ctxt, true);
                        if (v is VariableValue)
                        {
                            var vv = v as VariableValue;
                            if (vv.Variable.IsConst && vv.Variable.Initializer != null)
                            {
                                v = Evaluation.EvaluateValue(vv, new StandardValueProvider(ctxt));
                            }
                        }
                        if (!hasNonFinalArgument)
                        {
                            hasNonFinalArgument = IsNonFinalArgument(v);
                        }
                        v = DResolver.StripValueTypeWrappers(v);
                        templateArguments.Add(v);
                    }
                }
            }

            return(templateArguments);
        }
Example #18
0
        public static AbstractType ResolveKey(ArrayDecl ad, out int fixedArrayLength, out ISymbolValue keyVal, ResolutionContext ctxt)
        {
            keyVal           = null;
            fixedArrayLength = -1;
            AbstractType keyType = null;

            if (ad.KeyExpression != null)
            {
                //TODO: Template instance expressions?
                var id_x = ad.KeyExpression as IdentifierExpression;
                if (id_x != null && id_x.IsIdentifier)
                {
                    var id = new IdentifierDeclaration((string)id_x.Value)
                    {
                        Location    = id_x.Location,
                        EndLocation = id_x.EndLocation
                    };

                    keyType = TypeDeclarationResolver.ResolveSingle(id, ctxt);

                    if (keyType != null)
                    {
                        var tt = DResolver.StripAliasSymbol(keyType) as MemberSymbol;

                        if (tt == null ||
                            !(tt.Definition is DVariable) ||
                            ((DVariable)tt.Definition).Initializer == null)
                        {
                            return(keyType);
                        }
                    }
                }

                try
                {
                    keyVal = Evaluation.EvaluateValue(ad.KeyExpression, ctxt);

                    if (keyVal != null)
                    {
                        // Take the value's type as array key type
                        keyType = keyVal.RepresentedType;

                        // It should be mostly a number only that points out how large the final array should be
                        var pv = Evaluation.GetVariableContents(keyVal, new StandardValueProvider(ctxt)) as PrimitiveValue;
                        if (pv != null)
                        {
                            fixedArrayLength = System.Convert.ToInt32(pv.Value);

                            if (fixedArrayLength < 0)
                            {
                                ctxt.LogError(ad, "Invalid array size: Length value must be greater than 0");
                            }
                        }
                        //TODO Is there any other type of value allowed?
                    }
                }
                catch { }
            }
            else
            {
                var t = Resolve(ad.KeyType, ctxt);
                ctxt.CheckForSingleResult(t, ad.KeyType);

                if (t != null && t.Length != 0)
                {
                    return(t[0]);
                }
            }

            return(keyType);
        }
Example #19
0
        public static AbstractType GetMethodReturnType(DMethod method, ResolutionContext ctxt)
        {
            if ((ctxt.Options & ResolutionOptions.DontResolveBaseTypes) == ResolutionOptions.DontResolveBaseTypes)
            {
                return(null);
            }

            /*
             * If a method's type equals null, assume that it's an 'auto' function..
             * 1) Search for a return statement
             * 2) Resolve the returned expression
             * 3) Use that one as the method's type
             */
            bool pushMethodScope = ctxt.ScopedBlock != method;

            if (method.Type != null)
            {
                if (pushMethodScope)
                {
                    ctxt.PushNewScope(method);
                }

                //FIXME: Is it legal to explicitly return a nested type?
                var returnType = TypeDeclarationResolver.Resolve(method.Type, ctxt);

                if (pushMethodScope)
                {
                    ctxt.Pop();
                }

                ctxt.CheckForSingleResult(returnType, method.Type);
                if (returnType != null && returnType.Length > 0)
                {
                    return(returnType[0]);
                }
            }
            else if (method.Body != null)
            {
                ReturnStatement returnStmt = null;
                var             list       = new List <IStatement> {
                    method.Body
                };
                var list2 = new List <IStatement>();

                bool foundMatch = false;
                while (!foundMatch && list.Count > 0)
                {
                    foreach (var stmt in list)
                    {
                        if (stmt is ReturnStatement)
                        {
                            returnStmt = stmt as ReturnStatement;

                            var te = returnStmt.ReturnExpression as TokenExpression;
                            if (te == null || te.Token != DTokens.Null)
                            {
                                foundMatch = true;
                                break;
                            }
                        }

                        var statementContainingStatement = stmt as StatementContainingStatement;
                        if (statementContainingStatement != null)
                        {
                            list2.AddRange(statementContainingStatement.SubStatements);
                        }
                    }

                    list  = list2;
                    list2 = new List <IStatement>();
                }

                if (returnStmt != null && returnStmt.ReturnExpression != null)
                {
                    if (pushMethodScope)
                    {
                        var dedTypes = ctxt.CurrentContext.DeducedTemplateParameters;
                        ctxt.PushNewScope(method, returnStmt);

                        if (dedTypes.Count != 0)
                        {
                            foreach (var kv in dedTypes)
                            {
                                ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value;
                            }
                        }
                    }

                    var t = DResolver.StripMemberSymbols(ExpressionTypeEvaluation.EvaluateType(returnStmt.ReturnExpression, ctxt));

                    if (pushMethodScope)
                    {
                        ctxt.Pop();
                    }

                    return(t);
                }

                return(new PrimitiveType(DTokens.Void));
            }

            return(null);
        }
Example #20
0
        public static AbstractType ResolveTypeLoosely(IEditorData editor, out NodeResolutionAttempt resolutionAttempt, ResolutionContext ctxt = null)
        {
            var o = GetScopedCodeObject(editor);

            if (ctxt == null)
            {
                ctxt = ResolutionContext.Create(editor, false);
            }

            AbstractType          ret        = null;
            NodeResolutionAttempt resAttempt = NodeResolutionAttempt.Normal;

            CodeCompletion.DoTimeoutableCompletionTask(null, ctxt, () =>
            {
                ctxt.Push(editor);

                var optionBackup = ctxt.CurrentContext.ContextDependentOptions;
                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly | ResolutionOptions.DontResolveAliases;

                if (o is IExpression)
                {
                    ret = ExpressionTypeEvaluation.EvaluateType((IExpression)o, ctxt, false);
                }
                else if (o is ITypeDeclaration)
                {
                    ret = TypeDeclarationResolver.ResolveSingle((ITypeDeclaration)o, ctxt);
                }
                else if (o is INode)
                {
                    ret = TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt, null, o);
                }
                else
                {
                    ret = null;
                }

                if (ret == null)
                {
                    resAttempt = NodeResolutionAttempt.NoParameterOrTemplateDeduction;

                    if (o is PostfixExpression_MethodCall)
                    {
                        o = (o as PostfixExpression_MethodCall).PostfixForeExpression;
                    }

                    ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.NoTemplateParameterDeduction | ResolutionOptions.DontResolveAliases;

                    if (o is IdentifierExpression)
                    {
                        ret = AmbiguousType.Get(ExpressionTypeEvaluation.GetOverloads(o as IdentifierExpression, ctxt, deduceParameters: false), o);
                    }
                    else if (o is ITypeDeclaration)
                    {
                        ret = TypeDeclarationResolver.ResolveSingle(o as ITypeDeclaration, ctxt);
                    }
                    else if (o is IExpression)
                    {
                        ret = ExpressionTypeEvaluation.EvaluateType(o as IExpression, ctxt, false);
                    }
                }

                if (ret == null)
                {
                    resAttempt    = NodeResolutionAttempt.RawSymbolLookup;
                    var overloads = TypeDeclarationResolver.HandleNodeMatches(LookupIdRawly(editor, o as ISyntaxRegion), ctxt, null, o);
                    ret           = AmbiguousType.Get(overloads, o);
                }

                ctxt.CurrentContext.ContextDependentOptions = optionBackup;
            });

            resolutionAttempt = resAttempt;

            if (ret != null)
            {
                ret.DeclarationOrExpressionBase = o;
            }

            return(ret);
        }
Example #21
0
        /// <summary>
        /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces.
        /// Also usable for enums.
        ///
        /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved.
        /// Will clone 'tr', whereas the new object will contain the base class.
        /// </summary>
        public static UserDefinedType ResolveBaseClasses(UserDefinedType tr, ResolverContextStack ctxt, bool ResolveFirstBaseIdOnly = false)
        {
            if (bcStack > 8)
            {
                bcStack--;
                return(tr);
            }

            if (tr is EnumType)
            {
                var et = tr as EnumType;

                AbstractType bt = null;

                if (et.Definition.Type == null)
                {
                    bt = new PrimitiveType(DTokens.Int);
                }
                else
                {
                    if (tr.Definition.Parent is IBlockNode)
                    {
                        ctxt.PushNewScope((IBlockNode)tr.Definition.Parent);
                    }

                    var bts = TypeDeclarationResolver.Resolve(et.Definition.Type, ctxt);

                    if (tr.Definition.Parent is IBlockNode)
                    {
                        ctxt.Pop();
                    }

                    ctxt.CheckForSingleResult(bts, et.Definition.Type);

                    if (bts != null && bts.Length != 0)
                    {
                        bt = bts[0];
                    }
                }

                return(new EnumType(et.Definition, bt, et.DeclarationOrExpressionBase));
            }

            var dc = tr.Definition as DClassLike;

            // Return immediately if searching base classes of the Object class
            if (dc == null || ((dc.BaseClasses == null || dc.BaseClasses.Count < 1) && dc.Name == "Object"))
            {
                return(tr);
            }

            // If no base class(es) specified, and if it's no interface that is handled, return the global Object reference
            // -- and do not throw any error message, it's ok
            if (dc.BaseClasses == null || dc.BaseClasses.Count < 1)
            {
                if (tr is ClassType)                // Only Classes can inherit from non-interfaces
                {
                    return(new ClassType(dc, tr.DeclarationOrExpressionBase, ctxt.ParseCache.ObjectClassResult));
                }
                return(tr);
            }

            #region Base class & interface resolution
            TemplateIntermediateType baseClass = null;
            var interfaces = new List <InterfaceType>();

            if (!(tr is ClassType || tr is InterfaceType))
            {
                if (dc.BaseClasses.Count != 0)
                {
                    ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces");
                }
                return(tr);
            }

            for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++)
            {
                var type = dc.BaseClasses[i];

                // If there's an explicit 'Object' inheritance, also return the pre-resolved object class
                if (type is IdentifierDeclaration && ((IdentifierDeclaration)type).Id == "Object")
                {
                    if (baseClass != null)
                    {
                        ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes"));
                        continue;
                    }
                    else if (i != 0)
                    {
                        ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces"));
                        continue;
                    }

                    baseClass = ctxt.ParseCache.ObjectClassResult;
                    continue;
                }

                if (type == null || type.ToString(false) == dc.Name || dc.NodeRoot == dc)
                {
                    ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself"));
                    continue;
                }

                ctxt.PushNewScope(dc.Parent as IBlockNode);

                bcStack++;

                var res = TypeDeclarationResolver.Resolve(type, ctxt);

                ctxt.CheckForSingleResult(res, type);

                if (res != null && res.Length != 0)
                {
                    var r = res[0];
                    if (r is ClassType || r is TemplateType)
                    {
                        if (tr is InterfaceType)
                        {
                            ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces"));
                        }
                        else if (i == 0)
                        {
                            baseClass = (TemplateIntermediateType)r;
                        }
                        else
                        {
                            ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ?  "class" : "template") + " name must preceed base interfaces"));
                        }
                    }
                    else if (r is InterfaceType)
                    {
                        interfaces.Add((InterfaceType)r);
                    }
                    else
                    {
                        ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface"));
                        continue;
                    }
                }

                bcStack--;

                ctxt.Pop();
            }
            #endregion

            if (baseClass == null && interfaces.Count == 0)
            {
                return(tr);
            }

            if (tr is ClassType)
            {
                return(new ClassType(dc, tr.DeclarationOrExpressionBase, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), tr.DeducedTypes));
            }
            else if (tr is InterfaceType)
            {
                return(new InterfaceType(dc, tr.DeclarationOrExpressionBase, interfaces.Count == 0 ? null : interfaces.ToArray(), tr.DeducedTypes));
            }

            // Method should end here
            return(tr);
        }
        /// <summary>
        /// The variable's or method's base type will be resolved (if auto type, the intializer's type will be taken).
        /// A class' base class will be searched.
        /// etc..
        /// </summary>
        public static AbstractType HandleNodeMatch(
            INode m,
            ResolverContextStack ctxt,
            AbstractType resultBase = null,
            object typeBase         = null)
        {
            stackNum_HandleNodeMatch++;

            /*
             * Pushing a new scope is only required if current scope cannot be found in the handled node's hierarchy.
             */
            bool popAfterwards = !ctxt.NodeIsInCurrentScopeHierarchy(m);

            if (popAfterwards)
            {
                ctxt.PushNewScope(m is IBlockNode ? (IBlockNode)m : m.Parent as IBlockNode);
            }



            //HACK: Really dirty stack overflow prevention via manually counting call depth
            var canResolveBaseGenerally = stackNum_HandleNodeMatch < 6;



            var DoResolveBaseType = canResolveBaseGenerally &&
                                    !ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseClasses) &&
                                    (m.Type == null || m.Type.ToString(false) != m.Name);

            AbstractType ret = null;

            // To support resolving type parameters to concrete types if the context allows this, introduce all deduced parameters to the current context
            if (canResolveBaseGenerally && resultBase is DSymbol)
            {
                ctxt.CurrentContext.IntroduceTemplateParameterTypes((DSymbol)resultBase);
            }

            // Only import symbol aliases are allowed to search in the parse cache
            if (m is ImportSymbolAlias)
            {
                var isa = (ImportSymbolAlias)m;

                if (isa.IsModuleAlias ? isa.Type != null : isa.Type.InnerDeclaration != null)
                {
                    var mods = new List <DModule>();
                    var td   = isa.IsModuleAlias ? isa.Type : isa.Type.InnerDeclaration;
                    foreach (var mod in ctxt.ParseCache.LookupModuleName(td.ToString()))
                    {
                        mods.Add(mod as DModule);
                    }

                    if (mods.Count == 0)
                    {
                        ctxt.LogError(new NothingFoundError(isa.Type));
                    }
                    else if (mods.Count > 1)
                    {
                        var m__ = new List <ISemantic>();

                        foreach (var mod in mods)
                        {
                            m__.Add(new ModuleSymbol(mod, isa.Type));
                        }

                        ctxt.LogError(new AmbiguityError(isa.Type, m__));
                    }

                    var bt = mods.Count != 0 ? (AbstractType) new ModuleSymbol(mods[0], td) : null;

                    //TODO: Is this correct behaviour?
                    if (!isa.IsModuleAlias)
                    {
                        var furtherId = ResolveFurtherTypeIdentifier(isa.Type.ToString(false), new[] { bt }, ctxt, isa.Type);

                        ctxt.CheckForSingleResult(furtherId, isa.Type);

                        if (furtherId != null && furtherId.Length != 0)
                        {
                            bt = furtherId[0];
                        }
                        else
                        {
                            bt = null;
                        }
                    }

                    ret = new AliasedType(isa, bt, isa.Type);
                }
            }
            else if (m is DVariable)
            {
                var          v  = (DVariable)m;
                AbstractType bt = null;

                if (DoResolveBaseType)
                {
                    var bts = TypeDeclarationResolver.Resolve(v.Type, ctxt);

                    if (bts != null && bts.Length != 0 && ctxt.CheckForSingleResult(bts, v.Type))
                    {
                        bt = bts[0];
                    }

                    // For auto variables, use the initializer to get its type
                    else if (v.Initializer != null)
                    {
                        bt = ExpressionSemantics.Evaluation.EvaluateType(v.Initializer, ctxt);
                    }

                    // Check if inside an foreach statement header
                    if (bt == null && ctxt.ScopedStatement != null)
                    {
                        bt = GetForeachIteratorType(v, ctxt);
                    }
                }

                // Note: Also works for aliases! In this case, we simply try to resolve the aliased type, otherwise the variable's base type
                ret = v.IsAlias ?
                      (DSymbol) new AliasedType(v, bt, typeBase as ISyntaxRegion) :
                      new MemberSymbol(v, bt, typeBase as ISyntaxRegion);
            }
            else if (m is DMethod)
            {
                ret = new MemberSymbol((DNode)m,
                                       DoResolveBaseType ? GetMethodReturnType((DMethod)m, ctxt) : null
                                       , typeBase as ISyntaxRegion);
            }
            else if (m is DClassLike)
            {
                UserDefinedType udt = null;
                var             dc  = (DClassLike)m;

                var invisibleTypeParams = new Dictionary <string, TemplateParameterSymbol>();

                /*
                 * Add 'superior' template parameters to the current symbol because the parameters
                 * might be re-used in the nested class.
                 */
                var tStk = new Stack <ResolverContext>();
                do
                {
                    var curCtxt = ctxt.Pop();
                    tStk.Push(curCtxt);
                    foreach (var kv in curCtxt.DeducedTemplateParameters)
                    {
                        if (!dc.ContainsTemplateParameter(kv.Key) &&
                            !invisibleTypeParams.ContainsKey(kv.Key))
                        {
                            invisibleTypeParams.Add(kv.Key, kv.Value);
                        }
                    }
                } while (ctxt.PrevContextIsInSameHierarchy);

                while (tStk.Count != 0)
                {
                    ctxt.Push(tStk.Pop());
                }

                switch (dc.ClassType)
                {
                case DTokens.Struct:
                    ret = new StructType(dc, typeBase as ISyntaxRegion, invisibleTypeParams);
                    break;

                case DTokens.Union:
                    ret = new UnionType(dc, typeBase as ISyntaxRegion, invisibleTypeParams);
                    break;

                case DTokens.Class:
                    udt = new ClassType(dc, typeBase as ISyntaxRegion, null, null, invisibleTypeParams);
                    break;

                case DTokens.Interface:
                    udt = new InterfaceType(dc, typeBase as ISyntaxRegion, null, invisibleTypeParams);
                    break;

                case DTokens.Template:
                    ret = new TemplateType(dc, typeBase as ISyntaxRegion, invisibleTypeParams);
                    break;

                default:
                    ctxt.LogError(new ResolutionError(m, "Unknown type (" + DTokens.GetTokenString(dc.ClassType) + ")"));
                    break;
                }

                if (dc.ClassType == DTokens.Class || dc.ClassType == DTokens.Interface)
                {
                    if (canResolveBaseGenerally &&
                        !ctxt.Options.HasFlag(ResolutionOptions.DontResolveBaseClasses))
                    {
                        ret = DResolver.ResolveBaseClasses(udt, ctxt);
                    }
                    else
                    {
                        ret = udt;
                    }
                }
            }
            else if (m is IAbstractSyntaxTree)
            {
                var mod = (IAbstractSyntaxTree)m;
                if (typeBase != null && typeBase.ToString() != mod.ModuleName)
                {
                    var pack = ctxt.ParseCache.LookupPackage(typeBase.ToString()).First();
                    if (pack != null)
                    {
                        ret = new PackageSymbol(pack, typeBase as ISyntaxRegion);
                    }
                }
                else
                {
                    ret = new ModuleSymbol(m as DModule, typeBase as ISyntaxRegion);
                }
            }
            else if (m is DEnum)
            {
                ret = new EnumType((DEnum)m, typeBase as ISyntaxRegion);
            }
            else if (m is TemplateParameterNode)
            {
                //ResolveResult[] templateParameterType = null;

                //TODO: Resolve the specialization type
                //var templateParameterType = TemplateInstanceHandler.ResolveTypeSpecialization(tmp, ctxt);
                ret = new TemplateParameterSymbol((TemplateParameterNode)m, null, typeBase as ISyntaxRegion);
            }

            if (canResolveBaseGenerally && resultBase is DSymbol)
            {
                ctxt.CurrentContext.RemoveParamTypesFromPreferredLocals((DSymbol)resultBase);
            }

            if (popAfterwards)
            {
                ctxt.Pop();
            }

            stackNum_HandleNodeMatch--;
            return(ret);
        }
Example #23
0
        /// <summary>
        /// Takes the class passed via the tr, and resolves its base class and/or implemented interfaces.
        /// Also usable for enums.
        ///
        /// Never returns null. Instead, the original 'tr' object will be returned if no base class was resolved.
        /// Will clone 'tr', whereas the new object will contain the base class.
        /// </summary>
        public static TemplateIntermediateType ResolveClassOrInterface(DClassLike dc, ResolutionContext ctxt, ISyntaxRegion instanceDeclaration, bool ResolveFirstBaseIdOnly = false, IEnumerable <TemplateParameterSymbol> extraDeducedTemplateParams = null)
        {
            if (parsedClassInstanceDecls == null)
            {
                parsedClassInstanceDecls = new List <ISyntaxRegion> ();
            }

            switch (dc.ClassType)
            {
            case DTokens.Class:
            case DTokens.Interface:
                break;

            default:
                if (dc.BaseClasses.Count != 0)
                {
                    ctxt.LogError(dc, "Only classes and interfaces may inherit from other classes/interfaces");
                }
                return(null);
            }

            bool isClass = dc.ClassType == DTokens.Class;

            if (bcStack > 6 || (instanceDeclaration != null && parsedClassInstanceDecls.Contains(instanceDeclaration)))
            {
                return(isClass ? new ClassType(dc, instanceDeclaration, null) as TemplateIntermediateType : new InterfaceType(dc, instanceDeclaration));
            }

            if (instanceDeclaration != null)
            {
                parsedClassInstanceDecls.Add(instanceDeclaration);
            }
            bcStack++;

            var deducedTypes = new DeducedTypeDictionary(dc);
            var tix          = instanceDeclaration as TemplateInstanceExpression;

            if (tix != null && (ctxt.Options & ResolutionOptions.NoTemplateParameterDeduction) == 0)
            {
                bool hasUndeterminedArgs;
                var  givenTemplateArguments = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt, out hasUndeterminedArgs);

                if (!TemplateInstanceHandler.DeduceParams(givenTemplateArguments, false, ctxt, null, dc, deducedTypes))
                {
                    parsedClassInstanceDecls.Remove(instanceDeclaration);
                    bcStack--;
                    return(null);
                }
            }

            if (extraDeducedTemplateParams != null)
            {
                foreach (var tps in extraDeducedTemplateParams)
                {
                    deducedTypes[tps.Parameter] = tps;
                }
            }


            if (dc.BaseClasses == null || dc.BaseClasses.Count < 1)
            {
                parsedClassInstanceDecls.Remove(instanceDeclaration);
                bcStack--;

                // The Object class has no further base class;
                // Normal class instances have the object as base class;
                // Interfaces must not have any default base class/interface
                return(isClass ? new ClassType(dc, instanceDeclaration, dc.NameHash != ObjectNameHash ? ctxt.ParseCache.ObjectClassResult : null, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) :
                       new InterfaceType(dc, instanceDeclaration, null, deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null) as TemplateIntermediateType);
            }


            #region Base class & interface resolution
            AbstractType[] res;
            var            pop = ctxt.ScopedBlock != dc.Parent;
            if (pop)
            {
                ctxt.PushNewScope(dc.Parent as IBlockNode);
            }

            foreach (var kv in deducedTypes)
            {
                ctxt.CurrentContext.DeducedTemplateParameters[kv.Key] = kv.Value;
            }

            TemplateIntermediateType baseClass = null;
            var interfaces = new List <InterfaceType>();
            try
            {
                for (int i = 0; i < (ResolveFirstBaseIdOnly ? 1 : dc.BaseClasses.Count); i++)
                {
                    var type = dc.BaseClasses[i];

                    // If there's an explicit 'Object' inheritance, also return the pre-resolved object class
                    if (type is IdentifierDeclaration &&
                        (type as IdentifierDeclaration).IdHash == ObjectNameHash)
                    {
                        if (baseClass != null)
                        {
                            ctxt.LogError(new ResolutionError(dc, "Class must not have two base classes"));
                            continue;
                        }
                        else if (i != 0)
                        {
                            ctxt.LogError(new ResolutionError(dc, "The base class name must preceed base interfaces"));
                            continue;
                        }

                        baseClass = ctxt.ParseCache.ObjectClassResult;
                        continue;
                    }

                    if (type == null || (type is IdentifierDeclaration && (type as IdentifierDeclaration).IdHash == dc.NameHash) || dc.NodeRoot == dc)
                    {
                        ctxt.LogError(new ResolutionError(dc, "A class cannot inherit from itself"));
                        continue;
                    }

                    res = DResolver.StripAliasSymbols(TypeDeclarationResolver.Resolve(type, ctxt));

                    ctxt.CheckForSingleResult(res, type);

                    if (res != null && res.Length != 0)
                    {
                        var r = res[0];
                        if (r is ClassType || r is TemplateType)
                        {
                            if (!isClass)
                            {
                                ctxt.LogError(new ResolutionError(type, "An interface cannot inherit from non-interfaces"));
                            }
                            else if (i == 0)
                            {
                                baseClass = r as TemplateIntermediateType;
                            }
                            else
                            {
                                ctxt.LogError(new ResolutionError(dc, "The base " + (r is ClassType ?  "class" : "template") + " name must preceed base interfaces"));
                            }
                        }
                        else if (r is InterfaceType)
                        {
                            interfaces.Add(r as InterfaceType);

                            if (isClass && dc.NameHash != ObjectNameHash && baseClass == null)
                            {
                                baseClass = ctxt.ParseCache.ObjectClassResult;
                            }
                        }
                        else
                        {
                            ctxt.LogError(new ResolutionError(type, "Resolved class is neither a class nor an interface"));
                            continue;
                        }
                    }
                }
            }
            finally
            {
                bcStack--;
                parsedClassInstanceDecls.Remove(instanceDeclaration);
            }

            if (pop)
            {
                ctxt.Pop();
            }
            else
            {
                foreach (var kv in deducedTypes)                 // May be backup old tps?
                {
                    ctxt.CurrentContext.DeducedTemplateParameters.Remove(kv.Key);
                }
            }

            #endregion

            if (isClass)
            {
                return(new ClassType(dc, instanceDeclaration, baseClass, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null));
            }

            return(new InterfaceType(dc, instanceDeclaration, interfaces.Count == 0 ? null : interfaces.ToArray(), deducedTypes.Count != 0 ? deducedTypes.ToReadonly() : null));
        }
Example #24
0
        public static AbstractType[] ResolveTypeLoosely(IEditorData editor, out NodeResolutionAttempt resolutionAttempt, ResolutionContext ctxt = null)
        {
            if (ctxt == null)
            {
                ctxt = ResolutionContext.Create(editor);
            }

            var o = GetScopedCodeObject(editor);

            var optionBackup = ctxt.CurrentContext.ContextDependentOptions;

            ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.ReturnMethodReferencesOnly;
            resolutionAttempt = NodeResolutionAttempt.Normal;

            AbstractType[] ret;

            if (o is IExpression)
            {
                ret = ExpressionTypeEvaluation.EvaluateTypes((IExpression)o, ctxt);
            }
            else if (o is ITypeDeclaration)
            {
                ret = TypeDeclarationResolver.Resolve((ITypeDeclaration)o, ctxt);
            }
            else if (o is INode)
            {
                ret = new[] { TypeDeclarationResolver.HandleNodeMatch(o as INode, ctxt, null, o) }
            }
            ;
            else
            {
                ret = null;
            }

            if (ret == null)
            {
                resolutionAttempt = NodeResolutionAttempt.NoParameterOrTemplateDeduction;

                if (o is PostfixExpression_MethodCall)
                {
                    o = (o as PostfixExpression_MethodCall).PostfixForeExpression;
                }

                ctxt.CurrentContext.ContextDependentOptions |= ResolutionOptions.NoTemplateParameterDeduction;

                if (o is IdentifierExpression)
                {
                    ret = ExpressionTypeEvaluation.GetOverloads(o as IdentifierExpression, ctxt, deduceParameters: false);
                }
                else if (o is ITypeDeclaration)
                {
                    ret = TypeDeclarationResolver.Resolve(o as ITypeDeclaration, ctxt);
                }
                else if (o is IExpression)
                {
                    ret = ExpressionTypeEvaluation.EvaluateTypes(o as IExpression, ctxt);
                }
            }

            if (ret == null)
            {
                resolutionAttempt = NodeResolutionAttempt.RawSymbolLookup;
                ret = TypeDeclarationResolver.HandleNodeMatches(LookupIdRawly(editor, o as ISyntaxRegion), ctxt, null, o);
            }

            if (ret != null)
            {
                foreach (var r in ret)
                {
                    if (r != null)
                    {
                        r.DeclarationOrExpressionBase = o;
                    }
                }
            }

            ctxt.CurrentContext.ContextDependentOptions = optionBackup;
            return(ret);
        }