Example #1
0
        public void ProcessCompletionList(ModuleAnalysis analysis, PythonAst tree, SourceLocation location, CompletionList completions)
        {
            var evt = PostProcessCompletion;

            if (evt != null)
            {
                var e = new Extensibility.CompletionEventArgs(analysis, tree, location, completions);
                try {
                    evt(this, e);
                    completions       = e.CompletionList;
                    completions.items = completions.items ?? Array.Empty <CompletionItem>();
                } catch (Exception ex) when(!ex.IsCriticalException())
                {
                    // We do not replace res in this case.
                }
            }
        }
Example #2
0
        public override Task <CompletionList> Completion(CompletionParams @params)
        {
            var uri = @params.textDocument.uri;
            // Make sure document is enqueued for processing
            var openFile = _openFiles.GetDocument(uri);

            _projectFiles.GetAnalysis(@params.textDocument, @params.position, @params._version, out var entry, out var tree);
            TraceMessage($"Completions in {uri} at {@params.position}");

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

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

            var opts = GetOptions(@params.context);
            var ctxt = new CompletionAnalysis(analysis, tree, @params.position, opts, _displayTextBuilder, this,
                                              () => entry.ReadDocument(_projectFiles.GetPart(uri), out _));
            var members = ctxt.GetCompletionsFromString(@params._expr) ?? ctxt.GetCompletions();

            if (members == null)
            {
                TraceMessage($"Do not trigger at {@params.position} in {uri}");
                return(Task.FromResult(new CompletionList()));
            }

            if (_settings.SuppressAdvancedMembers)
            {
                members = members.Where(m => !m.label.StartsWith("__"));
            }

            var filterKind = @params.context?._filterKind;

            if (filterKind.HasValue && filterKind != CompletionItemKind.None)
            {
                TraceMessage($"Only returning {filterKind.Value} items");
                members = members.Where(m => m.kind == filterKind.Value);
            }

            var res = new CompletionList {
                items            = members.ToArray(),
                _expr            = ctxt.ParentExpression?.ToCodeString(tree, CodeFormattingOptions.Traditional),
                _commitByDefault = ctxt.ShouldCommitByDefault
            };

            SourceLocation trigger = @params.position;

            if (ctxt.ApplicableSpan.HasValue)
            {
                res._applicableSpan = ctxt.ApplicableSpan;
            }
            else if (ctxt.Node != null)
            {
                var span = ctxt.Node.GetSpan(tree);
                if (@params.context?.triggerKind == CompletionTriggerKind.TriggerCharacter)
                {
                    if (span.End > trigger)
                    {
                        span = new SourceSpan(span.Start, trigger);
                    }
                }
                if (span.End != span.Start)
                {
                    res._applicableSpan = span;
                }
            }
            else if (@params.context?.triggerKind == CompletionTriggerKind.TriggerCharacter)
            {
                var ch = @params.context?.triggerCharacter.FirstOrDefault() ?? '\0';
                res._applicableSpan = new SourceSpan(
                    trigger.Line,
                    Tokenizer.IsIdentifierStartChar(ch) ? Math.Max(1, trigger.Column - 1) : trigger.Column,
                    trigger.Line,
                    trigger.Column
                    );
            }

            LogMessage(MessageType.Info, $"Found {res.items.Length} completions for {uri} at {@params.position} after filtering");

            var evt = PostProcessCompletion;

            if (evt != null)
            {
                var e = new Extensibility.CompletionEventArgs(analysis, tree, @params.position, res);
                try {
                    evt(this, e);
                    res       = e.CompletionList;
                    res.items = res.items ?? Array.Empty <CompletionItem>();
                    LogMessage(MessageType.Info, $"Found {res.items.Length} completions after hooks");
                } catch (Exception ex) when(!ex.IsCriticalException())
                {
                    // We do not replace res in this case.
                    LogMessage(MessageType.Error, $"Error while post-processing completions: {ex}");
                }
            }

            return(Task.FromResult(res));
        }