Exemple #1
0
 public InsertionInfo(bool addBlankLine, string insertionText, Range range, string indentation, string abbreviationOpt = null)
 {
     AddBlankLine    = addBlankLine;
     InsertionText   = insertionText;
     Range           = range;
     Indentation     = indentation;
     AbbreviationOpt = abbreviationOpt;
 }
 public static bool RangeEquals(Range r1, Range r2) => PositionEquals(r1.start, r2.start) && PositionEquals(r1.end, r2.end);
Exemple #3
0
        public Hover GetHover(IDocumentAnalysis analysis, SourceLocation location)
        {
            if (analysis is EmptyAnalysis)
            {
                return(new Hover {
                    contents = Resources.AnalysisIsInProgressHover
                });
            }

            ExpressionLocator.FindExpression(analysis.Ast, location,
                                             FindExpressionOptions.Hover, out var node, out var statement, out var hoverScopeStatement);

            if (!HasHover(node) || !(node is Expression expr))
            {
                return(null);
            }

            var range = new Range {
                start = expr.GetStart(analysis.Ast),
                end   = expr.GetEnd(analysis.Ast)
            };

            var eval = analysis.ExpressionEvaluator;

            switch (statement)
            {
            case FromImportStatement fi when node is NameExpression nex: {
                var contents = HandleFromImport(fi, location, hoverScopeStatement, analysis);
                if (contents != null)
                {
                    return(new Hover {
                            contents = contents,
                            range = range
                        });
                }

                break;
            }

            case ImportStatement imp: {
                var contents = HandleImport(imp, location, hoverScopeStatement, analysis);
                if (contents != null)
                {
                    return(new Hover {
                            contents = contents,
                            range = range
                        });
                }

                break;
            }
            }

            IMember     value;
            IPythonType type;

            using (eval.OpenScope(analysis.Document, hoverScopeStatement)) {
                // Here we can be hovering over a class member. Class members are declared
                // as members as well as special variables in the class scope. If this is
                // a name expression (rather than a member expression) and it is a class
                // variable NOT in the immediate class scope, filter it out. Consider:
                //   class A:
                //     x = 1
                //     y = x
                // hover over 'x' in 'y = x' should produce proper tooltip. However, in
                //   class A:
                //     x = 1
                //     def func(self):
                //       y = x
                // hover over 'x' in 'y = x' should not produce tooltip.

                IVariable variable = null;
                if (expr is NameExpression nex)
                {
                    eval.LookupNameInScopes(nex.Name, out _, out variable, LookupOptions.All);
                    if (IsInvalidClassMember(variable, hoverScopeStatement, location.ToIndex(analysis.Ast)))
                    {
                        return(null);
                    }
                }

                value = variable?.Value ?? eval.GetValueFromExpression(expr, LookupOptions.All);
                type  = value?.GetPythonType();
                if (type == null)
                {
                    return(null);
                }
            }

            IPythonType self = null;
            string      name = null;

            // If expression is A.B, trim applicable span to 'B'.
            if (expr is MemberExpression mex)
            {
                name  = mex.Name;
                range = new Range {
                    start = mex.Target.GetEnd(analysis.Ast),
                    end   = range.end
                };

                // In case of a member expression get the target since if we end up with method
                // of a generic class, the function will need specific type to determine its return
                // value correctly. I.e. in x.func() we need to determine type of x (self for func).
                var v = eval.GetValueFromExpression(mex.Target);
                self = v?.GetPythonType();
            }

            // Figure out name, if any
            name = name ?? (node as NameExpression)?.Name;

            // Special case hovering over self or cls
            if ((name.EqualsOrdinal("self") || name.EqualsOrdinal("cls")) && type is IPythonClassType)
            {
                return(new Hover {
                    contents = _docSource.GetHover(null, type),
                    range = range
                });
            }

            name = name == null && statement is ClassDefinition cd ? cd.Name : name;
            name = name == null && statement is FunctionDefinition fd ? fd.Name : name;

            return(new Hover {
                contents = _docSource.GetHover(name, value, self),
                range = range
            });
        }