Пример #1
0
		public static TypeReferencesResult Scan(DModule ast, ResolutionContext ctxt)
		{
			if (ast == null)
				return new TypeReferencesResult();

			var typeRefFinder = new TypeReferenceFinder(ctxt);

			ContextFrame backupFrame = null;

			if(ctxt.ScopedBlock == ast)
				backupFrame = ctxt.Pop ();

			if (ctxt.CurrentContext == null)
			{
				ctxt.Push(backupFrame);
				backupFrame = null;
			}

			//typeRefFinder.ast = ast;
			// Enum all identifiers
			ast.Accept (typeRefFinder);

			if (backupFrame != null)
				ctxt.Push (backupFrame);

			// Crawl through all remaining expressions by evaluating their types and check if they're actual type references.
			/*typeRefFinder.queueCount = typeRefFinder.q.Count;
			typeRefFinder.ResolveAllIdentifiers();
			*/
			return typeRefFinder.result;
		}
Пример #2
0
        /// <summary>
        /// </summary>
        /// <param name="ast">The syntax tree to scan</param>
        /// <param name="symbol">Might not be a child symbol of ast</param>
        /// <param name="ctxt">The context required to search for symbols</param>
        /// <returns></returns>
        public static IEnumerable<ISyntaxRegion> Scan(DModule ast, INode symbol, ResolutionContext ctxt, bool includeDefinition = true)
        {
            if (ast == null || symbol == null || ctxt == null)
                return null;

            var f = new ReferencesFinder(symbol, ast, ctxt);

            using(ctxt.Push(ast))
                ast.Accept (f);

            var nodeRoot = symbol.NodeRoot as DModule;
            if (includeDefinition && nodeRoot != null && nodeRoot.FileName == ast.FileName)
            {
                var dc = symbol.Parent as DClassLike;
                if (dc != null && dc.ClassType == D_Parser.Parser.DTokens.Template &&
                    dc.NameHash == symbol.NameHash)
                {
                    f.l.Insert(0, new IdentifierDeclaration(dc.NameHash)
                        {
                            Location = dc.NameLocation,
                            EndLocation = new CodeLocation(dc.NameLocation.Column + dc.Name.Length, dc.NameLocation.Line)
                        });
                }

                f.l.Insert(0, new IdentifierDeclaration(symbol.NameHash)
                    {
                        Location = symbol.NameLocation,
                        EndLocation = new CodeLocation(symbol.NameLocation.Column + symbol.Name.Length,	symbol.NameLocation.Line)
                    });
            }

            return f.l;
        }
Пример #3
0
            /// <summary>
            /// Add 'superior' template parameters to the current symbol because
            /// the parameters might be re-used in the nested class.
            /// </summary>
            List <TemplateParameterSymbol> GetInvisibleTypeParameters(DNode n)
            {
                var invisibleTypeParams = new List <TemplateParameterSymbol>();

                var tStk = new Stack <ContextFrame>();

                do
                {
                    var curCtxt = ctxt.Pop();
                    tStk.Push(curCtxt);
                    foreach (var kv in curCtxt.DeducedTemplateParameters)
                    {
                        if (!n.ContainsTemplateParameter(kv.Value.Parameter))
                        {
                            invisibleTypeParams.Add(kv.Value);
                        }
                    }
                }while (ctxt.PrevContextIsInSameHierarchy);
                while (tStk.Count != 0)
                {
                    ctxt.Push(tStk.Pop());
                }

                return(invisibleTypeParams);
            }
