提交 d65b9ba0 编写于 作者: C CyrusNajmabadi

Unify infrastructure for snippets between C# and VB.

上级 37986f57
...@@ -54,11 +54,6 @@ public IReadOnlyList<TextSpan> GetHighlightedSpans(CompletionItem completionItem ...@@ -54,11 +54,6 @@ public IReadOnlyList<TextSpan> GetHighlightedSpans(CompletionItem completionItem
return match?.MatchedSpans; return match?.MatchedSpans;
} }
/// <summary>
/// If true then a [TAB] after a question mark brings up completion.
/// </summary>
public virtual bool QuestionTabInvokesSnippetCompletion => false;
/// <summary> /// <summary>
/// Returns true if the completion item matches the filter text typed so far. Returns 'true' /// Returns true if the completion item matches the filter text typed so far. Returns 'true'
/// iff the completion item matches and should be included in the filtered completion /// iff the completion item matches and should be included in the filtered completion
......
...@@ -25,13 +25,10 @@ void ICommandHandler<TabKeyCommandArgs>.ExecuteCommand(TabKeyCommandArgs args, A ...@@ -25,13 +25,10 @@ void ICommandHandler<TabKeyCommandArgs>.ExecuteCommand(TabKeyCommandArgs args, A
if (sessionOpt == null) if (sessionOpt == null)
{ {
// The user may be trying to invoke snippets in VB // The user may be trying to invoke snippets through question-tab
var helper = GetCompletionHelper();
var completionService = GetCompletionService(); var completionService = GetCompletionService();
if (helper != null && if (completionService != null &&
completionService != null &&
helper.QuestionTabInvokesSnippetCompletion &&
TryInvokeSnippetCompletion(args, completionService)) TryInvokeSnippetCompletion(args, completionService))
{ {
// We've taken care of the tab. Don't send it to the buffer. // We've taken care of the tab. Don't send it to the buffer.
...@@ -67,60 +64,91 @@ private bool TryInvokeSnippetCompletion(TabKeyCommandArgs args, CompletionServic ...@@ -67,60 +64,91 @@ private bool TryInvokeSnippetCompletion(TabKeyCommandArgs args, CompletionServic
var text = subjectBuffer.AsTextContainer().CurrentText; var text = subjectBuffer.AsTextContainer().CurrentText;
// Delete the ? and invoke completion // If the user types "<line start><spaces><question><tab>"
// then the editor takes over and shows the normal *full* snippet picker UI.
// i.e. the picker with all the folders and snippet organization.
//
// However, if the user instead has something like
//
// "<line start><spaces><identifier><question><tab>"
//
// Then we take over and we show a completion list with all snippets in it
// in a flat list. This enables simple browsing and filtering of all items
// based on what the user typed so far.
//
// If we detect this pattern, then we delete the previous character (the
// question mark) and we don't send the tab through to the editor. In
// essence, the <quesiton><tab> acts as the trigger, and we act as if that
// text never makes it into the buffer.
Workspace workspace = null; Workspace workspace = null;
if (Workspace.TryGetWorkspace(subjectBuffer.AsTextContainer(), out workspace)) if (!Workspace.TryGetWorkspace(subjectBuffer.AsTextContainer(), out workspace))
{ {
var documentId = workspace.GetDocumentIdInCurrentContext(subjectBuffer.AsTextContainer()); return false;
if (documentId != null) }
{
var document = workspace.CurrentSolution.GetDocument(documentId); var documentId = workspace.GetDocumentIdInCurrentContext(subjectBuffer.AsTextContainer());
if (document != null) if (documentId == null)
{ {
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>(); return false;
}
if (caretPoint >= 2 && text[caretPoint - 1] == '?' && QuestionMarkIsPrecededByIdentifierAndWhitespace(text, caretPoint - 2, syntaxFacts))
{ var document = workspace.CurrentSolution.GetDocument(documentId);
var textChange = new TextChange(TextSpan.FromBounds(caretPoint - 1, caretPoint), string.Empty); if (document == null)
workspace.ApplyTextChanges(documentId, textChange, CancellationToken.None); {
this.StartNewModelComputation(completionService, new CompletionTrigger(CompletionTriggerKind.Snippets), filterItems: false); return false;
return true; }
}
} var rules = GetCompletionService().GetRules();
} if (rules.SnippetsRule != SnippetsRule.IncludeAfterTypingIdentifierQuestionTab)
{
return false;
} }
return false; var syntaxFactsOpt = document.GetLanguageService<ISyntaxFactsService>();
if (syntaxFactsOpt == null ||
caretPoint < 2 ||
text[caretPoint - 1] != '?' ||
!QuestionMarkIsPrecededByIdentifierAndWhitespace(text, caretPoint - 1, syntaxFactsOpt))
{
return false;
}
// Because <question><tab> is actually a command to bring up snippets,
// we delete the last <question> that was typed.
var textChange = new TextChange(TextSpan.FromBounds(caretPoint - 1, caretPoint), string.Empty);
workspace.ApplyTextChanges(documentId, textChange, CancellationToken.None);
this.StartNewModelComputation(completionService, new CompletionTrigger(CompletionTriggerKind.Snippets), filterItems: false);
return true;
} }
private bool QuestionMarkIsPrecededByIdentifierAndWhitespace(SourceText text, int p, ISyntaxFactsService syntaxFacts) private bool QuestionMarkIsPrecededByIdentifierAndWhitespace(
SourceText text, int questionPosition, ISyntaxFactsService syntaxFacts)
{ {
int start = text.Lines.GetLineFromPosition(p).Start; var startOfLine = text.Lines.GetLineFromPosition(questionPosition).Start;
bool seenIdentifier = false;
while (p >= start) // First, skip all the whitespace.
var current = startOfLine;
while (current < questionPosition && char.IsWhiteSpace(text[current]))
{ {
if (!(syntaxFacts.IsIdentifierStartCharacter(text[p]) || syntaxFacts.IsIdentifierPartCharacter(text[p]))) current++;
{
break;
}
seenIdentifier = true;
p--;
} }
while (p >= start) if (current < questionPosition && syntaxFacts.IsIdentifierStartCharacter(text[current]))
{ {
if (!char.IsWhiteSpace(text[p])) current++;
{ }
break; else
} {
return false;
}
p--; while (current < questionPosition && syntaxFacts.IsIdentifierPartCharacter(text[current]))
{
current++;
} }
return seenIdentifier && p <= start; return current == questionPosition;
} }
private void CommitOnTab(out bool committed) private void CommitOnTab(out bool committed)
......
...@@ -35,12 +35,6 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Completion ...@@ -35,12 +35,6 @@ Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.Completion
MyBase.New(isCaseSensitive:=False) MyBase.New(isCaseSensitive:=False)
End Sub End Sub
Public Overrides ReadOnly Property QuestionTabInvokesSnippetCompletion As Boolean
Get
Return True
End Get
End Property
Public Overrides Function MatchesFilterText(item As CompletionItem, filterText As String, trigger As CompletionTrigger, filterReason As CompletionFilterReason, Optional recentItems As ImmutableArray(Of String) = Nothing) As Boolean Public Overrides Function MatchesFilterText(item As CompletionItem, filterText As String, trigger As CompletionTrigger, filterReason As CompletionFilterReason, Optional recentItems As ImmutableArray(Of String) = Nothing) As Boolean
' If this Is a session started on backspace, we use a much looser prefix match check ' If this Is a session started on backspace, we use a much looser prefix match check
' to see if an item matches ' to see if an item matches
......
...@@ -12,6 +12,7 @@ internal static class CSharpCompletionOptions ...@@ -12,6 +12,7 @@ internal static class CSharpCompletionOptions
[Obsolete("This option is superceded by CompletionOptions.EnterKeyBehavior")] [Obsolete("This option is superceded by CompletionOptions.EnterKeyBehavior")]
public static readonly Option<bool> AddNewLineOnEnterAfterFullyTypedWord = new Option<bool>(FeatureName, "Add New Line On Enter After Fully Typed Word", defaultValue: false); public static readonly Option<bool> AddNewLineOnEnterAfterFullyTypedWord = new Option<bool>(FeatureName, "Add New Line On Enter After Fully Typed Word", defaultValue: false);
[Obsolete("This option is superceded by CompletionOptions.SnippetsBehavior")]
public static readonly Option<bool> IncludeSnippets = new Option<bool>(FeatureName, "Include Code Snippets", defaultValue: true); public static readonly Option<bool> IncludeSnippets = new Option<bool>(FeatureName, "Include Code Snippets", defaultValue: true);
} }
} }
...@@ -5,16 +5,14 @@ ...@@ -5,16 +5,14 @@
using System.Composition; using System.Composition;
using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Options.Providers; using Microsoft.CodeAnalysis.Options.Providers;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Completion namespace Microsoft.CodeAnalysis.CSharp.Completion
{ {
[ExportOptionProvider, Shared] [ExportOptionProvider, Shared]
internal class CSharpCompletionOptionsProvider : IOptionProvider internal class CSharpCompletionOptionsProvider : IOptionProvider
{ {
private readonly IEnumerable<IOption> _options = new List<IOption> private readonly IEnumerable<IOption> _options = SpecializedCollections.EmptyEnumerable<IOption>();
{
CSharpCompletionOptions.IncludeSnippets,
}.ToImmutableArray();
public IEnumerable<IOption> GetOptions() public IEnumerable<IOption> GetOptions()
{ {
......
...@@ -78,17 +78,24 @@ public override CompletionRules GetRules() ...@@ -78,17 +78,24 @@ public override CompletionRules GetRules()
{ {
var options = _workspace.Options; var options = _workspace.Options;
var rule = options.GetOption(CompletionOptions.EnterKeyBehavior, LanguageNames.CSharp); var enterRule = options.GetOption(CompletionOptions.EnterKeyBehavior, LanguageNames.CSharp);
var snippetRule = options.GetOption(CompletionOptions.SnippetsBehavior, LanguageNames.CSharp);
// Although EnterKeyBehavior is a per-language setting, the meaning of an unset setting (Default) differs between C# and VB // Although EnterKeyBehavior is a per-language setting, the meaning of an unset setting (Default) differs between C# and VB
// In C# the default means Never to maintain previous behavior // In C# the default means Never to maintain previous behavior
if (rule == EnterKeyRule.Default) if (enterRule == EnterKeyRule.Default)
{ {
rule = EnterKeyRule.Never; enterRule = EnterKeyRule.Never;
}
if (snippetRule == SnippetsRule.Default)
{
snippetRule = SnippetsRule.AlwaysInclude;
} }
// use interlocked + stored rules to reduce # of times this gets created when option is different than default // use interlocked + stored rules to reduce # of times this gets created when option is different than default
var newRules = _latestRules.WithDefaultEnterKeyRule(rule); var newRules = _latestRules.WithDefaultEnterKeyRule(enterRule)
.WithSnippetsRule(snippetRule);
Interlocked.Exchange(ref _latestRules, newRules); Interlocked.Exchange(ref _latestRules, newRules);
......
...@@ -24,10 +24,7 @@ internal sealed class SnippetCompletionProvider : CommonCompletionProvider ...@@ -24,10 +24,7 @@ internal sealed class SnippetCompletionProvider : CommonCompletionProvider
// If null, the document's language service will be used. // If null, the document's language service will be used.
private readonly ISnippetInfoService _snippetInfoService; private readonly ISnippetInfoService _snippetInfoService;
internal override bool IsSnippetProvider internal override bool IsSnippetProvider => true;
{
get { return true; }
}
public SnippetCompletionProvider(ISnippetInfoService snippetInfoService = null) public SnippetCompletionProvider(ISnippetInfoService snippetInfoService = null)
{ {
...@@ -36,11 +33,6 @@ public SnippetCompletionProvider(ISnippetInfoService snippetInfoService = null) ...@@ -36,11 +33,6 @@ public SnippetCompletionProvider(ISnippetInfoService snippetInfoService = null)
internal override bool IsInsertionTrigger(SourceText text, int characterPosition, OptionSet options) internal override bool IsInsertionTrigger(SourceText text, int characterPosition, OptionSet options)
{ {
if (!options.GetOption(CSharpCompletionOptions.IncludeSnippets))
{
return false;
}
return CompletionUtilities.IsTriggerCharacter(text, characterPosition, options); return CompletionUtilities.IsTriggerCharacter(text, characterPosition, options);
} }
...@@ -62,11 +54,6 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) ...@@ -62,11 +54,6 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
return; return;
} }
if (!options.GetOption(CSharpCompletionOptions.IncludeSnippets))
{
return;
}
var snippetCompletionItems = await document.GetUnionItemsFromDocumentAndLinkedDocumentsAsync( var snippetCompletionItems = await document.GetUnionItemsFromDocumentAndLinkedDocumentsAsync(
UnionCompletionItemComparer.Instance, UnionCompletionItemComparer.Instance,
(d, c) => GetSnippetsForDocumentAsync(d, position, context.DefaultItemSpan, workspace, c), (d, c) => GetSnippetsForDocumentAsync(d, position, context.DefaultItemSpan, workspace, c),
......
...@@ -10,12 +10,13 @@ internal static class CompletionOptions ...@@ -10,12 +10,13 @@ internal static class CompletionOptions
internal const string FeatureName = "Completion"; internal const string FeatureName = "Completion";
public static readonly PerLanguageOption<bool> HideAdvancedMembers = new PerLanguageOption<bool>(FeatureName, "HideAdvancedMembers", defaultValue: false); public static readonly PerLanguageOption<bool> HideAdvancedMembers = new PerLanguageOption<bool>(FeatureName, "HideAdvancedMembers", defaultValue: false);
public static readonly PerLanguageOption<bool> IncludeKeywords = new PerLanguageOption<bool>(FeatureName, "IncludeKeywords", defaultValue: true);
public static readonly PerLanguageOption<bool> TriggerOnTyping = new PerLanguageOption<bool>(FeatureName, "TriggerOnTyping", defaultValue: true); public static readonly PerLanguageOption<bool> TriggerOnTyping = new PerLanguageOption<bool>(FeatureName, "TriggerOnTyping", defaultValue: true);
public static readonly PerLanguageOption<bool> TriggerOnTypingLetters = new PerLanguageOption<bool>(FeatureName, "TriggerOnTypingLetters", defaultValue: true); public static readonly PerLanguageOption<bool> TriggerOnTypingLetters = new PerLanguageOption<bool>(FeatureName, "TriggerOnTypingLetters", defaultValue: true);
public static readonly PerLanguageOption<EnterKeyRule> EnterKeyBehavior = public static readonly PerLanguageOption<EnterKeyRule> EnterKeyBehavior =
new PerLanguageOption<EnterKeyRule>(FeatureName, nameof(EnterKeyBehavior), defaultValue: EnterKeyRule.Default); new PerLanguageOption<EnterKeyRule>(FeatureName, nameof(EnterKeyBehavior), defaultValue: EnterKeyRule.Default);
public static readonly PerLanguageOption<SnippetsRule> SnippetsBehavior =
new PerLanguageOption<SnippetsRule>(FeatureName, nameof(SnippetsBehavior), defaultValue: SnippetsRule.Default);
// Dev15 options // Dev15 options
public static readonly PerLanguageOption<bool> ShowCompletionItemFilters = new PerLanguageOption<bool>(FeatureName, nameof(ShowCompletionItemFilters), defaultValue: false); public static readonly PerLanguageOption<bool> ShowCompletionItemFilters = new PerLanguageOption<bool>(FeatureName, nameof(ShowCompletionItemFilters), defaultValue: false);
......
...@@ -13,12 +13,12 @@ internal class CompletionOptionsProvider : IOptionProvider ...@@ -13,12 +13,12 @@ internal class CompletionOptionsProvider : IOptionProvider
{ {
private readonly IEnumerable<IOption> _options = ImmutableArray.Create<IOption>( private readonly IEnumerable<IOption> _options = ImmutableArray.Create<IOption>(
CompletionOptions.HideAdvancedMembers, CompletionOptions.HideAdvancedMembers,
CompletionOptions.IncludeKeywords,
CompletionOptions.TriggerOnTyping, CompletionOptions.TriggerOnTyping,
CompletionOptions.TriggerOnTypingLetters, CompletionOptions.TriggerOnTypingLetters,
CompletionOptions.ShowCompletionItemFilters, CompletionOptions.ShowCompletionItemFilters,
CompletionOptions.HighlightMatchingPortionsOfCompletionListItems, CompletionOptions.HighlightMatchingPortionsOfCompletionListItems,
CompletionOptions.EnterKeyBehavior); CompletionOptions.EnterKeyBehavior,
CompletionOptions.SnippetsBehavior);
public IEnumerable<IOption> GetOptions() => _options; public IEnumerable<IOption> GetOptions() => _options;
} }
......
...@@ -33,16 +33,23 @@ public sealed class CompletionRules ...@@ -33,16 +33,23 @@ public sealed class CompletionRules
/// </summary> /// </summary>
public EnterKeyRule DefaultEnterKeyRule { get; } public EnterKeyRule DefaultEnterKeyRule { get; }
/// <summary>
/// The rule determing how snippets work.
/// </summary>
public SnippetsRule SnippetsRule { get; }
private CompletionRules( private CompletionRules(
bool dismissIfEmpty, bool dismissIfEmpty,
bool dismissIfLastCharacterDeleted, bool dismissIfLastCharacterDeleted,
ImmutableArray<char> defaultCommitCharacters, ImmutableArray<char> defaultCommitCharacters,
EnterKeyRule defaultEnterKeyRule) EnterKeyRule defaultEnterKeyRule,
SnippetsRule snippetsRule)
{ {
this.DismissIfEmpty = dismissIfEmpty; this.DismissIfEmpty = dismissIfEmpty;
this.DismissIfLastCharacterDeleted = dismissIfLastCharacterDeleted; this.DismissIfLastCharacterDeleted = dismissIfLastCharacterDeleted;
this.DefaultCommitCharacters = defaultCommitCharacters.IsDefault ? ImmutableArray<char>.Empty : defaultCommitCharacters; this.DefaultCommitCharacters = defaultCommitCharacters.IsDefault ? ImmutableArray<char>.Empty : defaultCommitCharacters;
this.DefaultEnterKeyRule = defaultEnterKeyRule; this.DefaultEnterKeyRule = defaultEnterKeyRule;
this.SnippetsRule = snippetsRule;
} }
/// <summary> /// <summary>
...@@ -52,35 +59,57 @@ public sealed class CompletionRules ...@@ -52,35 +59,57 @@ public sealed class CompletionRules
/// <param name="dismissIfLastCharacterDeleted">True if the list should be dismissed when the user deletes the last character in the span.</param> /// <param name="dismissIfLastCharacterDeleted">True if the list should be dismissed when the user deletes the last character in the span.</param>
/// <param name="defaultCommitCharacters">The default set of typed characters that cause the selected item to be committed.</param> /// <param name="defaultCommitCharacters">The default set of typed characters that cause the selected item to be committed.</param>
/// <param name="defaultEnterKeyRule">The default rule that determines if the enter key is passed through to the editor after the selected item has been committed.</param> /// <param name="defaultEnterKeyRule">The default rule that determines if the enter key is passed through to the editor after the selected item has been committed.</param>
/// <returns></returns> public static CompletionRules Create(
bool dismissIfEmpty,
bool dismissIfLastCharacterDeleted,
ImmutableArray<char> defaultCommitCharacters,
EnterKeyRule defaultEnterKeyRule)
{
return Create(dismissIfEmpty, dismissIfLastCharacterDeleted, defaultCommitCharacters,
defaultEnterKeyRule, SnippetsRule.Default);
}
/// <summary>
/// Creates a new <see cref="CompletionRules"/> instance.
/// </summary>
/// <param name="dismissIfEmpty">True if the completion list should be dismissed if the user's typing causes it to filter and display no items.</param>
/// <param name="dismissIfLastCharacterDeleted">True if the list should be dismissed when the user deletes the last character in the span.</param>
/// <param name="defaultCommitCharacters">The default set of typed characters that cause the selected item to be committed.</param>
/// <param name="defaultEnterKeyRule">The default rule that determines if the enter key is passed through to the editor after the selected item has been committed.</param>
/// <param name="snippetsRule">The rule that controls snippets behavior.</param>
public static CompletionRules Create( public static CompletionRules Create(
bool dismissIfEmpty = false, bool dismissIfEmpty = false,
bool dismissIfLastCharacterDeleted = false, bool dismissIfLastCharacterDeleted = false,
ImmutableArray<char> defaultCommitCharacters = default(ImmutableArray<char>), ImmutableArray<char> defaultCommitCharacters = default(ImmutableArray<char>),
EnterKeyRule defaultEnterKeyRule = EnterKeyRule.Default) EnterKeyRule defaultEnterKeyRule = EnterKeyRule.Default,
SnippetsRule snippetsRule = SnippetsRule.Default)
{ {
return new CompletionRules( return new CompletionRules(
dismissIfEmpty: dismissIfEmpty, dismissIfEmpty: dismissIfEmpty,
dismissIfLastCharacterDeleted: dismissIfLastCharacterDeleted, dismissIfLastCharacterDeleted: dismissIfLastCharacterDeleted,
defaultCommitCharacters: defaultCommitCharacters, defaultCommitCharacters: defaultCommitCharacters,
defaultEnterKeyRule: defaultEnterKeyRule); defaultEnterKeyRule: defaultEnterKeyRule,
snippetsRule: snippetsRule);
} }
private CompletionRules With( private CompletionRules With(
Optional<bool> dismissIfEmpty = default(Optional<bool>), Optional<bool> dismissIfEmpty = default(Optional<bool>),
Optional<bool> dismissIfLastCharacterDeleted = default(Optional<bool>), Optional<bool> dismissIfLastCharacterDeleted = default(Optional<bool>),
Optional<ImmutableArray<char>> defaultCommitCharacters = default(Optional<ImmutableArray<char>>), Optional<ImmutableArray<char>> defaultCommitCharacters = default(Optional<ImmutableArray<char>>),
Optional<EnterKeyRule> defaultEnterKeyRule = default(Optional<EnterKeyRule>)) Optional<EnterKeyRule> defaultEnterKeyRule = default(Optional<EnterKeyRule>),
Optional<SnippetsRule> snippetsRule = default(Optional<SnippetsRule>))
{ {
var newDismissIfEmpty = dismissIfEmpty.HasValue ? dismissIfEmpty.Value : this.DismissIfEmpty; var newDismissIfEmpty = dismissIfEmpty.HasValue ? dismissIfEmpty.Value : this.DismissIfEmpty;
var newDismissIfLastCharacterDeleted = dismissIfLastCharacterDeleted.HasValue ? dismissIfLastCharacterDeleted.Value : this.DismissIfLastCharacterDeleted; var newDismissIfLastCharacterDeleted = dismissIfLastCharacterDeleted.HasValue ? dismissIfLastCharacterDeleted.Value : this.DismissIfLastCharacterDeleted;
var newDefaultCommitCharacters = defaultCommitCharacters.HasValue ? defaultCommitCharacters.Value : this.DefaultCommitCharacters; var newDefaultCommitCharacters = defaultCommitCharacters.HasValue ? defaultCommitCharacters.Value : this.DefaultCommitCharacters;
var newDefaultEnterKeyRule = defaultEnterKeyRule.HasValue ? defaultEnterKeyRule.Value : this.DefaultEnterKeyRule; var newDefaultEnterKeyRule = defaultEnterKeyRule.HasValue ? defaultEnterKeyRule.Value : this.DefaultEnterKeyRule;
var newSnippetsRule = snippetsRule.HasValue ? snippetsRule.Value : this.SnippetsRule;
if (newDismissIfEmpty == this.DismissIfEmpty if (newDismissIfEmpty == this.DismissIfEmpty &&
&& newDismissIfLastCharacterDeleted == this.DismissIfLastCharacterDeleted newDismissIfLastCharacterDeleted == this.DismissIfLastCharacterDeleted &&
&& newDefaultCommitCharacters == this.DefaultCommitCharacters newDefaultCommitCharacters == this.DefaultCommitCharacters &&
&& newDefaultEnterKeyRule == this.DefaultEnterKeyRule) newDefaultEnterKeyRule == this.DefaultEnterKeyRule &&
newSnippetsRule == this.SnippetsRule)
{ {
return this; return this;
} }
...@@ -90,7 +119,8 @@ public sealed class CompletionRules ...@@ -90,7 +119,8 @@ public sealed class CompletionRules
newDismissIfEmpty, newDismissIfEmpty,
newDismissIfLastCharacterDeleted, newDismissIfLastCharacterDeleted,
newDefaultCommitCharacters, newDefaultCommitCharacters,
newDefaultEnterKeyRule); newDefaultEnterKeyRule,
newSnippetsRule);
} }
} }
...@@ -126,12 +156,18 @@ public CompletionRules WithDefaultEnterKeyRule(EnterKeyRule defaultEnterKeyRule) ...@@ -126,12 +156,18 @@ public CompletionRules WithDefaultEnterKeyRule(EnterKeyRule defaultEnterKeyRule)
return With(defaultEnterKeyRule: defaultEnterKeyRule); return With(defaultEnterKeyRule: defaultEnterKeyRule);
} }
private static readonly ImmutableArray<char> s_defaultCommitKeys = new[] /// <summary>
{ /// Creates a copy of the this <see cref="CompletionRules"/> with the <see cref="SnippetsRule"/> property changed.
/// </summary>
public CompletionRules WithSnippetsRule(SnippetsRule snippetsRule)
{
return With(snippetsRule: snippetsRule);
}
private static readonly ImmutableArray<char> s_defaultCommitKeys = ImmutableArray.Create(
' ', '{', '}', '[', ']', '(', ')', '.', ',', ':', ' ', '{', '}', '[', ']', '(', ')', '.', ',', ':',
';', '+', '-', '*', '/', '%', '&', '|', '^', '!', ';', '+', '-', '*', '/', '%', '&', '|', '^', '!',
'~', '=', '<', '>', '?', '@', '#', '\'', '\"', '\\' '~', '=', '<', '>', '?', '@', '#', '\'', '\"', '\\');
}.ToImmutableArray();
/// <summary> /// <summary>
/// The default <see cref="CompletionRules"/> if none is otherwise specified. /// The default <see cref="CompletionRules"/> if none is otherwise specified.
...@@ -141,6 +177,7 @@ public CompletionRules WithDefaultEnterKeyRule(EnterKeyRule defaultEnterKeyRule) ...@@ -141,6 +177,7 @@ public CompletionRules WithDefaultEnterKeyRule(EnterKeyRule defaultEnterKeyRule)
dismissIfEmpty: false, dismissIfEmpty: false,
dismissIfLastCharacterDeleted: false, dismissIfLastCharacterDeleted: false,
defaultCommitCharacters: s_defaultCommitKeys, defaultCommitCharacters: s_defaultCommitKeys,
defaultEnterKeyRule: EnterKeyRule.Never); defaultEnterKeyRule: EnterKeyRule.Never,
snippetsRule: SnippetsRule.NeverInclude);
} }
} }
...@@ -137,16 +137,32 @@ protected ImmutableArray<CompletionProvider> GetProviders(ImmutableHashSet<strin ...@@ -137,16 +137,32 @@ protected ImmutableArray<CompletionProvider> GetProviders(ImmutableHashSet<strin
} }
} }
protected virtual ImmutableArray<CompletionProvider> GetProviders(ImmutableHashSet<string> roles, CompletionTrigger trigger) protected virtual ImmutableArray<CompletionProvider> GetProviders(
ImmutableHashSet<string> roles, CompletionTrigger trigger)
{ {
if (trigger.Kind == CompletionTriggerKind.Snippets) var snippetsRule = this.GetRules().SnippetsRule;
if (snippetsRule == SnippetsRule.NeverInclude)
{ {
return GetProviders(roles).Where(p => p.IsSnippetProvider).ToImmutableArray(); return GetProviders(roles).Where(p => !p.IsSnippetProvider).ToImmutableArray();
} }
else else if (snippetsRule == SnippetsRule.AlwaysInclude)
{ {
return GetProviders(roles); return GetProviders(roles);
} }
else if (snippetsRule == SnippetsRule.IncludeAfterTypingIdentifierQuestionTab)
{
if (trigger.Kind == CompletionTriggerKind.Snippets)
{
return GetProviders(roles).Where(p => p.IsSnippetProvider).ToImmutableArray();
}
else
{
return GetProviders(roles).Where(p => !p.IsSnippetProvider).ToImmutableArray();
}
}
return ImmutableArray<CompletionProvider>.Empty;
} }
internal protected CompletionProvider GetProvider(CompletionItem item) internal protected CompletionProvider GetProvider(CompletionItem item)
......
...@@ -47,11 +47,6 @@ public override async Task ProvideCompletionsAsync(CompletionContext context) ...@@ -47,11 +47,6 @@ public override async Task ProvideCompletionsAsync(CompletionContext context)
var options = context.Options; var options = context.Options;
var cancellationToken = context.CancellationToken; var cancellationToken = context.CancellationToken;
if (!options.GetOption(CompletionOptions.IncludeKeywords, document.Project.Language))
{
return;
}
using (Logger.LogBlock(FunctionId.Completion_KeywordCompletionProvider_GetItemsWorker, cancellationToken)) using (Logger.LogBlock(FunctionId.Completion_KeywordCompletionProvider_GetItemsWorker, cancellationToken))
{ {
var keywords = await document.GetUnionItemsFromDocumentAndLinkedDocumentsAsync( var keywords = await document.GetUnionItemsFromDocumentAndLinkedDocumentsAsync(
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Microsoft.CodeAnalysis.Completion
{
public enum SnippetsRule
{
/// <summary>
/// Snippet triggering follows the default rules of the language.
/// </summary>
Default = 0,
/// <summary>
/// Snippets are never included in the completion list
/// </summary>
NeverInclude = 1,
/// <summary>
/// Snippets are always included in the completion list.
/// </summary>
AlwaysInclude = 2,
/// <summary>
/// Snippets are included if the user types: id?&lt;tab&gt;
/// </summary>
IncludeAfterTypingIdentifierQuestionTab = 3,
}
}
\ No newline at end of file
...@@ -200,6 +200,7 @@ ...@@ -200,6 +200,7 @@
<Compile Include="Completion\Providers\RecommendedKeyword.cs" /> <Compile Include="Completion\Providers\RecommendedKeyword.cs" />
<Compile Include="Completion\Providers\XmlDocCommentCompletionItem.cs" /> <Compile Include="Completion\Providers\XmlDocCommentCompletionItem.cs" />
<Compile Include="Completion\SuggestionMode\SuggestionModeCompletionProvider.cs" /> <Compile Include="Completion\SuggestionMode\SuggestionModeCompletionProvider.cs" />
<Compile Include="Completion\SnippetsRule.cs" />
<Compile Include="Diagnostics\AnalyzerHelper.cs" /> <Compile Include="Diagnostics\AnalyzerHelper.cs" />
<Compile Include="Diagnostics\AbstractHostDiagnosticUpdateSource.cs" /> <Compile Include="Diagnostics\AbstractHostDiagnosticUpdateSource.cs" />
<Compile Include="Diagnostics\Analyzers\QualifyMemberAccessDiagnosticAnalyzerBase.cs" /> <Compile Include="Diagnostics\Analyzers\QualifyMemberAccessDiagnosticAnalyzerBase.cs" />
......
...@@ -80,10 +80,12 @@ Microsoft.CodeAnalysis.Completion.CompletionRules.DefaultCommitCharacters.get -> ...@@ -80,10 +80,12 @@ Microsoft.CodeAnalysis.Completion.CompletionRules.DefaultCommitCharacters.get ->
Microsoft.CodeAnalysis.Completion.CompletionRules.DefaultEnterKeyRule.get -> Microsoft.CodeAnalysis.Completion.EnterKeyRule Microsoft.CodeAnalysis.Completion.CompletionRules.DefaultEnterKeyRule.get -> Microsoft.CodeAnalysis.Completion.EnterKeyRule
Microsoft.CodeAnalysis.Completion.CompletionRules.DismissIfEmpty.get -> bool Microsoft.CodeAnalysis.Completion.CompletionRules.DismissIfEmpty.get -> bool
Microsoft.CodeAnalysis.Completion.CompletionRules.DismissIfLastCharacterDeleted.get -> bool Microsoft.CodeAnalysis.Completion.CompletionRules.DismissIfLastCharacterDeleted.get -> bool
Microsoft.CodeAnalysis.Completion.CompletionRules.SnippetsRule.get -> Microsoft.CodeAnalysis.Completion.SnippetsRule
Microsoft.CodeAnalysis.Completion.CompletionRules.WithDefaultCommitCharacters(System.Collections.Immutable.ImmutableArray<char> defaultCommitCharacters) -> Microsoft.CodeAnalysis.Completion.CompletionRules Microsoft.CodeAnalysis.Completion.CompletionRules.WithDefaultCommitCharacters(System.Collections.Immutable.ImmutableArray<char> defaultCommitCharacters) -> Microsoft.CodeAnalysis.Completion.CompletionRules
Microsoft.CodeAnalysis.Completion.CompletionRules.WithDefaultEnterKeyRule(Microsoft.CodeAnalysis.Completion.EnterKeyRule defaultEnterKeyRule) -> Microsoft.CodeAnalysis.Completion.CompletionRules Microsoft.CodeAnalysis.Completion.CompletionRules.WithDefaultEnterKeyRule(Microsoft.CodeAnalysis.Completion.EnterKeyRule defaultEnterKeyRule) -> Microsoft.CodeAnalysis.Completion.CompletionRules
Microsoft.CodeAnalysis.Completion.CompletionRules.WithDismissIfEmpty(bool dismissIfEmpty) -> Microsoft.CodeAnalysis.Completion.CompletionRules Microsoft.CodeAnalysis.Completion.CompletionRules.WithDismissIfEmpty(bool dismissIfEmpty) -> Microsoft.CodeAnalysis.Completion.CompletionRules
Microsoft.CodeAnalysis.Completion.CompletionRules.WithDismissIfLastCharacterDeleted(bool dismissIfLastCharacterDeleted) -> Microsoft.CodeAnalysis.Completion.CompletionRules Microsoft.CodeAnalysis.Completion.CompletionRules.WithDismissIfLastCharacterDeleted(bool dismissIfLastCharacterDeleted) -> Microsoft.CodeAnalysis.Completion.CompletionRules
Microsoft.CodeAnalysis.Completion.CompletionRules.WithSnippetsRule(Microsoft.CodeAnalysis.Completion.SnippetsRule snippetsRule) -> Microsoft.CodeAnalysis.Completion.CompletionRules
Microsoft.CodeAnalysis.Completion.CompletionService Microsoft.CodeAnalysis.Completion.CompletionService
Microsoft.CodeAnalysis.Completion.CompletionService.CompletionService() -> void Microsoft.CodeAnalysis.Completion.CompletionService.CompletionService() -> void
Microsoft.CodeAnalysis.Completion.CompletionServiceWithProviders Microsoft.CodeAnalysis.Completion.CompletionServiceWithProviders
...@@ -111,6 +113,11 @@ Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Name.get -> ...@@ -111,6 +113,11 @@ Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Name.get ->
Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Roles.get -> string[] Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Roles.get -> string[]
Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Roles.set -> void Microsoft.CodeAnalysis.Completion.ExportCompletionProviderAttribute.Roles.set -> void
Microsoft.CodeAnalysis.Completion.MatchPriority Microsoft.CodeAnalysis.Completion.MatchPriority
Microsoft.CodeAnalysis.Completion.SnippetsRule
Microsoft.CodeAnalysis.Completion.SnippetsRule.AlwaysInclude = 2 -> Microsoft.CodeAnalysis.Completion.SnippetsRule
Microsoft.CodeAnalysis.Completion.SnippetsRule.Default = 0 -> Microsoft.CodeAnalysis.Completion.SnippetsRule
Microsoft.CodeAnalysis.Completion.SnippetsRule.IncludeAfterTypingIdentifierQuestionTab = 3 -> Microsoft.CodeAnalysis.Completion.SnippetsRule
Microsoft.CodeAnalysis.Completion.SnippetsRule.NeverInclude = 1 -> Microsoft.CodeAnalysis.Completion.SnippetsRule
Microsoft.CodeAnalysis.TaggedText Microsoft.CodeAnalysis.TaggedText
Microsoft.CodeAnalysis.TaggedText.Tag.get -> string Microsoft.CodeAnalysis.TaggedText.Tag.get -> string
Microsoft.CodeAnalysis.TaggedText.TaggedText(string tag, string text) -> void Microsoft.CodeAnalysis.TaggedText.TaggedText(string tag, string text) -> void
...@@ -198,7 +205,8 @@ static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Create(System.Colle ...@@ -198,7 +205,8 @@ static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Create(System.Colle
static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Create(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> filterCharacterRules, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> commitCharacterRules, Microsoft.CodeAnalysis.Completion.EnterKeyRule enterKeyRule, bool formatOnCommit, int? matchPriority) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Create(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> filterCharacterRules, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CharacterSetModificationRule> commitCharacterRules, Microsoft.CodeAnalysis.Completion.EnterKeyRule enterKeyRule, bool formatOnCommit, int? matchPriority) -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Default -> Microsoft.CodeAnalysis.Completion.CompletionItemRules static Microsoft.CodeAnalysis.Completion.CompletionItemRules.Default -> Microsoft.CodeAnalysis.Completion.CompletionItemRules
static Microsoft.CodeAnalysis.Completion.CompletionList.Create(Microsoft.CodeAnalysis.Text.TextSpan defaultSpan, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CompletionItem> items, Microsoft.CodeAnalysis.Completion.CompletionRules rules = null, Microsoft.CodeAnalysis.Completion.CompletionItem suggestionModeItem = null) -> Microsoft.CodeAnalysis.Completion.CompletionList static Microsoft.CodeAnalysis.Completion.CompletionList.Create(Microsoft.CodeAnalysis.Text.TextSpan defaultSpan, System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Completion.CompletionItem> items, Microsoft.CodeAnalysis.Completion.CompletionRules rules = null, Microsoft.CodeAnalysis.Completion.CompletionItem suggestionModeItem = null) -> Microsoft.CodeAnalysis.Completion.CompletionList
static Microsoft.CodeAnalysis.Completion.CompletionRules.Create(bool dismissIfEmpty = false, bool dismissIfLastCharacterDeleted = false, System.Collections.Immutable.ImmutableArray<char> defaultCommitCharacters = default(System.Collections.Immutable.ImmutableArray<char>), Microsoft.CodeAnalysis.Completion.EnterKeyRule defaultEnterKeyRule = Microsoft.CodeAnalysis.Completion.EnterKeyRule.Default) -> Microsoft.CodeAnalysis.Completion.CompletionRules static Microsoft.CodeAnalysis.Completion.CompletionRules.Create(bool dismissIfEmpty = false, bool dismissIfLastCharacterDeleted = false, System.Collections.Immutable.ImmutableArray<char> defaultCommitCharacters = default(System.Collections.Immutable.ImmutableArray<char>), Microsoft.CodeAnalysis.Completion.EnterKeyRule defaultEnterKeyRule = Microsoft.CodeAnalysis.Completion.EnterKeyRule.Default, Microsoft.CodeAnalysis.Completion.SnippetsRule snippetsRule = Microsoft.CodeAnalysis.Completion.SnippetsRule.Default) -> Microsoft.CodeAnalysis.Completion.CompletionRules
static Microsoft.CodeAnalysis.Completion.CompletionRules.Create(bool dismissIfEmpty, bool dismissIfLastCharacterDeleted, System.Collections.Immutable.ImmutableArray<char> defaultCommitCharacters, Microsoft.CodeAnalysis.Completion.EnterKeyRule defaultEnterKeyRule) -> Microsoft.CodeAnalysis.Completion.CompletionRules
static Microsoft.CodeAnalysis.Completion.CompletionService.GetService(Microsoft.CodeAnalysis.Document document) -> Microsoft.CodeAnalysis.Completion.CompletionService static Microsoft.CodeAnalysis.Completion.CompletionService.GetService(Microsoft.CodeAnalysis.Document document) -> Microsoft.CodeAnalysis.Completion.CompletionService
static Microsoft.CodeAnalysis.Completion.CompletionTrigger.CreateDeletionTrigger(char deletedCharacter) -> Microsoft.CodeAnalysis.Completion.CompletionTrigger static Microsoft.CodeAnalysis.Completion.CompletionTrigger.CreateDeletionTrigger(char deletedCharacter) -> Microsoft.CodeAnalysis.Completion.CompletionTrigger
static Microsoft.CodeAnalysis.Completion.CompletionTrigger.CreateInsertionTrigger(char insertedCharacter) -> Microsoft.CodeAnalysis.Completion.CompletionTrigger static Microsoft.CodeAnalysis.Completion.CompletionTrigger.CreateInsertionTrigger(char insertedCharacter) -> Microsoft.CodeAnalysis.Completion.CompletionTrigger
......
...@@ -58,23 +58,29 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion ...@@ -58,23 +58,29 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion
End Property End Property
Private _latestRules As CompletionRules = CompletionRules.Create( Private _latestRules As CompletionRules = CompletionRules.Create(
dismissIfEmpty:=True, dismissIfEmpty:=True,
dismissIfLastCharacterDeleted:=True, dismissIfLastCharacterDeleted:=True,
defaultCommitCharacters:=CompletionRules.Default.DefaultCommitCharacters, defaultCommitCharacters:=CompletionRules.Default.DefaultCommitCharacters,
defaultEnterKeyRule:=EnterKeyRule.Always) defaultEnterKeyRule:=EnterKeyRule.Always)
Public Overrides Function GetRules() As CompletionRules Public Overrides Function GetRules() As CompletionRules
Dim options = _workspace.Options Dim options = _workspace.Options
' Although EnterKeyBehavior is a per-language setting, the meaning of an unset setting (Default) differs between C# And VB ' Although EnterKeyBehavior is a per-language setting, the meaning of an unset setting (Default) differs between C# And VB
' In VB the default means Always to maintain previous behavior ' In VB the default means Always to maintain previous behavior
Dim rule = options.GetOption(CompletionOptions.EnterKeyBehavior, LanguageNames.VisualBasic) Dim enterRule = options.GetOption(CompletionOptions.EnterKeyBehavior, LanguageNames.VisualBasic)
Dim snippetsRule = options.GetOption(CompletionOptions.SnippetsBehavior, LanguageNames.VisualBasic)
If rule = EnterKeyRule.Default Then If enterRule = EnterKeyRule.Default Then
rule = EnterKeyRule.Always enterRule = EnterKeyRule.Always
End If End If
Dim newRules = _latestRules.WithDefaultEnterKeyRule(rule) If snippetsRule = SnippetsRule.Default Then
snippetsRule = SnippetsRule.IncludeAfterTypingIdentifierQuestionTab
End If
Dim newRules = _latestRules.WithDefaultEnterKeyRule(enterRule).
WithSnippetsRule(snippetsRule)
Interlocked.Exchange(_latestRules, newRules) Interlocked.Exchange(_latestRules, newRules)
...@@ -86,18 +92,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion ...@@ -86,18 +92,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Completion
Return _completionProviders Return _completionProviders
End Function End Function
Protected Overrides Function GetProviders(roles As ImmutableHashSet(Of String), trigger As CompletionTrigger) As ImmutableArray(Of CompletionProvider)
Dim _providers = MyBase.GetProviders(roles)
If trigger.Kind = CompletionTriggerKind.Snippets Then
_providers = _providers.Where(Function(p) p.IsSnippetProvider).ToImmutableArray()
Else
_providers = _providers.Where(Function(p) Not p.IsSnippetProvider).ToImmutableArray()
End If
Return _providers
End Function
Protected Overrides Function GetBetterItem(item As CompletionItem, existingItem As CompletionItem) As CompletionItem Protected Overrides Function GetBetterItem(item As CompletionItem, existingItem As CompletionItem) As CompletionItem
' If one Is a keyword, And the other Is some other item that inserts the same text as the keyword, ' If one Is a keyword, And the other Is some other item that inserts the same text as the keyword,
' keep the keyword (VB only) ' keep the keyword (VB only)
......
...@@ -402,6 +402,15 @@ internal class CSharpVSResources { ...@@ -402,6 +402,15 @@ internal class CSharpVSResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Always include snippets.
/// </summary>
internal static string Option_Always_include_snippets {
get {
return ResourceManager.GetString("Option_Always_include_snippets", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to _Show completion list after a character is typed. /// Looks up a localized string similar to _Show completion list after a character is typed.
/// </summary> /// </summary>
...@@ -519,6 +528,15 @@ internal class CSharpVSResources { ...@@ -519,6 +528,15 @@ internal class CSharpVSResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Include snippets when ?-Tab is typed after an identifier.
/// </summary>
internal static string Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier {
get {
return ResourceManager.GetString("Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to _Insert * at the start of new lines when writing /* */ comments. /// Looks up a localized string similar to _Insert * at the start of new lines when writing /* */ comments.
/// </summary> /// </summary>
...@@ -537,6 +555,15 @@ internal class CSharpVSResources { ...@@ -537,6 +555,15 @@ internal class CSharpVSResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Never include snippets.
/// </summary>
internal static string Option_Never_include_snippets {
get {
return ResourceManager.GetString("Option_Never_include_snippets", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to _Only add new line on enter after end of fully typed word. /// Looks up a localized string similar to _Only add new line on enter after end of fully typed word.
/// </summary> /// </summary>
...@@ -852,6 +879,15 @@ internal class CSharpVSResources { ...@@ -852,6 +879,15 @@ internal class CSharpVSResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Snippets behavior.
/// </summary>
internal static string Snippets_behavior {
get {
return ResourceManager.GetString("Snippets_behavior", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Insert space after cast. /// Looks up a localized string similar to Insert space after cast.
/// </summary> /// </summary>
......
...@@ -468,10 +468,22 @@ ...@@ -468,10 +468,22 @@
<data name="Option_Only_add_new_line_on_enter_with_whole_word" xml:space="preserve"> <data name="Option_Only_add_new_line_on_enter_with_whole_word" xml:space="preserve">
<value>_Only add new line on enter after end of fully typed word</value> <value>_Only add new line on enter after end of fully typed word</value>
</data> </data>
<data name="Option_Always_add_new_line_on_enter" xml:space="preserve"> <data name="Option_Always_add_new_line_on_enter" xml:space="preserve">
<value>_Always add new line on enter</value> <value>_Always add new line on enter</value>
</data> </data>
<data name="Option_Never_add_new_line_on_enter" xml:space="preserve"> <data name="Option_Never_add_new_line_on_enter" xml:space="preserve">
<value>_Never add new line on enter</value> <value>_Never add new line on enter</value>
</data> </data>
<data name="Option_Always_include_snippets" xml:space="preserve">
<value>Always include snippets</value>
</data>
<data name="Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier" xml:space="preserve">
<value>Include snippets when ?-Tab is typed after an identifier</value>
</data>
<data name="Option_Never_include_snippets" xml:space="preserve">
<value>Never include snippets</value>
</data>
<data name="Snippets_behavior" xml:space="preserve">
<value>Snippets behavior</value>
</data>
</root> </root>
\ No newline at end of file
...@@ -208,6 +208,12 @@ public int EnterKeyBehavior ...@@ -208,6 +208,12 @@ public int EnterKeyBehavior
set { SetOption(CompletionOptions.EnterKeyBehavior, (EnterKeyRule)value); } set { SetOption(CompletionOptions.EnterKeyBehavior, (EnterKeyRule)value); }
} }
public int SnippetsBehavior
{
get { return (int)GetOption(CompletionOptions.SnippetsBehavior); }
set { SetOption(CompletionOptions.SnippetsBehavior, (SnippetsRule)value); }
}
public int NewLines_AnonymousTypeInitializer_EachMember public int NewLines_AnonymousTypeInitializer_EachMember
{ {
get { return GetBooleanOption(CSharpFormattingOptions.NewLineForMembersInAnonymousTypes); } get { return GetBooleanOption(CSharpFormattingOptions.NewLineForMembersInAnonymousTypes); }
...@@ -318,14 +324,14 @@ public int RenameTrackingPreview ...@@ -318,14 +324,14 @@ public int RenameTrackingPreview
public int ShowKeywords public int ShowKeywords
{ {
get { return GetBooleanOption(CompletionOptions.IncludeKeywords); } get { return 0; }
set { SetBooleanOption(CompletionOptions.IncludeKeywords, value); } set { }
} }
public int ShowSnippets public int ShowSnippets
{ {
get { return GetBooleanOption(CSharpCompletionOptions.IncludeSnippets); } get { return this.SnippetsBehavior; }
set { SetBooleanOption(CSharpCompletionOptions.IncludeSnippets, value); } set { this.SnippetsBehavior = value; }
} }
public int SortUsings_PlaceSystemFirst public int SortUsings_PlaceSystemFirst
......
...@@ -80,7 +80,6 @@ private bool ShouldIncludeOnOffOption(FieldInfo fieldInfo) ...@@ -80,7 +80,6 @@ private bool ShouldIncludeOnOffOption(FieldInfo fieldInfo)
result.AddRange(new[] result.AddRange(new[]
{ {
new KeyValuePair<string, IOption>(GetStorageKeyForOption(CompletionOptions.IncludeKeywords), CompletionOptions.IncludeKeywords),
new KeyValuePair<string, IOption>(GetStorageKeyForOption(CompletionOptions.TriggerOnTypingLetters), CompletionOptions.TriggerOnTypingLetters), new KeyValuePair<string, IOption>(GetStorageKeyForOption(CompletionOptions.TriggerOnTypingLetters), CompletionOptions.TriggerOnTypingLetters),
new KeyValuePair<string, IOption>(GetStorageKeyForOption(CompletionOptions.ShowCompletionItemFilters), CompletionOptions.ShowCompletionItemFilters), new KeyValuePair<string, IOption>(GetStorageKeyForOption(CompletionOptions.ShowCompletionItemFilters), CompletionOptions.ShowCompletionItemFilters),
new KeyValuePair<string, IOption>(GetStorageKeyForOption(CompletionOptions.HighlightMatchingPortionsOfCompletionListItems), CompletionOptions.HighlightMatchingPortionsOfCompletionListItems), new KeyValuePair<string, IOption>(GetStorageKeyForOption(CompletionOptions.HighlightMatchingPortionsOfCompletionListItems), CompletionOptions.HighlightMatchingPortionsOfCompletionListItems),
...@@ -144,11 +143,11 @@ protected override bool SupportsOption(IOption option, string languageName) ...@@ -144,11 +143,11 @@ protected override bool SupportsOption(IOption option, string languageName)
} }
else if (languageName == LanguageNames.CSharp) else if (languageName == LanguageNames.CSharp)
{ {
if (option == CompletionOptions.IncludeKeywords || if (option == CompletionOptions.TriggerOnTypingLetters ||
option == CompletionOptions.TriggerOnTypingLetters ||
option == CompletionOptions.ShowCompletionItemFilters || option == CompletionOptions.ShowCompletionItemFilters ||
option == CompletionOptions.HighlightMatchingPortionsOfCompletionListItems || option == CompletionOptions.HighlightMatchingPortionsOfCompletionListItems ||
option == CompletionOptions.EnterKeyBehavior || option == CompletionOptions.EnterKeyBehavior ||
option == CompletionOptions.SnippetsBehavior ||
option.Feature == SimplificationOptions.PerLanguageFeatureName || option.Feature == SimplificationOptions.PerLanguageFeatureName ||
option.Feature == ExtractMethodOptions.FeatureName || option.Feature == ExtractMethodOptions.FeatureName ||
option.Feature == ServiceFeatureOnOffOptions.OptionName || option.Feature == ServiceFeatureOnOffOptions.OptionName ||
...@@ -272,6 +271,11 @@ public override bool TryFetch(OptionKey optionKey, out object value) ...@@ -272,6 +271,11 @@ public override bool TryFetch(OptionKey optionKey, out object value)
return FetchEnterKeyBehavior(optionKey, out value); return FetchEnterKeyBehavior(optionKey, out value);
} }
if (optionKey.Option == CompletionOptions.SnippetsBehavior)
{
return FetchSnippetsBehavior(optionKey, out value);
}
return base.TryFetch(optionKey, out value); return base.TryFetch(optionKey, out value);
} }
...@@ -281,6 +285,45 @@ private bool FetchStyleBool(string settingName, out object value) ...@@ -281,6 +285,45 @@ private bool FetchStyleBool(string settingName, out object value)
return FetchStyleOption<bool>(typeStyleValue, out value); return FetchStyleOption<bool>(typeStyleValue, out value);
} }
/// <summary>
/// The EnterKeyBehavior option (formerly AddNewLineOnEnterAfterFullyTypedWord) used to only exist in C# and as a boolean.
/// We need to maintain the meaning of the serialized legacy setting.
/// </summary>
private bool FetchSnippetsBehavior(OptionKey optionKey, out object value)
{
if (!base.TryFetch(optionKey, out value))
{
return false;
}
if (!value.Equals(SnippetsRule.Default))
{
return true;
}
// if the SnippetsBehavior setting cannot be loaded, then attempt to load and upgrade the legacy setting
#pragma warning disable CS0618 // IncludeSnippets is obsolete
if (base.TryFetch(CSharpCompletionOptions.IncludeSnippets, out value))
#pragma warning restore CS0618
{
if ((bool)value)
{
value = SnippetsRule.AlwaysInclude;
}
else
{
value = SnippetsRule.NeverInclude;
}
return true;
}
value = SnippetsRule.AlwaysInclude;
return true;
}
/// <summary> /// <summary>
/// The EnterKeyBehavior option (formerly AddNewLineOnEnterAfterFullyTypedWord) used to only exist in C# and as a boolean. /// The EnterKeyBehavior option (formerly AddNewLineOnEnterAfterFullyTypedWord) used to only exist in C# and as a boolean.
/// We need to maintain the meaning of the serialized legacy setting. /// We need to maintain the meaning of the serialized legacy setting.
......
...@@ -17,17 +17,7 @@ ...@@ -17,17 +17,7 @@
<StackPanel> <StackPanel>
<CheckBox x:Uid="BringUpOnIdentifier" <CheckBox x:Uid="BringUpOnIdentifier"
x:Name="BringUpOnIdentifier" x:Name="BringUpOnIdentifier"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_BringUpOnIdentifier}" Content="{x:Static local:IntelliSenseOptionPageStrings.Option_BringUpOnIdentifier}" />
Checked="BringUpOnIdentifier_Checked"
Unchecked="BringUpOnIdentifier_Unchecked" />
<StackPanel Margin="15, 0, 0, 0">
<CheckBox x:Uid="ShowKeywords"
x:Name="ShowKeywords"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_ShowKeywords}" />
<CheckBox x:Uid="ShowSnippets"
x:Name="ShowSnippets"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_ShowSnippets}" />
</StackPanel>
<CheckBox x:Uid="Highlight_matching_portions_of_completion_list_items" <CheckBox x:Uid="Highlight_matching_portions_of_completion_list_items"
x:Name="Highlight_matching_portions_of_completion_list_items" x:Name="Highlight_matching_portions_of_completion_list_items"
...@@ -36,6 +26,19 @@ ...@@ -36,6 +26,19 @@
x:Name="Show_completion_item_filters" x:Name="Show_completion_item_filters"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Show_completion_item_filters}" /> Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Show_completion_item_filters}" />
<Label Content="{x:Static local:IntelliSenseOptionPageStrings.Snippets_behavior}"/>
<StackPanel Margin="15, 0, 0, 0">
<RadioButton GroupName="Snippets_behavior"
x:Name="Never_include_snippets"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Never_include_snippets}"/>
<RadioButton GroupName="Snippets_behavior"
x:Name="Always_include_snippets"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Always_include_snippets}"/>
<RadioButton GroupName="Snippets_behavior"
x:Name="Include_snippets_when_question_Tab_is_typed_after_an_identifier"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier}"/>
</StackPanel>
<Label Content="{x:Static local:IntelliSenseOptionPageStrings.Enter_key_behavior_Title}"/> <Label Content="{x:Static local:IntelliSenseOptionPageStrings.Enter_key_behavior_Title}"/>
<StackPanel Margin="15, 0, 0, 0"> <StackPanel Margin="15, 0, 0, 0">
<RadioButton GroupName="InsertNewlineOnEnterRadio" <RadioButton GroupName="InsertNewlineOnEnterRadio"
......
...@@ -16,28 +16,15 @@ public IntelliSenseOptionPageControl(IServiceProvider serviceProvider) : base(se ...@@ -16,28 +16,15 @@ public IntelliSenseOptionPageControl(IServiceProvider serviceProvider) : base(se
BindToOption(Show_completion_item_filters, CompletionOptions.ShowCompletionItemFilters, LanguageNames.CSharp); BindToOption(Show_completion_item_filters, CompletionOptions.ShowCompletionItemFilters, LanguageNames.CSharp);
BindToOption(Highlight_matching_portions_of_completion_list_items, CompletionOptions.HighlightMatchingPortionsOfCompletionListItems, LanguageNames.CSharp); BindToOption(Highlight_matching_portions_of_completion_list_items, CompletionOptions.HighlightMatchingPortionsOfCompletionListItems, LanguageNames.CSharp);
BindToOption(ShowSnippets, CSharpCompletionOptions.IncludeSnippets);
BindToOption(ShowKeywords, CompletionOptions.IncludeKeywords, LanguageNames.CSharp);
BindToOption(BringUpOnIdentifier, CompletionOptions.TriggerOnTypingLetters, LanguageNames.CSharp); BindToOption(BringUpOnIdentifier, CompletionOptions.TriggerOnTypingLetters, LanguageNames.CSharp);
BindToOption(Never_include_snippets, CompletionOptions.SnippetsBehavior, SnippetsRule.NeverInclude, LanguageNames.CSharp);
BindToOption(Always_include_snippets, CompletionOptions.SnippetsBehavior, SnippetsRule.AlwaysInclude, LanguageNames.CSharp);
BindToOption(Include_snippets_when_question_Tab_is_typed_after_an_identifier, CompletionOptions.SnippetsBehavior, SnippetsRule.IncludeAfterTypingIdentifierQuestionTab, LanguageNames.CSharp);
BindToOption(Never_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Never, LanguageNames.CSharp); BindToOption(Never_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Never, LanguageNames.CSharp);
BindToOption(Only_add_new_line_on_enter_with_whole_word, CompletionOptions.EnterKeyBehavior, EnterKeyRule.AfterFullyTypedWord, LanguageNames.CSharp); BindToOption(Only_add_new_line_on_enter_with_whole_word, CompletionOptions.EnterKeyBehavior, EnterKeyRule.AfterFullyTypedWord, LanguageNames.CSharp);
BindToOption(Always_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Always, LanguageNames.CSharp); BindToOption(Always_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Always, LanguageNames.CSharp);
} }
private void BringUpOnIdentifier_Checked(object sender, System.Windows.RoutedEventArgs e)
{
ShowKeywords.IsEnabled = false;
ShowSnippets.IsEnabled = false;
ShowKeywords.IsChecked = true;
ShowSnippets.IsChecked = true;
}
private void BringUpOnIdentifier_Unchecked(object sender, System.Windows.RoutedEventArgs e)
{
ShowKeywords.IsEnabled = true;
ShowSnippets.IsEnabled = true;
}
} }
} }
...@@ -46,5 +46,17 @@ public static string Option_ShowSnippets ...@@ -46,5 +46,17 @@ public static string Option_ShowSnippets
public static string Option_Always_add_new_line_on_enter => public static string Option_Always_add_new_line_on_enter =>
CSharpVSResources.Option_Always_add_new_line_on_enter; CSharpVSResources.Option_Always_add_new_line_on_enter;
public static string Snippets_behavior =>
CSharpVSResources.Snippets_behavior;
public static string Option_Never_include_snippets =>
CSharpVSResources.Option_Never_include_snippets;
public static string Option_Always_include_snippets =>
CSharpVSResources.Option_Always_include_snippets;
public static string Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier =>
CSharpVSResources.Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier;
} }
} }
...@@ -127,6 +127,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic ...@@ -127,6 +127,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized string similar to Always include snippets.
'''</summary>
Friend Shared ReadOnly Property Option_Always_include_snippets() As String
Get
Return ResourceManager.GetString("Option_Always_include_snippets", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized string similar to Automatic _insertion of Interface and MustOverride members. ''' Looks up a localized string similar to Automatic _insertion of Interface and MustOverride members.
'''</summary> '''</summary>
...@@ -136,6 +145,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic ...@@ -136,6 +145,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized string similar to _Show completion list after a character is typed.
'''</summary>
Friend Shared ReadOnly Property Option_BringUpOnIdentifier() As String
Get
Return ResourceManager.GetString("Option_BringUpOnIdentifier", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized string similar to Enable full solution _analysis. ''' Looks up a localized string similar to Enable full solution _analysis.
'''</summary> '''</summary>
...@@ -280,6 +298,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic ...@@ -280,6 +298,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized string similar to Include snippets when ?-Tab is typed after an identifier.
'''</summary>
Friend Shared ReadOnly Property Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier() As String
Get
Return ResourceManager.GetString("Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized string similar to _Navigate to Object Browser for symbols defined in metadata. ''' Looks up a localized string similar to _Navigate to Object Browser for symbols defined in metadata.
'''</summary> '''</summary>
...@@ -298,6 +325,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic ...@@ -298,6 +325,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized string similar to Never include snippets.
'''</summary>
Friend Shared ReadOnly Property Option_Never_include_snippets() As String
Get
Return ResourceManager.GetString("Option_Never_include_snippets", resourceCulture)
End Get
End Property
'''<summary> '''<summary>
''' Looks up a localized string similar to _Only add new line on enter after end of fully typed word. ''' Looks up a localized string similar to _Only add new line on enter after end of fully typed word.
'''</summary> '''</summary>
...@@ -486,5 +522,14 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic ...@@ -486,5 +522,14 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic
Return ResourceManager.GetString("QualifyPropertyAccessWithMe", resourceCulture) Return ResourceManager.GetString("QualifyPropertyAccessWithMe", resourceCulture)
End Get End Get
End Property End Property
'''<summary>
''' Looks up a localized string similar to Snippets behavior.
'''</summary>
Friend Shared ReadOnly Property Snippets_behavior() As String
Get
Return ResourceManager.GetString("Snippets_behavior", resourceCulture)
End Get
End Property
End Class End Class
End Namespace End Namespace
...@@ -258,4 +258,19 @@ ...@@ -258,4 +258,19 @@
<data name="Option_Never_add_new_line_on_enter" xml:space="preserve"> <data name="Option_Never_add_new_line_on_enter" xml:space="preserve">
<value>_Never add new line on enter</value> <value>_Never add new line on enter</value>
</data> </data>
<data name="Option_Always_include_snippets" xml:space="preserve">
<value>Always include snippets</value>
</data>
<data name="Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier" xml:space="preserve">
<value>Include snippets when ?-Tab is typed after an identifier</value>
</data>
<data name="Option_Never_include_snippets" xml:space="preserve">
<value>Never include snippets</value>
</data>
<data name="Snippets_behavior" xml:space="preserve">
<value>Snippets behavior</value>
</data>
<data name="Option_BringUpOnIdentifier" xml:space="preserve">
<value>_Show completion list after a character is typed</value>
</data>
</root> </root>
\ No newline at end of file
...@@ -15,12 +15,30 @@ ...@@ -15,12 +15,30 @@
<GroupBox x:Uid="CompletionListsGroupBox" <GroupBox x:Uid="CompletionListsGroupBox"
Header="{x:Static local:IntelliSenseOptionPageStrings.Option_CompletionLists}"> Header="{x:Static local:IntelliSenseOptionPageStrings.Option_CompletionLists}">
<StackPanel> <StackPanel>
<CheckBox x:Uid="BringUpOnIdentifier"
x:Name="BringUpOnIdentifier"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_BringUpOnIdentifier}" />
<CheckBox x:Uid="Highlight_matching_portions_of_completion_list_items" <CheckBox x:Uid="Highlight_matching_portions_of_completion_list_items"
x:Name="Highlight_matching_portions_of_completion_list_items" x:Name="Highlight_matching_portions_of_completion_list_items"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Highlight_matching_portions_of_completion_list_items}" /> Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Highlight_matching_portions_of_completion_list_items}" />
<CheckBox x:Uid="Show_completion_item_filters" <CheckBox x:Uid="Show_completion_item_filters"
x:Name="Show_completion_item_filters" x:Name="Show_completion_item_filters"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Show_completion_item_filters}" /> Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Show_completion_item_filters}" />
<Label Content="{x:Static local:IntelliSenseOptionPageStrings.Snippets_behavior}"/>
<StackPanel Margin="15, 0, 0, 0">
<RadioButton GroupName="Snippets_behavior"
x:Name="Never_include_snippets"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Never_include_snippets}"/>
<RadioButton GroupName="Snippets_behavior"
x:Name="Always_include_snippets"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Always_include_snippets}"/>
<RadioButton GroupName="Snippets_behavior"
x:Name="Include_snippets_when_question_Tab_is_typed_after_an_identifier"
Content="{x:Static local:IntelliSenseOptionPageStrings.Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier}"/>
</StackPanel>
<Label Content="{x:Static local:IntelliSenseOptionPageStrings.Enter_key_behavior_Title}"/> <Label Content="{x:Static local:IntelliSenseOptionPageStrings.Enter_key_behavior_Title}"/>
<StackPanel Margin="15, 0, 0, 0"> <StackPanel Margin="15, 0, 0, 0">
<RadioButton GroupName="InsertNewlineOnEnterRadio" <RadioButton GroupName="InsertNewlineOnEnterRadio"
......
...@@ -12,9 +12,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options ...@@ -12,9 +12,15 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
MyBase.New(serviceProvider) MyBase.New(serviceProvider)
InitializeComponent() InitializeComponent()
BindToOption(BringUpOnIdentifier, CompletionOptions.TriggerOnTypingLetters, LanguageNames.VisualBasic)
BindToOption(Show_completion_item_filters, CompletionOptions.ShowCompletionItemFilters, LanguageNames.VisualBasic) BindToOption(Show_completion_item_filters, CompletionOptions.ShowCompletionItemFilters, LanguageNames.VisualBasic)
BindToOption(Highlight_matching_portions_of_completion_list_items, CompletionOptions.HighlightMatchingPortionsOfCompletionListItems, LanguageNames.VisualBasic) BindToOption(Highlight_matching_portions_of_completion_list_items, CompletionOptions.HighlightMatchingPortionsOfCompletionListItems, LanguageNames.VisualBasic)
BindToOption(Never_include_snippets, CompletionOptions.SnippetsBehavior, SnippetsRule.NeverInclude, LanguageNames.VisualBasic)
BindToOption(Always_include_snippets, CompletionOptions.SnippetsBehavior, SnippetsRule.AlwaysInclude, LanguageNames.VisualBasic)
BindToOption(Include_snippets_when_question_Tab_is_typed_after_an_identifier, CompletionOptions.SnippetsBehavior, SnippetsRule.IncludeAfterTypingIdentifierQuestionTab, LanguageNames.VisualBasic)
BindToOption(Never_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Never, LanguageNames.VisualBasic) BindToOption(Never_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Never, LanguageNames.VisualBasic)
BindToOption(Only_add_new_line_on_enter_with_whole_word, CompletionOptions.EnterKeyBehavior, EnterKeyRule.AfterFullyTypedWord, LanguageNames.VisualBasic) BindToOption(Only_add_new_line_on_enter_with_whole_word, CompletionOptions.EnterKeyBehavior, EnterKeyRule.AfterFullyTypedWord, LanguageNames.VisualBasic)
BindToOption(Always_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Always, LanguageNames.VisualBasic) BindToOption(Always_add_new_line_on_enter, CompletionOptions.EnterKeyBehavior, EnterKeyRule.Always, LanguageNames.VisualBasic)
......
...@@ -22,5 +22,20 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options ...@@ -22,5 +22,20 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Public ReadOnly Property Enter_key_behavior_Title As String = Public ReadOnly Property Enter_key_behavior_Title As String =
BasicVSResources.Enter_key_behavior_Title BasicVSResources.Enter_key_behavior_Title
Public ReadOnly Property Option_BringUpOnIdentifier As String =
BasicVSResources.Option_BringUpOnIdentifier
Public ReadOnly Property Snippets_behavior As String =
BasicVSResources.Snippets_behavior
Public ReadOnly Property Option_Never_include_snippets As String =
BasicVSResources.Option_Never_include_snippets
Public ReadOnly Property Option_Always_include_snippets As String =
BasicVSResources.Option_Always_include_snippets
Public ReadOnly Property Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier As String =
BasicVSResources.Option_Include_snippets_when_question_Tab_is_typed_after_an_identifier
End Module End Module
End Namespace End Namespace
\ No newline at end of file
...@@ -88,7 +88,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options ...@@ -88,7 +88,8 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Protected Overrides Function SupportsOption([option] As IOption, languageName As String) As Boolean Protected Overrides Function SupportsOption([option] As IOption, languageName As String) As Boolean
If [option].Name = CompletionOptions.EnterKeyBehavior.Name Then If [option].Name = CompletionOptions.EnterKeyBehavior.Name Then
Return True Return True
ElseIf [option].Name = CompletionOptions.SnippetsBehavior.Name Then
Return True
ElseIf languageName = LanguageNames.VisualBasic Then ElseIf languageName = LanguageNames.VisualBasic Then
If [option].Feature = FeatureOnOffOptions.OptionName Then If [option].Feature = FeatureOnOffOptions.OptionName Then
Return [option].Name = FeatureOnOffOptions.PrettyListing.Name OrElse Return [option].Name = FeatureOnOffOptions.PrettyListing.Name OrElse
...@@ -165,6 +166,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options ...@@ -165,6 +166,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Return FetchEnterKeyBehavior(optionKey, value) Return FetchEnterKeyBehavior(optionKey, value)
End If End If
If optionKey.Option Is CompletionOptions.SnippetsBehavior Then
Return FetchSnippetsBehavior(optionKey, value)
End If
Return MyBase.TryFetch(optionKey, value) Return MyBase.TryFetch(optionKey, value)
End Function End Function
...@@ -180,6 +185,18 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options ...@@ -180,6 +185,18 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options
Return False Return False
End Function End Function
Private Function FetchSnippetsBehavior(optionKey As OptionKey, ByRef value As Object) As Boolean
If MyBase.TryFetch(optionKey, value) Then
If value.Equals(SnippetsRule.Default) Then
value = SnippetsRule.IncludeAfterTypingIdentifierQuestionTab
End If
Return True
End If
Return False
End Function
Public Overrides Function TryPersist(optionKey As OptionKey, value As Object) As Boolean Public Overrides Function TryPersist(optionKey As OptionKey, value As Object) As Boolean
If Me.Manager Is Nothing Then If Me.Manager Is Nothing Then
Debug.Fail("Manager is unexpectedly Nothing") Debug.Fail("Manager is unexpectedly Nothing")
......
...@@ -6,7 +6,6 @@ Imports System.Threading.Tasks ...@@ -6,7 +6,6 @@ Imports System.Threading.Tasks
Imports Microsoft.CodeAnalysis Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Completion Imports Microsoft.CodeAnalysis.Completion
Imports Microsoft.CodeAnalysis.Editor Imports Microsoft.CodeAnalysis.Editor
Imports Microsoft.CodeAnalysis.Editor.Shared.Extensions
Imports Microsoft.CodeAnalysis.Options Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.Shared.Extensions Imports Microsoft.CodeAnalysis.Shared.Extensions
Imports Microsoft.CodeAnalysis.Snippets Imports Microsoft.CodeAnalysis.Snippets
...@@ -82,8 +81,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets ...@@ -82,8 +81,6 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets
Public Sub Commit(completionItem As CompletionItem, textView As ITextView, subjectBuffer As ITextBuffer, triggerSnapshot As ITextSnapshot, commitChar As Char?) Implements ICustomCommitCompletionProvider.Commit Public Sub Commit(completionItem As CompletionItem, textView As ITextView, subjectBuffer As ITextBuffer, triggerSnapshot As ITextSnapshot, commitChar As Char?) Implements ICustomCommitCompletionProvider.Commit
Dim snippetClient = SnippetExpansionClient.GetSnippetExpansionClient(textView, subjectBuffer, _editorAdaptersFactoryService) Dim snippetClient = SnippetExpansionClient.GetSnippetExpansionClient(textView, subjectBuffer, _editorAdaptersFactoryService)
Dim caretPoint = textView.GetCaretPoint(subjectBuffer)
Dim trackingSpan = triggerSnapshot.CreateTrackingSpan(completionItem.Span.ToSpan(), SpanTrackingMode.EdgeInclusive) Dim trackingSpan = triggerSnapshot.CreateTrackingSpan(completionItem.Span.ToSpan(), SpanTrackingMode.EdgeInclusive)
Dim currentSpan = trackingSpan.GetSpan(subjectBuffer.CurrentSnapshot) Dim currentSpan = trackingSpan.GetSpan(subjectBuffer.CurrentSnapshot)
...@@ -93,4 +90,4 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets ...@@ -93,4 +90,4 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Snippets
snippetClient.TryInsertExpansion(updatedSpan.Start, updatedSpan.Start + completionItem.DisplayText.Length) snippetClient.TryInsertExpansion(updatedSpan.Start, updatedSpan.Start + completionItem.DisplayText.Length)
End Sub End Sub
End Class End Class
End Namespace End Namespace
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册