File: LanguageService\AbstractLanguageService`2.IVsImmediateStatementCompletion2.cs
Web Access
Project: src\src\VisualStudio\Core\Def\Microsoft.VisualStudio.LanguageServices_pxr0p0dn_wpftmp.csproj (Microsoft.VisualStudio.LanguageServices)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.VisualStudio.LanguageServices.Implementation.DebuggerIntelliSense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.TextManager.Interop;
using Microsoft.VisualStudio.Utilities;
 
namespace Microsoft.VisualStudio.LanguageServices.Implementation.LanguageService;
 
internal abstract partial class AbstractLanguageService<TPackage, TLanguageService> : IVsImmediateStatementCompletion2
{
    protected Dictionary<IVsTextView, DebuggerIntelliSenseFilter> filters = [];
 
    int IVsImmediateStatementCompletion2.EnableStatementCompletion(int enable, int startIndex, int endIndex, IVsTextView textView)
    {
        if (filters.TryGetValue(textView, out var filter))
        {
            if (enable != 0)
            {
                filter.EnableCompletion();
            }
            else
            {
                filter.DisableCompletion();
            }
        }
 
        // Debugger wants Roslyn to return OK in all cases, 
        // for example, even if Rolsyn tried to enable the one already enabled.
        return VSConstants.S_OK;
    }
 
    int IVsImmediateStatementCompletion2.InstallStatementCompletion(int install, IVsTextView textView, int initialEnable)
    {
        // We'll install a filter whenever the debugger asks, but it won't do anything but call
        // the next filter until the context is set. To ensure that we correctly install and
        // uninstall from the many possible textviews we can work on, we maintain a dictionary
        // of textview->filters.
        if (install != 0)
        {
            if (!this.filters.TryGetValue(textView, out var filter))
            {
                filter = new DebuggerIntelliSenseFilter(
                    this.EditorAdaptersFactoryService.GetWpfTextView(textView),
                    this.Package.ComponentModel,
                    this.Package.ComponentModel.GetService<IFeatureServiceFactory>());
                this.filters[textView] = filter;
                Marshal.ThrowExceptionForHR(textView.AddCommandFilter(filter, out var nextFilter));
                filter.SetNextFilter(nextFilter);
            }
 
            filter.SetContentType(install: true);
        }
        else
        {
            Marshal.ThrowExceptionForHR(textView.RemoveCommandFilter(this.filters[textView]));
            this.filters[textView].SetContentType(install: false);
            this.filters[textView].Dispose();
            this.filters.Remove(textView);
        }
 
        return VSConstants.S_OK;
    }
 
    int IVsImmediateStatementCompletion2.SetCompletionContext(string filePath,
        IVsTextLines buffer,
        TextSpan[] currentStatementSpan,
        object punkContext,
        IVsTextView textView)
    {
        // The immediate window is always marked read-only and the language service is
        // responsible for asking the buffer to make itself writable. We'll have to do that for
        // commit, so we need to drag the IVsTextLines around, too.
        Marshal.ThrowExceptionForHR(textView.GetBuffer(out var debuggerBuffer));
 
        var view = EditorAdaptersFactoryService.GetWpfTextView(textView);
 
        // Sometimes, they give us a null context buffer. In that case, there's probably not any
        // work to do.
        if (buffer != null)
        {
            var contextBuffer = EditorAdaptersFactoryService.GetDataBuffer(buffer);
 
            if (!contextBuffer.ContentType.IsOfType(this.ContentTypeName))
            {
                FatalError.ReportAndCatch(
                    new ArgumentException($"Expected content type {this.ContentTypeName} " +
                    $"but got buffer of content type {contextBuffer.ContentType}"));
 
                return VSConstants.E_FAIL;
            }
 
            // Clean the old context in any case upfront: 
            // even if we fail to initialize, the old context must be cleaned.
            this.filters[textView].RemoveContext();
 
            var context = CreateContext(view, textView, debuggerBuffer, contextBuffer, currentStatementSpan);
            if (context.TryInitialize())
            {
                this.filters[textView].SetContext(context);
            }
        }
 
        return VSConstants.S_OK;
    }
 
    // Let our deriving language services build up an appropriate context.
    protected abstract AbstractDebuggerIntelliSenseContext CreateContext(IWpfTextView view,
        IVsTextView vsTextView,
        IVsTextLines debuggerBuffer,
        ITextBuffer contextBuffer,
        Microsoft.VisualStudio.TextManager.Interop.TextSpan[] currentStatementSpan);
 
    #region Methods that are never called
 
    int IVsImmediateStatementCompletion2.EnableStatementCompletion_Deprecated(int enable, int startIndex, int endIndex)
    {
        Debug.Assert(false);
        return VSConstants.S_OK;
    }
 
    int IVsImmediateStatementCompletion2.GetFilter(IVsTextView textView, out IVsTextViewFilter filter)
    {
        // They never even call this, so just make it compile
        Debug.Assert(false);
        filter = null;
        return VSConstants.S_OK;
    }
 
    int IVsImmediateStatementCompletion.EnableStatementCompletion_Deprecated(int enable, int startIndex, int endIndex)
    {
        Debug.Assert(false);
        return VSConstants.S_OK;
    }
 
    int IVsImmediateStatementCompletion.InstallStatementCompletion(int install, IVsTextView textView, int initialEnable)
    {
        Debug.Assert(false);
        return VSConstants.S_OK;
    }
 
    int IVsImmediateStatementCompletion.SetCompletionContext_Deprecated(string filePath, IVsTextLines buffer, TextSpan[] currentStatementSpan, object punkContext)
    {
        Debug.Assert(false);
        return VSConstants.S_OK;
    }
 
    int IVsImmediateStatementCompletion2.SetCompletionContext_Deprecated(string filepath, IVsTextLines buffer, TextSpan[] currentStatementSpan, object punkContext)
    {
        Debug.Assert(false);
        return VSConstants.S_OK;
    }
    #endregion
}