in vsintegration/src/FSharp.LanguageService.Base/ViewFilter.cs [648:702]
protected virtual int ExecCommand(ref Guid guidCmdGroup, uint nCmdId, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) {
this.autoCompleted = false;
int rc = 0;
if (this.IsExpansionUIActive) {
// Pass it along to the expansion UI picker.
return this.InnerExec(ref guidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut);
}
ExpansionProvider ep = GetExpansionProvider();
if (ep != null && ep.InTemplateEditingMode ) {
if (ep.HandlePreExec(ref guidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut))
return rc;
}
if (!HandlePreExec(ref guidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut) &&
this.nextTarget != null) {
// Pass it along the chain.
int count = this.source.ChangeCount;
rc = this.InnerExec(ref guidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut);
if (!Microsoft.VisualStudio.ErrorHandler.Succeeded(rc))
return rc;
bool bufferWasChanged = count != source.ChangeCount;
if (this.autoCompleted) {
this.autoCompleted = false;
// See if completion set just completed, so we can do auto-completion synchronously.
CompletionSet cset = this.source.CompletionSet;
if (cset != null) {
if (this.autoCompletedNothing &&
this.wasCompletionActive && guidCmdGroup == typeof(VsCommands2K).GUID &&
nCmdId == (uint)VsCommands2K.RETURN) {
// This happens if the user typed ENTER while the CompletionSet was active,
// but selected nothing from the list. In this case the ENTER key was gobbled up
// by the CompletionSet, and we want the ENTER key inserted into the buffer instead.
this.wasCompletionActive = false;
this.InnerExec(ref guidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut);
}
}
if (this.autoCompleteTypeChar) {
// Auto-complete typed a different char so we skip HandlePostExec in this case.
return rc;
}
}
if (ep != null && ep.InTemplateEditingMode ) {
if (ep.HandlePostExec(ref guidCmdGroup, nCmdId, nCmdexecopt, gotEnterKey, pvaIn, pvaOut))
return rc;
}
HandlePostExec(ref guidCmdGroup, nCmdId, nCmdexecopt, pvaIn, pvaOut, bufferWasChanged);
}
return rc;
}