Пример #4
0
        bool IsMoreSpecialized(ITypeDeclaration Spec, TemplateParameter t2, Dictionary <TemplateParameter, ISemantic> t1_DummyParamList)
        {
            AbstractType t1_TypeResults;

            // Make a type out of t1's specialization
            using (ctxt.Push(ctxt.ScopedBlock != null ? ctxt.ScopedBlock.Parent : null))
            {
                var dict = ctxt.CurrentContext.DeducedTemplateParameters;
                // Make the T in e.g. T[] a virtual type so T will be replaced by it
                // T** will be X** then - so a theoretically valid type instead of a template param
                var dummyType = new ClassType(new DClassLike {
                    Name = "X"
                }, null, null);
                foreach (var kv in t1_DummyParamList)
                {
                    dict[kv.Key] = new TemplateParameterSymbol(t2, dummyType);
                }

                t1_TypeResults = Resolver.TypeResolution.TypeDeclarationResolver.ResolveSingle(Spec, ctxt);
            }

            if (t1_TypeResults == null)
            {
                return(true);
            }

            // Now try to fit the virtual Type t2 into t1 - and return true if it's possible
            return(new TemplateParameterDeduction(new DeducedTypeDictionary(), ctxt).Handle(t2, t1_TypeResults));
        }
		protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar)
		{
			ed = Editor;
			ctxt = ResolutionContext.Create(Editor, false);

			AbstractType t = null;
			CodeCompletion.DoTimeoutableCompletionTask(CompletionDataGenerator,ctxt,() =>
			{
				try
				{
					ctxt.Push(Editor);
					if (AccessExpression is IExpression)
						t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt);
					else if (AccessExpression is ITypeDeclaration)
						t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt);
				}catch(Exception ex)
				{
					Logger.LogWarn("Error during member completion", ex);
				}
			});

			if (t == null) //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope
				return;

			t.Accept(this);
		}
Пример #6
0
        protected override void BuildCompletionDataInternal(IEditorData Editor, char enteredChar)
        {
            ed   = Editor;
            ctxt = ResolutionContext.Create(Editor, false);

            AbstractType t = null;

            CodeCompletion.DoTimeoutableCompletionTask(CompletionDataGenerator, ctxt, () =>
            {
                ctxt.Push(Editor);
                if (AccessExpression is IExpression)
                {
                    t = ExpressionTypeEvaluation.EvaluateType(AccessExpression as IExpression, ctxt);
                }
                else if (AccessExpression is ITypeDeclaration)
                {
                    t = TypeDeclarationResolver.ResolveSingle(AccessExpression as ITypeDeclaration, ctxt);
                }
            });

            if (t == null)             //TODO: Add after-space list creation when an unbound . (Dot) was entered which means to access the global scope
            {
                return;
            }

            t.Accept(this);
        }
Пример #7
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, ISyntaxRegion typeBase = null)
		{
			// The usual SO prevention
			if (nextIdentifierHash == opDispatchId || b == null)
				yield break;

			AbstractType[] overloads;

			var opt = ctxt.CurrentContext.ContextDependentOptions;
			// Look for opDispatch-Members inside b's Definition
			using (ctxt.Push(b))
			{
				ctxt.CurrentContext.ContextDependentOptions = opt; // Mainly required for not resolving opDispatch's return type, as this will be performed later on in higher levels
				overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(opDispatchId, b, ctxt, typeBase, false);
			}

			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.SetDeducedTypes(new[]{ new TemplateParameterSymbol(dn.TemplateParameters[0], av) });
					yield return o;
				}
			}
		}
Пример #8
0
		public static void Run()
		{
			Parse ();

			var pcw = new LegacyParseCacheView (new[]{ srcDir });
			var ctxt = new ResolutionContext (pcw, new ConditionalCompilationFlags(versions,0, true));

			var mod = pcw.LookupModuleName (null, "botan.pubkey.algo.dsa").First();
			var scope = ResolutionTests.N<DMethod> (mod, "DSAVerificationOperation.verify");
			var scopedStmt = ResolutionTests.S (scope, 9);

			ctxt.Push (scope, scopedStmt.Location);

			ITypeDeclaration td = new IdentifierDeclaration ("q"){ Location = scopedStmt.Location };
			AbstractType t;

			var sw = new Stopwatch ();
			Console.WriteLine ("Begin resolving...");
			sw.Restart ();
			t = TypeDeclarationResolver.ResolveSingle(td, ctxt);

			sw.Stop ();

			Console.WriteLine ("Finished resolution. {0} ms.", sw.ElapsedMilliseconds);

			sw.Restart ();
			t = TypeDeclarationResolver.ResolveSingle(td, ctxt);

			sw.Stop ();

			Console.WriteLine ("Finished resolution. {0} ms.", sw.ElapsedMilliseconds);
		}
