From 6f29e131605164509e58d32d1579e55842303b0b Mon Sep 17 00:00:00 2001 From: Ankita Khera <40616383+akhera99@users.noreply.github.com> Date: Thu, 23 Jan 2025 13:39:12 -0800 Subject: [PATCH] On-the-fly-docs -- Add quota exceeded dialogue (#76877) * wip * wip * revert * comments * pr feedback * pr feedback * pr feedback --- .../QuickInfo/OnTheFlyDocsView.xaml.cs | 103 ++++++++++++++++-- .../QuickInfo/OnTheFlyDocsViewFactory.cs | 8 +- .../Core/EditorFeaturesResources.resx | 4 + .../Core/xlf/EditorFeaturesResources.cs.xlf | 5 + .../Core/xlf/EditorFeaturesResources.de.xlf | 5 + .../Core/xlf/EditorFeaturesResources.es.xlf | 5 + .../Core/xlf/EditorFeaturesResources.fr.xlf | 5 + .../Core/xlf/EditorFeaturesResources.it.xlf | 5 + .../Core/xlf/EditorFeaturesResources.ja.xlf | 5 + .../Core/xlf/EditorFeaturesResources.ko.xlf | 5 + .../Core/xlf/EditorFeaturesResources.pl.xlf | 5 + .../xlf/EditorFeaturesResources.pt-BR.xlf | 5 + .../Core/xlf/EditorFeaturesResources.ru.xlf | 5 + .../Core/xlf/EditorFeaturesResources.tr.xlf | 5 + .../xlf/EditorFeaturesResources.zh-Hans.xlf | 5 + .../xlf/EditorFeaturesResources.zh-Hant.xlf | 5 + ...xternalCSharpCopilotCodeAnalysisService.cs | 2 +- .../AbstractCopilotCodeAnalysisService.cs | 6 +- ...otCodeAnalysisService.ReflectionWrapper.cs | 6 +- .../CSharpCopilotCodeAnalysisService.cs | 2 +- .../Copilot/InternalAPI.Unshipped.txt | 2 +- .../Test2/CodeFixes/CodeFixServiceTests.vb | 4 +- .../Copilot/ICopilotCodeAnalysisService.cs | 2 +- 23 files changed, 180 insertions(+), 24 deletions(-) diff --git a/src/EditorFeatures/Core.Wpf/QuickInfo/OnTheFlyDocsView.xaml.cs b/src/EditorFeatures/Core.Wpf/QuickInfo/OnTheFlyDocsView.xaml.cs index f2ab905041903..424d1c8c775d2 100644 --- a/src/EditorFeatures/Core.Wpf/QuickInfo/OnTheFlyDocsView.xaml.cs +++ b/src/EditorFeatures/Core.Wpf/QuickInfo/OnTheFlyDocsView.xaml.cs @@ -3,8 +3,11 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -20,6 +23,9 @@ using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Language.Intellisense; using Microsoft.VisualStudio.PlatformUI; +using Microsoft.VisualStudio.Shell; +using Microsoft.VisualStudio.Shell.Interop; +using Microsoft.VisualStudio.Telemetry; using Microsoft.VisualStudio.Text.Adornments; using Microsoft.VisualStudio.Text.Editor; using Roslyn.Utilities; @@ -40,6 +46,8 @@ internal sealed partial class OnTheFlyDocsView : UserControl, INotifyPropertyCha private readonly OnTheFlyDocsInfo _onTheFlyDocsInfo; private readonly ContentControl _responseControl = new(); private readonly CancellationTokenSource _cancellationTokenSource = new(); + private readonly List quotaExceededContent; + private readonly IServiceProvider _serviceProvider; private OnTheFlyDocsState _currentState = OnTheFlyDocsState.OnDemandLink; @@ -51,6 +59,11 @@ internal sealed partial class OnTheFlyDocsView : UserControl, INotifyPropertyCha /// public event EventHandler ResultsRequested; + /// + /// Event that fires when the user requests to upgrade their Copilot plan. + /// + public event EventHandler? PlanUpgradeRequested; + #pragma warning disable CA1822 // Mark members as static /// /// Used to display the "On the fly documentation" directly in the associated XAML file. @@ -58,7 +71,9 @@ internal sealed partial class OnTheFlyDocsView : UserControl, INotifyPropertyCha public string OnTheFlyDocumentation => EditorFeaturesResources.On_the_fly_documentation; #pragma warning restore CA1822 // Mark members as static - public OnTheFlyDocsView(ITextView textView, IViewElementFactoryService viewElementFactoryService, IAsynchronousOperationListenerProvider listenerProvider, IAsyncQuickInfoSession asyncQuickInfoSession, IThreadingContext threadingContext, QuickInfoOnTheFlyDocsElement onTheFlyDocsElement) + public OnTheFlyDocsView(ITextView textView, IViewElementFactoryService viewElementFactoryService, + IAsynchronousOperationListenerProvider listenerProvider, IAsyncQuickInfoSession asyncQuickInfoSession, + IThreadingContext threadingContext, QuickInfoOnTheFlyDocsElement onTheFlyDocsElement, IServiceProvider serviceProvider) { _textView = textView; _viewElementFactoryService = viewElementFactoryService; @@ -67,6 +82,7 @@ public OnTheFlyDocsView(ITextView textView, IViewElementFactoryService viewEleme _threadingContext = threadingContext; _onTheFlyDocsInfo = onTheFlyDocsElement.Info; _document = onTheFlyDocsElement.Document; + _serviceProvider = serviceProvider; var sparkle = new ImageElement(new VisualStudio.Core.Imaging.ImageId(CopilotConstants.CopilotIconMonikerGuid, CopilotConstants.CopilotIconSparkleId)); object onDemandLinkText = _onTheFlyDocsInfo.IsContentExcluded @@ -111,6 +127,34 @@ public OnTheFlyDocsView(ITextView textView, IViewElementFactoryService viewEleme _responseControl, ])); + // Locates the "upgrade now" link in the localized text, surrounded by square brackets. + var quotaExceededMatch = Regex.Match( + EditorFeaturesResources.Chat_limit_reached_upgrade_now_or_wait_for_the_limit_to_reset, + @"^(.*)\[(.*)\](.*)$"); + if (quotaExceededMatch == null) + { + // The text wasn't localized correctly. Assert and fallback to showing it verbatim. + Debug.Fail("Copilot Hover quota exceeded message was not correctly localized."); + quotaExceededContent = [new ClassifiedTextRun( + ClassifiedTextElement.TextClassificationTypeName, + EditorFeaturesResources.Chat_limit_reached_upgrade_now_or_wait_for_the_limit_to_reset)]; + } + else + { + quotaExceededContent = [ + new ClassifiedTextRun( + ClassifiedTextElement.TextClassificationTypeName, + quotaExceededMatch.Groups[1].Value), + new ClassifiedTextRun( + ClassifiedTextElement.TextClassificationTypeName, + quotaExceededMatch.Groups[2].Value, + () => this.PlanUpgradeRequested?.Invoke(this, EventArgs.Empty)), + new ClassifiedTextRun( + ClassifiedTextElement.TextClassificationTypeName, + quotaExceededMatch.Groups[3].Value), + ]; + } + ResultsRequested += (_, _) => PopulateAIDocumentationElements(_cancellationTokenSource.Token); _asyncQuickInfoSession.StateChanged += (_, _) => OnQuickInfoSessionChanged(); InitializeComponent(); @@ -135,31 +179,61 @@ private async Task SetResultTextAsync(ICopilotCodeAnalysisService copilotService try { - var response = await copilotService.GetOnTheFlyDocsAsync(_onTheFlyDocsInfo.SymbolSignature, _onTheFlyDocsInfo.DeclarationCode, _onTheFlyDocsInfo.Language, cancellationToken).ConfigureAwait(false); + var (responseString, isQuotaExceeded) = await copilotService.GetOnTheFlyDocsAsync(_onTheFlyDocsInfo.SymbolSignature, _onTheFlyDocsInfo.DeclarationCode, _onTheFlyDocsInfo.Language, cancellationToken).ConfigureAwait(false); var copilotRequestTime = stopwatch.Elapsed; await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); - if (response is null || response.Length == 0) + if (string.IsNullOrEmpty(responseString)) { - SetResultText(EditorFeaturesResources.An_error_occurred_while_generating_documentation_for_this_code); - CurrentState = OnTheFlyDocsState.Finished; - Logger.Log(FunctionId.Copilot_On_The_Fly_Docs_Error_Displayed, KeyValueLogMessage.Create(m => + // If the responseStatus is 8, then that means the quota has been exceeded. + if (isQuotaExceeded) { - m["ElapsedTime"] = copilotRequestTime; - }, LogLevel.Information)); + this.PlanUpgradeRequested += (_, _) => + { + // GUID and command ID from + // https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/45121/Free-SKU-Handling-Guidance-and-Recommendations + var uiShell = _serviceProvider.GetServiceOnMainThread(); + uiShell.PostExecCommand( + new Guid("39B0DEDE-D931-4A92-9AA2-3447BC4998DC"), + 0x3901, + nCmdexecopt: 0, + pvaIn: null); + + _asyncQuickInfoSession.DismissAsync(); + + // Telemetry to track when users reach the quota of the Copilot Free plan. + var telemetryEvent = new OperationEvent( + "vs/copilot/showcopilotfreestatus", + TelemetryResult.Success); + telemetryEvent.Properties["vs.copilot.source"] = "CSharpOnTheFlyDocs"; + TelemetryService.DefaultSession.PostEvent(telemetryEvent); + }; + + ShowQuotaExceededResult(); + } + else + { + SetResultText(EditorFeaturesResources.An_error_occurred_while_generating_documentation_for_this_code); + Logger.Log(FunctionId.Copilot_On_The_Fly_Docs_Error_Displayed, KeyValueLogMessage.Create(m => + { + m["ElapsedTime"] = copilotRequestTime; + }, LogLevel.Information)); + } + + CurrentState = OnTheFlyDocsState.Finished; } else { - SetResultText(response); + SetResultText(responseString); CurrentState = OnTheFlyDocsState.Finished; Logger.Log(FunctionId.Copilot_On_The_Fly_Docs_Results_Displayed, KeyValueLogMessage.Create(m => { m["ElapsedTime"] = copilotRequestTime; - m["ResponseLength"] = response.Length; + m["ResponseLength"] = responseString.Length; }, LogLevel.Information)); } } @@ -222,6 +296,15 @@ public void SetResultText(string text) new ContainerElement(ContainerElementStyle.Wrapped, new ClassifiedTextElement([new ClassifiedTextRun(ClassificationTypeNames.Text, text)]))); } + /// + /// Shows a result message for exceeding the quota of the Copilot Free plan. + /// + public void ShowQuotaExceededResult() + { + _responseControl.Content = ToUIElement(new ContainerElement(ContainerElementStyle.Stacked, + [new ContainerElement(ContainerElementStyle.Wrapped, new ClassifiedTextElement(this.quotaExceededContent))])); + } + private void OnPropertyChanged(ref T member, T value, [CallerMemberName] string? name = null) { member = value; diff --git a/src/EditorFeatures/Core.Wpf/QuickInfo/OnTheFlyDocsViewFactory.cs b/src/EditorFeatures/Core.Wpf/QuickInfo/OnTheFlyDocsViewFactory.cs index 35ee7beb5349d..c0b96f3cf63ea 100644 --- a/src/EditorFeatures/Core.Wpf/QuickInfo/OnTheFlyDocsViewFactory.cs +++ b/src/EditorFeatures/Core.Wpf/QuickInfo/OnTheFlyDocsViewFactory.cs @@ -12,6 +12,7 @@ using Microsoft.CodeAnalysis.QuickInfo.Presentation; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Language.Intellisense; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Text.Adornments; using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.Utilities; @@ -28,15 +29,18 @@ internal sealed class OnTheFlyDocsViewFactory : IViewElementFactory private readonly IAsynchronousOperationListenerProvider _listenerProvider; private readonly IAsyncQuickInfoBroker _asyncQuickInfoBroker; private readonly IThreadingContext _threadingContext; + private readonly IServiceProvider _serviceProvider; [ImportingConstructor] [Obsolete(MefConstruction.ImportingConstructorMessage, error: true)] - public OnTheFlyDocsViewFactory(IViewElementFactoryService factoryService, IAsynchronousOperationListenerProvider listenerProvider, IAsyncQuickInfoBroker asyncQuickInfoBroker, IThreadingContext threadingContext) + public OnTheFlyDocsViewFactory(IViewElementFactoryService factoryService, IAsynchronousOperationListenerProvider listenerProvider, + IAsyncQuickInfoBroker asyncQuickInfoBroker, IThreadingContext threadingContext, SVsServiceProvider serviceProvider) { _factoryService = factoryService; _listenerProvider = listenerProvider; _asyncQuickInfoBroker = asyncQuickInfoBroker; _threadingContext = threadingContext; + _serviceProvider = serviceProvider; } public TView? CreateViewElement(ITextView textView, object model) where TView : class @@ -64,6 +68,6 @@ public OnTheFlyDocsViewFactory(IViewElementFactoryService factoryService, IAsync OnTheFlyDocsLogger.LogShowedOnTheFlyDocsLinkWithDocComments(); } - return new OnTheFlyDocsView(textView, _factoryService, _listenerProvider, quickInfoSession, _threadingContext, onTheFlyDocsElement) as TView; + return new OnTheFlyDocsView(textView, _factoryService, _listenerProvider, quickInfoSession, _threadingContext, onTheFlyDocsElement, _serviceProvider) as TView; } } diff --git a/src/EditorFeatures/Core/EditorFeaturesResources.resx b/src/EditorFeatures/Core/EditorFeaturesResources.resx index 0d2ddf466abbc..42d5a9f806b9d 100644 --- a/src/EditorFeatures/Core/EditorFeaturesResources.resx +++ b/src/EditorFeatures/Core/EditorFeaturesResources.resx @@ -950,4 +950,8 @@ Do you want to proceed? 'Describe with Copilot' is unavailable since the referenced document is excluded by your organization. + + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + \ No newline at end of file diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf index deadfb68a2575..cda4910f11c0d 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.cs.xlf @@ -17,6 +17,11 @@ Aplikují se změny. + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information Výpočet informací Encapsulate Field diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf index 7c5542620b5d3..223527ee2ae83 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.de.xlf @@ -17,6 +17,11 @@ Änderungen werden übernommen + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information Berechnen von "Kapselungsfeld"-Informationen diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf index 7def27cefa87b..8f96fcc9c21d7 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.es.xlf @@ -17,6 +17,11 @@ Aplicando cambios + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information Calculando información de "Encapsular campo" diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf index 77e83a00bb46b..cd4dc9731af30 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.fr.xlf @@ -17,6 +17,11 @@ Application des changements + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information Calcul des informations « Encapsuler le champ » diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf index 494d58240b5f9..264651a81a1d2 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.it.xlf @@ -17,6 +17,11 @@ Applicazione delle modifiche in corso + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information Calcolo delle informazioni su 'Incapsula campo' diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf index 173a32b73c844..162b9ff3a5da9 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ja.xlf @@ -17,6 +17,11 @@ 変更の適用 + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information 'フィールドのカプセル化' 情報を計算中 diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf index 6af82a2e1d86a..967a8c3d65f76 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ko.xlf @@ -17,6 +17,11 @@ 변경 내용 적용 + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information 'Encapsulate Field' 정보 계산 diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf index db20f5ea0e5ab..13c31e460e558 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pl.xlf @@ -17,6 +17,11 @@ Stosowanie zmian + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information Obliczanie informacji „Hermetyzuj pole” diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf index 3106e84c43329..f0b76297e818e 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.pt-BR.xlf @@ -17,6 +17,11 @@ Aplicando mudanças + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information Computando informações de 'Encapsular Campo' diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf index 159f84ac42a3b..882882e284155 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.ru.xlf @@ -17,6 +17,11 @@ Применение изменений + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information Вычисление сведений "Инкапсуляция поля" diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf index 98f893e21b5cc..6aff6dc59e379 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.tr.xlf @@ -17,6 +17,11 @@ Değişiklikler uygulanıyor + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information 'Alanı Kapsülle' bilgileri hesaplanıyor diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf index e626b6675a912..0bed7187047f0 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hans.xlf @@ -17,6 +17,11 @@ 应用更改 + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information 计算“封装字段”信息 diff --git a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf index 3ef849680bea5..7daf637ef2194 100644 --- a/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf +++ b/src/EditorFeatures/Core/xlf/EditorFeaturesResources.zh-Hant.xlf @@ -17,6 +17,11 @@ 正在套用變更 + + Chat limit reached, [upgrade now] or wait for the limit to reset. + Chat limit reached, [upgrade now] or wait for the limit to reset. + The text surrounded by "[" and "]" characters will be hyperlinked. Please ensure the localized text still has "[" and "]" characters. + Computing 'Encapsulate Field' information 正在計算 [封裝欄位] 資訊 diff --git a/src/EditorFeatures/ExternalAccess/Copilot/Analyzer/IExternalCSharpCopilotCodeAnalysisService.cs b/src/EditorFeatures/ExternalAccess/Copilot/Analyzer/IExternalCSharpCopilotCodeAnalysisService.cs index 3a8485c1f14b2..1a0fed9bd383b 100644 --- a/src/EditorFeatures/ExternalAccess/Copilot/Analyzer/IExternalCSharpCopilotCodeAnalysisService.cs +++ b/src/EditorFeatures/ExternalAccess/Copilot/Analyzer/IExternalCSharpCopilotCodeAnalysisService.cs @@ -18,6 +18,6 @@ internal interface IExternalCSharpCopilotCodeAnalysisService Task> AnalyzeDocumentAsync(Document document, TextSpan? span, string promptTitle, CancellationToken cancellationToken); Task> GetCachedDiagnosticsAsync(Document document, string promptTitle, CancellationToken cancellationToken); Task StartRefinementSessionAsync(Document oldDocument, Document newDocument, Diagnostic? primaryDiagnostic, CancellationToken cancellationToken); - Task GetOnTheFlyDocsAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken); + Task<(string responseString, bool isQuotaExceeded)> GetOnTheFlyDocsAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken); Task IsFileExcludedAsync(string filePath, CancellationToken cancellationToken); } diff --git a/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/AbstractCopilotCodeAnalysisService.cs b/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/AbstractCopilotCodeAnalysisService.cs index 1c0353b079b42..a75f5e8f6f026 100644 --- a/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/AbstractCopilotCodeAnalysisService.cs +++ b/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/AbstractCopilotCodeAnalysisService.cs @@ -39,7 +39,7 @@ internal abstract class AbstractCopilotCodeAnalysisService(IDiagnosticsRefresher protected abstract Task> AnalyzeDocumentCoreAsync(Document document, TextSpan? span, string promptTitle, CancellationToken cancellationToken); protected abstract Task> GetCachedDiagnosticsCoreAsync(Document document, string promptTitle, CancellationToken cancellationToken); protected abstract Task StartRefinementSessionCoreAsync(Document oldDocument, Document newDocument, Diagnostic? primaryDiagnostic, CancellationToken cancellationToken); - protected abstract Task GetOnTheFlyDocsCoreAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken); + protected abstract Task<(string responseString, bool isQuotaExceeded)> GetOnTheFlyDocsCoreAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken); protected abstract Task IsFileExcludedCoreAsync(string filePath, CancellationToken cancellationToken); public Task IsAvailableAsync(CancellationToken cancellationToken) @@ -173,10 +173,10 @@ public async Task StartRefinementSessionAsync(Document oldDocument, Document new await StartRefinementSessionCoreAsync(oldDocument, newDocument, primaryDiagnostic, cancellationToken).ConfigureAwait(false); } - public async Task GetOnTheFlyDocsAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken) + public async Task<(string responseString, bool isQuotaExceeded)> GetOnTheFlyDocsAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken) { if (!await IsAvailableAsync(cancellationToken).ConfigureAwait(false)) - return string.Empty; + return (string.Empty, false); return await GetOnTheFlyDocsCoreAsync(symbolSignature, declarationCode, language, cancellationToken).ConfigureAwait(false); } diff --git a/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/CSharp/CSharpCopilotCodeAnalysisService.ReflectionWrapper.cs b/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/CSharp/CSharpCopilotCodeAnalysisService.ReflectionWrapper.cs index 7b3b41c63c1c6..6f33ec3b27cf8 100644 --- a/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/CSharp/CSharpCopilotCodeAnalysisService.ReflectionWrapper.cs +++ b/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/CSharp/CSharpCopilotCodeAnalysisService.ReflectionWrapper.cs @@ -19,7 +19,7 @@ namespace Microsoft.CodeAnalysis.ExternalAccess.Copilot.Internal.Analyzer.CSharp using GetCachedDiagnosticsAsyncDelegateType = Func>>; using IsAvailableAsyncDelegateType = Func>; using StartRefinementSessionAsyncDelegateType = Func; -using GetOnTheFlyDocsAsyncDelegateType = Func, string, CancellationToken, Task>; +using GetOnTheFlyDocsAsyncDelegateType = Func, string, CancellationToken, Task<(string responseString, bool isQuotaExceeded)>>; using IsAnyExclusionAsyncDelegateType = Func>; using IsFileExcludedAsyncDelegateType = Func>; @@ -159,10 +159,10 @@ public Task StartRefinementSessionAsync(Document oldDocument, Document newDocume return _lazyStartRefinementSessionAsyncDelegate.Value(oldDocument, newDocument, primaryDiagnostic, cancellationToken); } - public async Task GetOnTheFlyDocsAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken) + public async Task<(string responseString, bool isQuotaExceeded)> GetOnTheFlyDocsAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken) { if (_lazyGetOnTheFlyDocsAsyncDelegate.Value is null) - return string.Empty; + return (string.Empty, false); return await _lazyGetOnTheFlyDocsAsyncDelegate.Value(symbolSignature, declarationCode, language, cancellationToken).ConfigureAwait(false); } diff --git a/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/CSharp/CSharpCopilotCodeAnalysisService.cs b/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/CSharp/CSharpCopilotCodeAnalysisService.cs index 317a234a68c11..8d5a5a91088af 100644 --- a/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/CSharp/CSharpCopilotCodeAnalysisService.cs +++ b/src/EditorFeatures/ExternalAccess/Copilot/Internal/Analyzer/CSharp/CSharpCopilotCodeAnalysisService.cs @@ -57,7 +57,7 @@ protected override Task IsAvailableCoreAsync(CancellationToken cancellatio protected override Task StartRefinementSessionCoreAsync(Document oldDocument, Document newDocument, Diagnostic? primaryDiagnostic, CancellationToken cancellationToken) => _lazyExternalCopilotService.Value.StartRefinementSessionAsync(oldDocument, newDocument, primaryDiagnostic, cancellationToken); - protected override Task GetOnTheFlyDocsCoreAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken) + protected override Task<(string responseString, bool isQuotaExceeded)> GetOnTheFlyDocsCoreAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken) => _lazyExternalCopilotService.Value.GetOnTheFlyDocsAsync(symbolSignature, declarationCode, language, cancellationToken); protected override async Task> GetDiagnosticsIntersectWithSpanAsync( diff --git a/src/EditorFeatures/ExternalAccess/Copilot/InternalAPI.Unshipped.txt b/src/EditorFeatures/ExternalAccess/Copilot/InternalAPI.Unshipped.txt index 9f06d5d62b1b3..546acd188e8fa 100644 --- a/src/EditorFeatures/ExternalAccess/Copilot/InternalAPI.Unshipped.txt +++ b/src/EditorFeatures/ExternalAccess/Copilot/InternalAPI.Unshipped.txt @@ -8,7 +8,7 @@ Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysis Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysisService.AnalyzeDocumentAsync(Microsoft.CodeAnalysis.Document! document, Microsoft.CodeAnalysis.Text.TextSpan? span, string! promptTitle, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task>! Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysisService.GetAvailablePromptTitlesAsync(Microsoft.CodeAnalysis.Document! document, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task>! Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysisService.GetCachedDiagnosticsAsync(Microsoft.CodeAnalysis.Document! document, string! promptTitle, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task>! -Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysisService.GetOnTheFlyDocsAsync(string! symbolSignature, System.Collections.Immutable.ImmutableArray declarationCode, string! language, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! +Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysisService.GetOnTheFlyDocsAsync(string! symbolSignature, System.Collections.Immutable.ImmutableArray declarationCode, string! language, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task<(string! responseString, bool isQuotaExceeded)>! Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysisService.IsAvailableAsync(System.Threading.CancellationToken cancellation) -> System.Threading.Tasks.Task! Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysisService.IsFileExcludedAsync(string! filePath, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! Microsoft.CodeAnalysis.ExternalAccess.Copilot.IExternalCSharpCopilotCodeAnalysisService.StartRefinementSessionAsync(Microsoft.CodeAnalysis.Document! oldDocument, Microsoft.CodeAnalysis.Document! newDocument, Microsoft.CodeAnalysis.Diagnostic? primaryDiagnostic, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task! diff --git a/src/EditorFeatures/Test2/CodeFixes/CodeFixServiceTests.vb b/src/EditorFeatures/Test2/CodeFixes/CodeFixServiceTests.vb index 466596e4df790..f2daa492cf9c6 100644 --- a/src/EditorFeatures/Test2/CodeFixes/CodeFixServiceTests.vb +++ b/src/EditorFeatures/Test2/CodeFixes/CodeFixServiceTests.vb @@ -351,8 +351,8 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests Return Task.CompletedTask End Function - Public Function GetOnTheFlyDocsAsync(symbolSignature As String, declarationCode As ImmutableArray(Of String), language As String, cancellationToken As CancellationToken) As Task(Of String) Implements ICopilotCodeAnalysisService.GetOnTheFlyDocsAsync - Return Task.FromResult("") + Public Function GetOnTheFlyDocsAsync(symbolSignature As String, declarationCode As ImmutableArray(Of String), language As String, cancellationToken As CancellationToken) As Task(Of (responseString As String, isQuotaExceeded As Boolean)) Implements ICopilotCodeAnalysisService.GetOnTheFlyDocsAsync + Return Task.FromResult(("", False)) End Function Public Function IsFileExcludedAsync(filePath As String, cancellationToken As CancellationToken) As Task(Of Boolean) Implements ICopilotCodeAnalysisService.IsFileExcludedAsync diff --git a/src/Features/Core/Portable/Copilot/ICopilotCodeAnalysisService.cs b/src/Features/Core/Portable/Copilot/ICopilotCodeAnalysisService.cs index 0bdd083ad9584..a4ce548bcfa7c 100644 --- a/src/Features/Core/Portable/Copilot/ICopilotCodeAnalysisService.cs +++ b/src/Features/Core/Portable/Copilot/ICopilotCodeAnalysisService.cs @@ -70,7 +70,7 @@ internal interface ICopilotCodeAnalysisService : ILanguageService /// is the language of the originating . /// /// - Task GetOnTheFlyDocsAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken); + Task<(string responseString, bool isQuotaExceeded)> GetOnTheFlyDocsAsync(string symbolSignature, ImmutableArray declarationCode, string language, CancellationToken cancellationToken); /// /// Determines if the given is excluded in the workspace.