Пример #1
0
        public static ArgumentsResolutionResult ResolveArgumentContext(
			string code,
			int caretOffset,
			CodeLocation caretLocation,
			DMethod MethodScope,
			IEnumerable<IAbstractSyntaxTree> parseCache, IEnumerable<IAbstractSyntaxTree> ImportCache)
        {
            var ctxt = new ResolverContext { ScopedBlock = MethodScope, ParseCache = parseCache, ImportCache=ImportCache };

            #region Parse the code between the last block opener and the caret

            var curMethodBody = MethodScope.GetSubBlockAt(caretLocation);

            if (curMethodBody == null && MethodScope.Parent is DMethod)
            {
                MethodScope = MethodScope.Parent as DMethod;
                curMethodBody = MethodScope.GetSubBlockAt(caretLocation);
            }

            if (curMethodBody == null)
                return null;

            var blockOpenerLocation = curMethodBody.StartLocation;
            var blockOpenerOffset = blockOpenerLocation.Line <= 0 ? blockOpenerLocation.Column :
                DocumentHelper.LocationToOffset(code, blockOpenerLocation);

            if (blockOpenerOffset >= 0 && caretOffset - blockOpenerOffset > 0)
            {
                var codeToParse = code.Substring(blockOpenerOffset, caretOffset - blockOpenerOffset);

                curMethodBody = DParser.ParseBlockStatement(codeToParse, blockOpenerLocation, MethodScope);

                if (curMethodBody != null)
                    ctxt.ScopedStatement = curMethodBody.SearchStatementDeeply(caretLocation);
            }

            if (curMethodBody == null || ctxt.ScopedStatement == null)
                return null;
            #endregion

            // Scan statement for method calls or template instantiations
            var e = DResolver.SearchForMethodCallsOrTemplateInstances(ctxt.ScopedStatement, caretLocation);

            /*
             * 1) foo(			-- normal arguments only
             * 2) foo!(...)(	-- normal arguments + template args
             * 3) foo!(		-- template args only
             * 4) new myclass(  -- ctor call
             * 5) new myclass!( -- ditto
             * 6) new myclass!(...)(
             * 7) mystruct(		-- opCall call
             */
            var res = new ArgumentsResolutionResult() { ParsedExpression = e };

            ITypeDeclaration methodIdentifier = null;

            // 1), 2)
            if (e is PostfixExpression_MethodCall)
            {
                res.IsMethodArguments = true;
                var call = e as PostfixExpression_MethodCall;

                if (call.Arguments != null)
                {
                    int i = 0;
                    foreach (var arg in call.Arguments)
                    {
                        if (caretLocation >= arg.Location && caretLocation <= arg.EndLocation)
                        {
                            res.CurrentlyTypedArgumentIndex = i;
                            break;
                        }
                        i++;
                    }
                }

                methodIdentifier = call.PostfixForeExpression.ExpressionTypeRepresentation;

            }
            // 3)
            else if (e is TemplateInstanceExpression)
            {
                var templ = e as TemplateInstanceExpression;

                res.IsTemplateInstanceArguments = true;

                if (templ.Arguments != null)
                {
                    int i = 0;
                    foreach (var arg in templ.Arguments)
                    {
                        if (caretLocation >= arg.Location && caretLocation <= arg.EndLocation)
                        {
                            res.CurrentlyTypedArgumentIndex = i;
                            break;
                        }
                        i++;
                    }
                }

                methodIdentifier = new IdentifierDeclaration(templ.TemplateIdentifier.Value) { InnerDeclaration=templ.InnerDeclaration };
            }
            else if (e is NewExpression)
            {
                var ne = e as NewExpression;

                if (ne.Arguments != null)
                {
                    int i = 0;
                    foreach (var arg in ne.Arguments)
                    {
                        if (caretLocation >= arg.Location && caretLocation <= arg.EndLocation)
                        {
                            res.CurrentlyTypedArgumentIndex = i;
                            break;
                        }
                        i++;
                    }
                }

                methodIdentifier = ne.ExpressionTypeRepresentation;
            }

            if (methodIdentifier == null)
                return null;

            // Resolve all types, methods etc. which belong to the methodIdentifier
            res.ResolvedTypesOrMethods = ResolveType(methodIdentifier, ctxt);

            if (res.ResolvedTypesOrMethods == null)
                return res;

            // 4),5),6)
            if (e is NewExpression)
            {
                var substitutionList = new List<ResolveResult>();
                foreach (var rr in res.ResolvedTypesOrMethods)
                    if (rr is TypeResult)
                    {
                        var classDef = (rr as TypeResult).ResolvedTypeDefinition as DClassLike;

                        if (classDef == null)
                            continue;

                        //TODO: Regard protection attributes for ctor members
                        foreach (var i in classDef)
                            if (i is DMethod && (i as DMethod).SpecialType == DMethod.MethodType.Constructor)
                                substitutionList.Add(HandleNodeMatch(i, ctxt, resultBase: rr));
                    }

                if (substitutionList.Count > 0)
                    res.ResolvedTypesOrMethods = substitutionList.ToArray();
            }

            // 7)
            else if (e is PostfixExpression_MethodCall)
            {
                var substitutionList = new List<ResolveResult>();

                var nonAliases=TryRemoveAliasesFromResult(res.ResolvedTypesOrMethods);

                foreach (var rr in nonAliases)
                    if (rr is TypeResult)
                    {
                        var classDef = (rr as TypeResult).ResolvedTypeDefinition as DClassLike;

                        if (classDef == null)
                            continue;

                        //TODO: Regard protection attributes for opCall members
                        foreach (var i in classDef)
                            if (i is DMethod && i.Name == "opCall")
                                substitutionList.Add(HandleNodeMatch(i, ctxt, resultBase: rr));
                    }

                if (substitutionList.Count > 0)
                    nonAliases = substitutionList.ToArray();

                res.ResolvedTypesOrMethods = nonAliases;
            }

            return res;
        }
Пример #2
0
        /// <summary>
        /// Parses the code between the start of the parent method's block and the given caret location.
        /// </summary>
        /// <returns>Returns the deepest Statement that exists in the statement hierarchy.</returns>
        public static IStatement ParseBlockStatementUntilCaret(string code, DMethod MethodParent, int caretOffset, CodeLocation caretLocation)
        {
            //HACK: Clear anonymous decl array to ensure that no duplicates occur when calling DParser.ParseBlockStatement()
            MethodParent.AdditionalChildren.Clear();

            var oldBlock = MethodParent.GetSubBlockAt(caretLocation);
            if (oldBlock == null)
                return null;
            var blockOpenerLocation = oldBlock.StartLocation;
            var blockOpenerOffset = blockOpenerLocation.Line <= 0 ? blockOpenerLocation.Column :
                DocumentHelper.LocationToOffset(code, blockOpenerLocation);

            if (blockOpenerOffset >= 0 && caretOffset - blockOpenerOffset > 0)
            {
                var codeToParse = code.Substring(blockOpenerOffset, caretOffset - blockOpenerOffset);

                /*
                 * So, if we're inside of a method, we parse all its 'contents' (statements, expressions, declarations etc.)
                 * to achieve a fully updated insight.
                 */
                var newStmt = DParser.ParseBlockStatement(codeToParse, blockOpenerLocation, MethodParent);

                var ret = newStmt.SearchStatementDeeply(caretLocation);

                return ret == null ? newStmt : ret;
            }

            return null;
        }