示例#1
0
        /// <summary>
        /// Reparses the code of the current scope and returns the object (either IExpression or ITypeDeclaration derivative)
        /// that is beneath the caret location.
        ///
        /// Used for code completion/symbol resolution.
        /// Mind the extra options that might be passed via the Options parameter.
        /// </summary>
        /// <param name="ctxt">Can be null</param>
        public static ISyntaxRegion GetScopedCodeObject(IEditorData editor,
                                                        ResolverContextStack ctxt = null,
                                                        AstReparseOptions Options = 0)
        {
            if (ctxt == null)
            {
                ctxt = ResolverContextStack.Create(editor);
            }

            var code = editor.ModuleCode;

            int  start         = 0;
            var  startLocation = CodeLocation.Empty;
            bool IsExpression  = false;

            if (ctxt.CurrentContext.ScopedStatement is IExpressionContainingStatement)
            {
                var         exprs      = ((IExpressionContainingStatement)ctxt.CurrentContext.ScopedStatement).SubExpressions;
                IExpression targetExpr = null;

                if (exprs != null)
                {
                    foreach (var ex in exprs)
                    {
                        if ((targetExpr = ExpressionHelper.SearchExpressionDeeply(ex, editor.CaretLocation, true))
                            != ex)
                        {
                            break;
                        }
                    }
                }

                if (targetExpr != null && editor.CaretLocation >= targetExpr.Location && editor.CaretLocation <= targetExpr.EndLocation)
                {
                    startLocation = targetExpr.Location;
                    start         = DocumentHelper.LocationToOffset(editor.ModuleCode, startLocation);
                    IsExpression  = true;
                }
            }

            if (!IsExpression)
            {
                // First check if caret is inside a comment/string etc.
                int lastStart    = -1;
                int lastEnd      = -1;
                var caretContext = CaretContextAnalyzer.GetTokenContext(code, editor.CaretOffset, out lastStart, out lastEnd);

                // Return if comment etc. found
                if (caretContext != TokenContext.None)
                {
                    return(null);
                }

                start = CaretContextAnalyzer.SearchExpressionStart(code, editor.CaretOffset - 1,
                                                                   (lastEnd > 0 && lastEnd < editor.CaretOffset) ? lastEnd : 0);
                startLocation = DocumentHelper.OffsetToLocation(editor.ModuleCode, start);
            }

            if (start < 0 || editor.CaretOffset <= start)
            {
                return(null);
            }

            var expressionCode = code.Substring(start, Options.HasFlag(AstReparseOptions.AlsoParseBeyondCaret) ? code.Length - start : editor.CaretOffset - start);

            var parser = DParser.Create(new StringReader(expressionCode));

            parser.Lexer.SetInitialLocation(startLocation);
            parser.Step();

            if (!IsExpression && Options.HasFlag(AstReparseOptions.OnlyAssumeIdentifierList) && parser.Lexer.LookAhead.Kind == DTokens.Identifier)
            {
                return(parser.IdentifierList());
            }
            else if (IsExpression || parser.IsAssignExpression())
            {
                if (Options.HasFlag(AstReparseOptions.ReturnRawParsedExpression))
                {
                    return(parser.AssignExpression());
                }
                else
                {
                    return(ExpressionHelper.SearchExpressionDeeply(parser.AssignExpression(), editor.CaretLocation, Options.HasFlag(AstReparseOptions.WatchForParamExpressions)));
                }
            }
            else
            {
                return(parser.Type());
            }
        }
