Controller_ReturnKey.cs 4.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

using System;
using Microsoft.CodeAnalysis.Editor.Commands;

namespace Microsoft.CodeAnalysis.Editor.Implementation.IntelliSense.Completion
{
    internal partial class Controller
    {
        CommandState ICommandHandler<ReturnKeyCommandArgs>.GetCommandState(ReturnKeyCommandArgs args, Func<CommandState> nextHandler)
        {
            AssertIsForeground();
            return nextHandler();
        }

        void ICommandHandler<ReturnKeyCommandArgs>.ExecuteCommand(ReturnKeyCommandArgs args, Action nextHandler)
        {
            AssertIsForeground();

            if (sessionOpt == null)
            {
                // No computation.  Nothing to do.  Just let the editor handle this.
                nextHandler();
                return;
            }

            // We are computing a model.  Commit it if we compute any selected item.
            bool sendThrough, committed;
            CommitOnEnter(out sendThrough, out committed);

            // We did not commit based on enter.  So our computation will still be running.  Stop it now.
            if (!committed)
            {
                this.StopModelComputation();
            }

            // Enter has different behavior amongst languages, so we need to actually defer to
            // the individual language item to determine what to do.  For example, in VB, enter
            // always commits the item and then sends the enter through so that later features can
            // handle it (i.e. indentation).  In C# enter only commits, although there is an option
            // to send the newline along if the item was completely typed.
            if (sendThrough)
            {
                nextHandler();
            }
        }

        private void CommitOnEnter(out bool sendThrough, out bool committed)
        {
            AssertIsForeground();

            var model = sessionOpt.WaitForModel();

            // If there's no model, then there's nothing to commit.
            if (model == null)
            {
                // Make sure that the enter gets sent into the buffer.
                sendThrough = true;
                committed = false;
                return;
            }

63 64 65 66
            // If we're in a normal editor or the Immediate window, we'll send the enter through
            // to the editor.  In single-line debugger windows (Watch, etc), however, we don't
            // want to send the enter though, because those windows don't support displaying
            // more than one line of text.
67
            sendThrough = !_isDebugger || _isImmediateWindow;
68

69 70
            if (model.IsSoftSelection)
            {
71 72
                // If the completion list is soft selected, then don't commit on enter.
                // Instead, just dismiss the completion list.
73 74 75 76 77
                committed = false;
                return;
            }

            // If the selected item is the builder, dismiss
M
Matt Warren 已提交
78
            if (model.SelectedItem.IsSuggestionModeItem)
79 80 81 82 83 84
            {
                sendThrough = false;
                committed = false;
                return;
            }

M
Matt Warren 已提交
85
            var helper = GetCompletionHelper();
86

87 88 89
            if (sendThrough)
            {
                // Get the text that the user has currently entered into the buffer
M
Matt Warren 已提交
90
                var viewSpan = model.GetViewBufferSpan(model.SelectedItem.Item.Span);
91 92
                var textTypedSoFar = model.GetCurrentTextInSnapshot(
                    viewSpan, this.TextView.TextSnapshot, this.GetCaretPointInViewBuffer());
D
Dustin Campbell 已提交
93 94

                var options = GetOptions();
95
                if (options != null)
D
Dustin Campbell 已提交
96
                {
M
Matt Warren 已提交
97
                    sendThrough = helper.SendEnterThroughToEditor(model.SelectedItem.Item, textTypedSoFar, options);
D
Dustin Campbell 已提交
98
                }
99
            }
100

M
Matt Warren 已提交
101
            this.Commit(model.SelectedItem, model, commitChar: null);
102 103 104 105
            committed = true;
        }
    }
}