Пример #9
0
        public ContextFrame(ResolutionContext ctxt, IBlockNode b, IStatement stmt = null)
        {
            this.ctxt = ctxt;
            declarationCondititons = new ConditionalCompilation.ConditionSet(ctxt.CompilationEnvironment);

            ctxt.Push(this);

            Set(b,stmt);
        }
Пример #10
0
        public static TypeReferencesResult Scan(DModule ast, ResolutionContext ctxt)
        {
            if (ast == null)
            {
                return(new TypeReferencesResult());
            }

            var typeRefFinder = new TypeReferenceFinder(ctxt);

            ContextFrame backupFrame = null;

            if (ctxt.ScopedBlock == ast)
            {
                backupFrame = ctxt.Pop();
            }

            if (ctxt.CurrentContext == null)
            {
                ctxt.Push(backupFrame);
                backupFrame = null;
            }

            //typeRefFinder.ast = ast;
            // Enum all identifiers
            ast.Accept(typeRefFinder);

            if (backupFrame != null)
            {
                ctxt.Push(backupFrame);
            }

            // Crawl through all remaining expressions by evaluating their types and check if they're actual type references.

            /*typeRefFinder.queueCount = typeRefFinder.q.Count;
             * typeRefFinder.ResolveAllIdentifiers();
             */
            return(typeRefFinder.result);
        }
Пример #11
0
        /// <summary>
        /// </summary>
        /// <param name="ast">The syntax tree to scan</param>
        /// <param name="symbol">Might not be a child symbol of ast</param>
        /// <param name="ctxt">The context required to search for symbols</param>
        /// <returns></returns>
        public static IEnumerable <ISyntaxRegion> Scan(DModule ast, INode symbol, ResolutionContext ctxt, bool includeDefinition = true)
        {
            if (ast == null || symbol == null || ctxt == null)
            {
                return(null);
            }

            var f = new ReferencesFinder(symbol, ast, ctxt);

            using (ctxt.Push(ast))
                ast.Accept(f);

            var nodeRoot = symbol.NodeRoot as DModule;

            if (includeDefinition && nodeRoot != null && nodeRoot.FileName == ast.FileName)
            {
                var dc = symbol.Parent as DClassLike;
                if (dc != null && dc.ClassType == D_Parser.Parser.DTokens.Template &&
                    dc.NameHash == symbol.NameHash)
                {
                    f.l.Insert(0, new IdentifierDeclaration(dc.NameHash)
                    {
                        Location    = dc.NameLocation,
                        EndLocation = new CodeLocation(dc.NameLocation.Column + dc.Name.Length, dc.NameLocation.Line)
                    });
                }

                var  loc = symbol.NameLocation;
                bool add = !f.l.AsParallel().Any(
                    (o) => (o is TemplateParameter && (o as TemplateParameter).NameLocation == loc) ||
                    (o is INode && (o as INode).NameLocation == loc));

                if (add)
                {
                    f.l.Insert(0, new IdentifierDeclaration(symbol.NameHash)
                    {
                        Location    = loc,
                        EndLocation = new CodeLocation(loc.Column + symbol.Name.Length, loc.Line)
                    });
                }
            }

            return(f.l);
        }
        internal override IAnalysisSet Resolve(AnalysisUnit unit, ResolutionContext context)
        {
            if (context.Cache.TryGetValue(this, out var res))
            {
                return(res);
            }

            if (!Push())
            {
                return(AnalysisSet.Empty);
            }

            try {
                if (!context.Push())
                {
                    return(AnalysisSet.Empty);
                }
                try {
                    res = ResolveOnce(unit, context, out var allowCache);
                    bool changed = !Equals(res);
                    while (changed && context.ResolveFully)
                    {
                        res = res.Resolve(unit, context, out changed);
                    }
                    if (context.ResolveFully)
                    {
                        res.Split <LazyValueInfo>(out _, out res);
                    }
                    if (allowCache)
                    {
                        context.Cache[this] = res;
                    }
                    return(res);
                } finally {
                    context.Pop();
                }
            } finally {
                Pop();
            }
        }