示例#2
0
        /// <summary>
        /// Reparses the code of the current scope and returns the object (either IExpression or ITypeDeclaration derivative)
        /// that is beneath the caret location.
        ///
        /// Used for code completion/symbol resolution.
        /// Mind the extra options that might be passed via the Options parameter.
        /// </summary>
        /// <param name="ctxt">Can be null</param>
        public static ISyntaxRegion GetScopedCodeObject(IEditorData editor,
                                                        AstReparseOptions Options = AstReparseOptions.AlsoParseBeyondCaret,
                                                        ResolutionContext ctxt    = null)
        {
            if (ctxt == null)
            {
                ctxt = ResolutionContext.Create(editor);
            }

            var code = editor.ModuleCode;

            int  start         = 0;
            var  startLocation = CodeLocation.Empty;
            bool IsExpression  = false;

            if (ctxt.CurrentContext.ScopedStatement is IExpressionContainingStatement)
            {
                var         exprs      = ((IExpressionContainingStatement)ctxt.CurrentContext.ScopedStatement).SubExpressions;
                IExpression targetExpr = null;

                if (exprs != null)
                {
                    foreach (var ex in exprs)
                    {
                        if ((targetExpr = ExpressionHelper.SearchExpressionDeeply(ex, editor.CaretLocation))
                            != ex)
                        {
                            break;
                        }
                    }
                }

                if (targetExpr != null && editor.CaretLocation >= targetExpr.Location && editor.CaretLocation <= targetExpr.EndLocation)
                {
                    startLocation = targetExpr.Location;
                    start         = DocumentHelper.GetOffsetByRelativeLocation(editor.ModuleCode, editor.CaretLocation, editor.CaretOffset, startLocation);
                    IsExpression  = true;
                }
            }

            if (!IsExpression)
            {
                // First check if caret is inside a comment/string etc.
                int lastStart = 0;
                int lastEnd   = 0;
                if ((Options & AstReparseOptions.DontCheckForCommentsOrStringSurrounding) == 0)
                {
                    var caretContext = CaretContextAnalyzer.GetTokenContext(code, editor.CaretOffset, out lastStart, out lastEnd);

                    // Return if comment etc. found
                    if (caretContext != TokenContext.None)
                    {
                        return(null);
                    }
                }

                // Could be somewhere in an ITypeDeclaration..

                if (editor.CaretOffset < 0 || editor.CaretOffset >= code.Length)
                {
                    return(null);
                }

                if (Lexer.IsIdentifierPart(code[editor.CaretOffset]))
                {
                    start = editor.CaretOffset;
                }
                else if (editor.CaretOffset > 0 && Lexer.IsIdentifierPart(code[editor.CaretOffset - 1]))
                {
                    start = editor.CaretOffset - 1;
                }


                start = CaretContextAnalyzer.SearchExpressionStart(code, start,
                                                                   (lastEnd > 0 && lastEnd < editor.CaretOffset) ? lastEnd : 0);
                startLocation = DocumentHelper.OffsetToLocation(editor.ModuleCode, start);
            }

            if (start < 0 || editor.CaretOffset < start)
            {
                return(null);
            }

            var sv     = new StringView(code, start, Options.HasFlag(AstReparseOptions.AlsoParseBeyondCaret) ? code.Length - start : editor.CaretOffset - start);
            var parser = DParser.Create(sv);

            parser.Lexer.SetInitialLocation(startLocation);
            parser.Step();

            ITypeDeclaration td;

            if (!IsExpression && Options.HasFlag(AstReparseOptions.OnlyAssumeIdentifierList) && parser.Lexer.LookAhead.Kind == DTokens.Identifier)
            {
                td = parser.IdentifierList();
            }
            else if (IsExpression || parser.IsAssignExpression())
            {
                if (Options.HasFlag(AstReparseOptions.ReturnRawParsedExpression))
                {
                    return(parser.AssignExpression());
                }
                else
                {
                    return(ExpressionHelper.SearchExpressionDeeply(parser.AssignExpression(), editor.CaretLocation));
                }
            }
            else
            {
                td = parser.Type();
            }

            if (Options.HasFlag(AstReparseOptions.ReturnRawParsedExpression))
            {
                return(td);
            }

            while (td != null && td.InnerDeclaration != null && editor.CaretLocation <= td.InnerDeclaration.EndLocation)
            {
                td = td.InnerDeclaration;
            }

            return(td);
        }