예제 #1
0
        public CompletionSet GetCompletions(IGlyphService glyphService)
        {
            if (_snapshot == null)
            {
                return(null);
            }

            var start = _stopwatch.ElapsedMilliseconds;

            var interactiveWindow = _snapshot.TextBuffer.GetInteractiveWindow();
            var pyReplEval        = interactiveWindow?.Evaluator as IPythonInteractiveIntellisense;

            var bufferInfo = PythonTextBufferInfo.TryGetForBuffer(_textBuffer);

            Debug.Assert(bufferInfo != null, "Getting completions from uninitialized buffer " + _textBuffer);

            var analysis = bufferInfo?.AnalysisEntry;
            var analyzer = analysis?.Analyzer;

            if (analyzer == null)
            {
                return(null);
            }

            var point = _point.GetPoint(bufferInfo.CurrentSnapshot);

            var location = VsProjectAnalyzer.TranslateIndex(
                point.Position,
                point.Snapshot,
                analysis
                );

            var triggerChar = _session.GetTriggerCharacter();
            var completions = analyzer.WaitForRequest(analyzer.GetCompletionsAsync(
                                                          analysis,
                                                          location,
                                                          _options.MemberOptions,
                                                          triggerChar == '\0' ? Analysis.LanguageServer.CompletionTriggerKind.Invoked : Analysis.LanguageServer.CompletionTriggerKind.TriggerCharacter,
                                                          triggerChar == '\0' ? null : triggerChar.ToString()
                                                          ), "GetCompletions.GetMembers", null, pyReplEval?.Analyzer == null ? 1 : 5);

            if (completions == null)
            {
                return(null);
            }

            var snapshotSpan = completions._applicableSpan.HasValue
                ? ((SourceSpan)completions._applicableSpan.Value).ToSnapshotSpan(_snapshot)
                : new SnapshotSpan(point, 0);

            _span = bufferInfo.CurrentSnapshot.CreateTrackingSpan(snapshotSpan, SpanTrackingMode.EdgeInclusive);
            var members = completions.items.MaybeEnumerate().Select(c => new CompletionResult(
                                                                        // if a method stub generation (best guess by comparing length),
                                                                        // merge entry based on label, for everything else, use insertion text
                                                                        c.filterText ?? (c.insertText != null && c.insertText.Length <= c.label.Length ? c.insertText : c.label),
                                                                        c.label,
                                                                        c.insertText ?? c.label,
                                                                        c.documentation?.value,
                                                                        Enum.TryParse(c._kind, true, out PythonMemberType mt) ? mt : PythonMemberType.Unknown,
                                                                        null
                                                                        ));

            if (pyReplEval?.Analyzer != null && (string.IsNullOrEmpty(completions._expr) || pyReplEval.Analyzer.ShouldEvaluateForCompletion(completions._expr)))
            {
                var replMembers = pyReplEval.GetMemberNames(completions._expr ?? "");

                if (_services.Python.InteractiveOptions.LiveCompletionsOnly)
                {
                    members = replMembers ?? Array.Empty <CompletionResult>();
                }
                else if (replMembers != null)
                {
                    members = members.Union(replMembers, CompletionMergeKeyComparer.Instance);
                }
            }

            if (pyReplEval == null && (completions._allowSnippet ?? false))
            {
                var expansions = analyzer.WaitForRequest(_services.Python?.GetExpansionCompletionsAsync(), "GetCompletions.GetExpansions", null, 5);
                if (expansions != null)
                {
                    // Expansions should come first, so that they replace our keyword
                    // completions with the more detailed snippets.
                    members = expansions.Union(members, CompletionMergeKeyComparer.Instance);
                }
            }


            var end = _stopwatch.ElapsedMilliseconds;

            if (/*Logging &&*/ (end - start) > TooMuchTime)
            {
                var memberArray = members.ToArray();
                members = memberArray;
                Trace.WriteLine($"{this} lookup time {end - start} for {memberArray.Length} members");
            }

            start = _stopwatch.ElapsedMilliseconds;

            var result = new FuzzyCompletionSet(
                "Python",
                "Python",
                _span,
                members.Select(m => PythonCompletion(glyphService, m)),
                _options,
                CompletionComparer.UnderscoresLast,
                matchInsertionText: true
                )
            {
                CommitByDefault = completions._commitByDefault ?? true
            };


            end = _stopwatch.ElapsedMilliseconds;

            if (/*Logging &&*/ (end - start) > TooMuchTime)
            {
                Trace.WriteLine($"{this} completion set time {end - start} total time {end - start}");
            }

            return(result);
        }