예제 #1
0
        public override async Task <Hover> Hover(TextDocumentPositionParams @params)
        {
            await _analyzerCreationTask;

            await IfTestWaitForAnalysisCompleteAsync();

            var uri = @params.textDocument.uri;

            _projectFiles.GetAnalysis(@params.textDocument, @params.position, @params._version, out var entry, out var tree);

            TraceMessage($"Hover in {uri} at {@params.position}");

            var analysis = entry?.Analysis;

            if (analysis == null)
            {
                TraceMessage($"No analysis found for {uri}");
                return(EmptyHover);
            }

            tree = GetParseTree(entry, uri, CancellationToken, out var version) ?? tree;

            var index = tree.LocationToIndex(@params.position);
            var w     = new ImportedModuleNameWalker(entry.ModuleName, index);

            tree.Walk(w);
            if (!string.IsNullOrEmpty(w.ImportedName) &&
                _analyzer.Modules.TryImport(w.ImportedName, out var modRef))
            {
                var doc = _displayTextBuilder.GetModuleDocumentation(modRef);
                return(new Hover {
                    contents = doc
                });
            }

            Expression expr;
            SourceSpan?exprSpan;

            Analyzer.InterpreterScope scope = null;

            var finder = new ExpressionFinder(tree, GetExpressionOptions.Hover);

            expr     = finder.GetExpression(@params.position) as Expression;
            exprSpan = expr?.GetSpan(tree);

            if (expr == null)
            {
                TraceMessage($"No hover info found in {uri} at {@params.position}");
                return(EmptyHover);
            }

            TraceMessage($"Getting hover for {expr.ToCodeString(tree, CodeFormattingOptions.Traditional)}");
            var values = analysis.GetValues(expr, @params.position, scope).ToList();

            string originalExpr;

            if (expr is ConstantExpression || expr is ErrorExpression)
            {
                originalExpr = null;
            }
            else
            {
                originalExpr = @params._expr?.Trim();
                if (string.IsNullOrEmpty(originalExpr))
                {
                    originalExpr = expr.ToCodeString(tree, CodeFormattingOptions.Traditional);
                }
            }

            var names = values.Select(GetFullTypeName).Where(n => !string.IsNullOrEmpty(n)).Distinct().ToArray();

            var res = new Hover {
                contents = GetMarkupContent(
                    _displayTextBuilder.GetDocumentation(values, originalExpr),
                    _clientCaps.textDocument?.hover?.contentFormat),
                range      = exprSpan,
                _version   = version,
                _typeNames = names
            };

            return(res);
        }
예제 #2
0
        internal Task <Hover> Hover(TextDocumentPositionParams @params, CancellationToken cancellationToken)
        {
            var uri = @params.textDocument.uri;

            ProjectFiles.GetAnalysis(@params.textDocument, @params.position, @params._version, out var entry, out var tree);

            TraceMessage($"Hover in {uri} at {@params.position}");

            var analysis = entry?.Analysis;

            if (analysis == null)
            {
                TraceMessage($"No analysis found for {uri}");
                return(Task.FromResult(EmptyHover));
            }

            tree = GetParseTree(entry, uri, cancellationToken, out var version) ?? tree;

            Expression expr;
            SourceSpan?exprSpan;

            Analyzer.InterpreterScope scope = null;

            var finder = new ExpressionFinder(tree, GetExpressionOptions.Hover);

            expr     = finder.GetExpression(@params.position) as Expression;
            exprSpan = expr?.GetSpan(tree);

            if (expr == null)
            {
                TraceMessage($"No hover info found in {uri} at {@params.position}");
                return(Task.FromResult(EmptyHover));
            }

            TraceMessage($"Getting hover for {expr.ToCodeString(tree, CodeFormattingOptions.Traditional)}");

            // First try values from expression. This works for the import statement most of the time.
            var values = analysis.GetValues(expr, @params.position, scope).ToList();

            if (values.Count == 0)
            {
                // See if this is hover over import statement
                var index = tree.LocationToIndex(@params.position);
                var w     = new ImportedModuleNameWalker(entry, index, tree);
                tree.Walk(w);

                if (w.ImportedType != null)
                {
                    values = analysis.GetValues(w.ImportedType.Name, @params.position).ToList();
                }
                else
                {
                    var sb   = new StringBuilder();
                    var span = SourceSpan.Invalid;
                    foreach (var n in w.ImportedModules)
                    {
                        if (Analyzer.Modules.TryGetImportedModule(n.Name, out var modRef) && modRef.AnalysisModule != null)
                        {
                            if (sb.Length > 0)
                            {
                                sb.AppendLine();
                                sb.AppendLine();
                            }
                            sb.Append(_displayTextBuilder.GetModuleDocumentation(modRef));
                            span = span.IsValid ? span.Union(n.SourceSpan) : n.SourceSpan;
                        }
                    }
                    if (sb.Length > 0)
                    {
                        return(Task.FromResult(new Hover {
                            contents = sb.ToString(),
                            range = span
                        }));
                    }
                }
            }

            if (values.Count > 0)
            {
                string originalExpr;
                if (expr is ConstantExpression || expr is ErrorExpression)
                {
                    originalExpr = null;
                }
                else
                {
                    originalExpr = @params._expr?.Trim();
                    if (string.IsNullOrEmpty(originalExpr))
                    {
                        originalExpr = expr.ToCodeString(tree, CodeFormattingOptions.Traditional);
                    }
                }

                var names = values.Select(GetFullTypeName).Where(n => !string.IsNullOrEmpty(n)).Distinct().ToArray();
                var res   = new Hover {
                    contents = GetMarkupContent(
                        _displayTextBuilder.GetDocumentation(values, originalExpr),
                        _clientCaps.textDocument?.hover?.contentFormat),
                    range      = exprSpan,
                    _version   = version?.Version,
                    _typeNames = names
                };
                return(Task.FromResult(res));
            }

            return(Task.FromResult(EmptyHover));
        }