Пример #13
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, ISyntaxRegion typeBase = null)
        {
            // The usual SO prevention
            if (nextIdentifierHash == opDispatchId || b == null)
            {
                yield break;
            }

            AbstractType[] overloads;

            var opt = ctxt.CurrentContext.ContextDependentOptions;

            // Look for opDispatch-Members inside b's Definition
            using (ctxt.Push(b))
            {
                ctxt.CurrentContext.ContextDependentOptions = opt;                 // Mainly required for not resolving opDispatch's return type, as this will be performed later on in higher levels
                overloads = TypeDeclarationResolver.ResolveFurtherTypeIdentifier(opDispatchId, new[] { b }, ctxt, typeBase, false);
            }

            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);
                }
            }
        }
Пример #14
0
		/// <summary>
		/// </summary>
		/// <param name="ast">The syntax tree to scan</param>
		/// <param name="symbol">Might not be a child symbol of ast</param>
		/// <param name="ctxt">The context required to search for symbols</param>
		/// <returns></returns>
		public static IEnumerable<ISyntaxRegion> SearchModuleForASTNodeReferences(DModule ast, INode symbol, ResolutionContext ctxt, bool includeDefinition = true)
		{
			if (ast == null || symbol == null || ctxt == null)
				return null;

			var f = new ReferencesFinder(symbol, ast, ctxt);

			using(ctxt.Push(ast))
				ast.Accept (f);

			var nodeRoot = symbol.NodeRoot as DModule;
			if (includeDefinition && nodeRoot != null && nodeRoot.FileName == ast.FileName)
			{
				var dc = symbol.Parent as DClassLike;
				if (dc != null && dc.ClassType == D_Parser.Parser.DTokens.Template &&
					dc.NameHash == symbol.NameHash)
				{
					f.l.Insert(0, new IdentifierDeclaration(dc.NameHash)
						{
							Location = dc.NameLocation,
							EndLocation = new CodeLocation(dc.NameLocation.Column + dc.Name.Length, dc.NameLocation.Line)
						});
				}

				var loc = symbol.NameLocation;
				bool add = !f.l.AsParallel().Any(
					(o) =>	(o is TemplateParameter && (o as TemplateParameter).NameLocation == loc) ||
							(o is INode && (o as INode).NameLocation == loc));

				if(add)
					f.l.Insert(0, new IdentifierDeclaration(symbol.NameHash)
						{
							Location = loc,
							EndLocation = new CodeLocation(loc.Column + symbol.Name.Length,	loc.Line)
						});
			}

			return f.l;
		}
Пример #15
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);
        }
