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