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