Пример #16
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);
        }
        static void HandleDMethodOverload(ResolutionContext ctxt, bool eval, ISymbolValue baseValue, List <ISemantic> callArguments, bool returnBaseTypeOnly, List <AbstractType> argTypeFilteredOverloads, ref bool hasHandledUfcsResultBefore,
                                          MemberSymbol ms, ref AbstractType untemplatedMethod)
        {
            var dm = ms.Definition as DMethod;

            if (dm == null)
            {
                return;
            }



            ISemantic firstUfcsArg;
            bool      isUfcs = UFCSResolver.IsUfcsResult(ms, out firstUfcsArg);

            // In the case of an ufcs, insert the first argument into the CallArguments list
            if (isUfcs && !hasHandledUfcsResultBefore)
            {
                callArguments.Insert(0, eval ? baseValue as ISemantic : firstUfcsArg);
                hasHandledUfcsResultBefore = true;
            }
            else if (!isUfcs && hasHandledUfcsResultBefore)             // In the rare case of having a ufcs result occuring _after_ a normal member result, remove the initial arg again
            {
                callArguments.RemoveAt(0);
                hasHandledUfcsResultBefore = false;
            }

            if (dm.Parameters.Count == 0 && callArguments.Count > 0)
            {
                return;
            }

            var deducedTypeDict        = new DeducedTypeDictionary(ms);
            var templateParamDeduction = new TemplateParameterDeduction(deducedTypeDict, ctxt);

            var back = ctxt.ScopedBlock;

            using (ctxt.Push(ms))
            {
                if (ctxt.ScopedBlock != back)
                {
                    ctxt.CurrentContext.DeducedTemplateParameters = deducedTypeDict;
                }

                bool add        = true;
                int  currentArg = 0;
                if (dm.Parameters.Count > 0 || callArguments.Count > 0)
                {
                    bool hadDTuples = false;
                    for (int i = 0; i < dm.Parameters.Count; i++)
                    {
                        var paramType = dm.Parameters[i].Type;

                        // Handle the usage of tuples: Tuples may only be used as as-is, so not as an array, pointer or in a modified way..
                        if (paramType is IdentifierDeclaration &&
                            (hadDTuples |= TryHandleMethodArgumentTuple(ctxt, ref add, callArguments, dm, deducedTypeDict, i, ref currentArg)))
                        {
                            continue;
                        }
                        else if (currentArg < callArguments.Count)
                        {
                            if (!(add = templateParamDeduction.HandleDecl(null, paramType, callArguments[currentArg++])))
                            {
                                break;
                            }
                        }
                        else
                        {
                            // If there are more parameters than arguments given, check if the param has default values
                            add = !(dm.Parameters[i] is DVariable) || (dm.Parameters[i] as DVariable).Initializer != null;

                            // Assume that all further method parameters do have default values - and don't check further parameters
                            break;
                        }
                    }

                    // Too few args
                    if (!hadDTuples && currentArg < callArguments.Count)
                    {
                        add = false;
                    }
                }

                if (!add)
                {
                    return;
                }

                // If type params were unassigned, try to take the defaults
                if (dm.TemplateParameters != null)
                {
                    foreach (var tpar in dm.TemplateParameters)
                    {
                        if (deducedTypeDict[tpar] == null && !templateParamDeduction.Handle(tpar, null))
                        {
                            return;
                        }
                    }
                }

                if (deducedTypeDict.AllParamatersSatisfied)
                {
                    ms.DeducedTypes = deducedTypeDict.ToReadonly();
                    var bt = TypeDeclarationResolver.GetMethodReturnType(dm, ctxt) ?? ms.Base;

                    if (eval || !returnBaseTypeOnly)
                    {
                        bt = new MemberSymbol(dm, bt, ms.DeclarationOrExpressionBase, ms.DeducedTypes)
                        {
                            Tag = ms.Tag
                        }
                    }
                    ;

                    if (dm.TemplateParameters == null || dm.TemplateParameters.Length == 0)
                    {
                        untemplatedMethod = bt;                         //ISSUE: Have another state that indicates an ambiguous non-templated method matching.
                    }
                    argTypeFilteredOverloads.Add(bt);
                }
            }
        }
Пример #18
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)
            {
                // Pop a context frame as we still need to resolve the template instance expression args in the place where the expression occurs, not the instantiated class' location
                var backup = ctxt.Pop();
                if (ctxt.CurrentContext == null)
                {
                    ctxt.Push(backup);
                }

                var givenTemplateArguments = TemplateInstanceHandler.PreResolveTemplateArgs(tix, ctxt);

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

                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
            TemplateIntermediateType baseClass = null;
            var interfaces = new List <InterfaceType>();

            var back = ctxt.ScopedBlock;
            using (ctxt.Push(dc.Parent))
            {
                var pop = back != ctxt.ScopedBlock;

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

                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;
                        }

                        var r = DResolver.StripMemberSymbols(TypeDeclarationResolver.ResolveSingle(type, ctxt));

                        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)
                {
                    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));
        }
		/// <summary>
		/// Add 'superior' template parameters to the current symbol because 
		/// the parameters might be re-used in the nested class.
		/// </summary>
		static List<TemplateParameterSymbol> GetInvisibleTypeParameters(DNode n,ResolutionContext ctxt)
		{
			var invisibleTypeParams = new List<TemplateParameterSymbol> ();

			var tStk = new Stack<ContextFrame> ();
			do {
				var curCtxt = ctxt.Pop ();
				tStk.Push (curCtxt);
				foreach (var kv in curCtxt.DeducedTemplateParameters)
					if (!n.ContainsTemplateParameter (kv.Value.Parameter))
						invisibleTypeParams.Add (kv.Value);
			}
			while (ctxt.PrevContextIsInSameHierarchy);
			while (tStk.Count != 0)
				ctxt.Push (tStk.Pop ());

			return invisibleTypeParams;
		}
Пример #20
0
 public override void VisitAbstractStmt(AbstractStatement stmt)
 {
     using (ctxt.Push(stmt.ParentNode, stmt.Location))
         base.VisitAbstractStmt(stmt);
 }
Пример #21
0
        static string GetMixinContent(MixinStatement mx, ResolutionContext ctxt, bool takeStmtCache ,out ISyntaxRegion cachedContent)
        {
            cachedContent = null;

            if(!CheckAndPushAnalysisStack(mx))
                return null;
            ISemantic v;
            using (ctxt.Push(mx.ParentNode, mx))
            {
                bool hadCachedItem;
                if (takeStmtCache)
                {
                    BlockStatement stmt;
                    hadCachedItem = mixinStmtCache.TryGet(ctxt, mx, out stmt);
                    cachedContent = stmt;
                }
                else
                {
                    DModule mod;
                    hadCachedItem = mixinDeclCache.TryGet(ctxt, mx, out mod);
                    cachedContent = mod;
                }

                if (hadCachedItem)
                {
                    stmtsBeingAnalysed.Remove(mx);
                    return null;
                }

                try // 'try' because there is always a risk of e.g. not having something implemented or having an evaluation exception...
                {
                    // Evaluate the mixin expression
                    v = Evaluation.EvaluateValue(mx.MixinExpression, ctxt);
                }
                catch {
                    v = null;
                }

                stmtsBeingAnalysed.Remove(mx);
            }

            // Ensure it's a string literal
            var av = v as ArrayValue;
            if(av != null && av.IsString)
                return av.StringValue;

            if(takeStmtCache)
                mixinStmtCache.Add(ctxt, mx, null);
            else
                mixinDeclCache.Add(ctxt, mx, null);
            return null;
        }
		public bool UpdateTypeResolutionContext ()
		{
			if (!NeedsResolutionContextUpdate && resolutionCtx != null)
				return true;
			NeedsResolutionContextUpdate = false;

			var ff = DebuggingService.CurrentCallStack.GetFrame(Backtrace.CurrentFrameIndex);
			var document = Ide.IdeApp.Workbench.OpenDocument (ff.SourceLocation.FileName);
			if (document == null)
				return false;

			var codeLocation = new CodeLocation (ff.SourceLocation.Column,
			                                     ff.SourceLocation.Line);

			// Only create new if the cursor location is different from the previous
			if (firstFrameEditorData != null &&
				firstFrameEditorData.SyntaxTree.FileName == ff.SourceLocation.FileName &&
				firstFrameEditorData.CaretLocation.Line == codeLocation.Line)
				return true;

			firstFrameEditorData = DResolverWrapper.CreateEditorData (document);

			firstFrameEditorData.CaretLocation = codeLocation;

			resolutionCtx = ResolutionContext.Create (firstFrameEditorData, false);
			CodeCompletion.DoTimeoutableCompletionTask (null, resolutionCtx, () => resolutionCtx.Push (firstFrameEditorData));

			return true;
		}