public AndConstraint <CompletionItemAssertions> HaveInsertTextFormat(InsertTextFormat insertTextFormat, string because = "", params object[] reasonArgs) { Execute.Assertion.ForCondition(Subject.insertTextFormat == insertTextFormat) .BecauseOf(because, reasonArgs) .FailWith($"Expected '{Subject.label}' completion to have insert text format '{insertTextFormat}'{{reason}}, but it has '{Subject.insertTextFormat}'"); return(new AndConstraint <CompletionItemAssertions>(this)); }
private static void SetTextEditInternal(CompletionItem item, Range range, InsertTextFormat format, string text) { item.InsertTextFormat = format; item.TextEdit = new TextEdit { Range = range, NewText = text }; }
public CompletionItemBuilder WithInsertText(string insertText) { this.AssertNoTextEdit(); this.insertText = insertText; this.insertTextFormat = InsertTextFormat.PlainText; this.insertTextMode = InsertTextMode.AdjustIndentation; return(this); }
private void SetTextEditInternal(Range range, InsertTextFormat format, string text) { this.insertTextFormat = format; this.textEdit = new TextEdit { Range = range, NewText = text }; this.insertTextMode = InsertTextMode.AdjustIndentation; }
public CompletionItemBuilder WithSnippet(string snippet) { this.AssertNoTextEdit(); this.insertText = snippet; this.insertTextFormat = InsertTextFormat.Snippet; this.insertTextMode = InsertTextMode.AdjustIndentation; return(this); }
public void SimpleTest(string expected) { var model = new InsertTextFormat(); var result = Fixture.SerializeObject(model); result.Should().Be(expected); var deresult = JsonConvert.DeserializeObject <InsertTextFormat>(expected); deresult.ShouldBeEquivalentTo(model); }
public void SimpleTest(string expected) { var model = new InsertTextFormat(); var result = Fixture.SerializeObject(model); result.Should().Be(expected); var deresult = new Serializer(ClientVersion.Lsp3).DeserializeObject <InsertTextFormat>(expected); deresult.Should().BeEquivalentTo(model); }
public abstract bool TryResolveInsertion(Position position, FormattingContext context, [NotNullWhen(true)] out TextEdit?edit, out InsertTextFormat format);
public override bool TryResolveInsertion(Position position, FormattingContext context, out TextEdit edit, out InsertTextFormat format) { if (position is null) { throw new ArgumentNullException(nameof(position)); } if (context is null) { throw new ArgumentNullException(nameof(context)); } if (!_optionsMonitor.CurrentValue.AutoClosingTags) { format = default; edit = default; return(false); } var afterCloseAngleIndex = position.GetAbsoluteIndex(context.SourceText); if (!TryResolveAutoClosingBehavior(context, afterCloseAngleIndex, out var tagName, out var autoClosingBehavior)) { format = default; edit = default; return(false); } if (autoClosingBehavior == AutoClosingBehavior.EndTag) { format = InsertTextFormat.Snippet; edit = new TextEdit() { NewText = $"$0</{tagName}>", Range = new Range(position, position) }; } else { Debug.Assert(autoClosingBehavior == AutoClosingBehavior.SelfClosing); format = InsertTextFormat.PlainText; // Need to replace the `>` with ' />$0' or '/>$0' depending on if there's prefixed whitespace. var insertionText = char.IsWhiteSpace(context.SourceText[afterCloseAngleIndex - 2]) ? "/" : " /"; var insertionPosition = new Position(position.Line, position.Character - 1); var insertionRange = new Range( start: insertionPosition, end: insertionPosition); edit = new TextEdit() { NewText = insertionText, Range = insertionRange }; } return(true); }
public override bool TryResolveInsertion(Position position, FormattingContext context, out TextEdit edit, out InsertTextFormat format) { if (position is null) { throw new ArgumentNullException(nameof(position)); } if (context is null) { throw new ArgumentNullException(nameof(context)); } if (!IsAtAttributeValueStart(context, position)) { format = default; edit = default; return(false); } // We've just typed a Razor comment start. format = InsertTextFormat.Snippet; edit = new TextEdit() { NewText = "\"$0\"", Range = new Range(position, position) }; return(true); }
public abstract bool TryResolveInsertion(Position position, FormattingContext context, out TextEdit edit, out InsertTextFormat format);
// Disabling because [NotNullWhen] is available in two Assemblies and causes warnings #pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes). public override bool TryResolveInsertion(Position position, FormattingContext context, out TextEdit?edit, out InsertTextFormat format) #pragma warning restore CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes). { Called = true; edit = ResolvedTextEdit !; format = default; return(_canResolve); }
public override bool TryResolveInsertion(Position position, FormattingContext context, out TextEdit edit, out InsertTextFormat format) { if (position is null) { throw new ArgumentNullException(nameof(position)); } if (context is null) { throw new ArgumentNullException(nameof(context)); } if (!_optionsMonitor.CurrentValue.AutoClosingTags) { // We currently only support auto-closing tags our onType formatter. format = default; edit = default; return(false); } if (!IsAtTextTag(context, position)) { format = default; edit = default; return(false); } // This is a text tag. format = InsertTextFormat.Snippet; edit = new TextEdit() { NewText = $"$0</{SyntaxConstants.TextTagName}>", Range = new Range(position, position) }; return(true); }
private static CompletionItem CreateCompletionItem( CompletionDetails completionDetails, BufferRange completionRange, int sortIndex) { string detailString = null; string documentationString = null; string completionText = completionDetails.CompletionText; InsertTextFormat insertTextFormat = InsertTextFormat.PlainText; switch (completionDetails.CompletionType) { case CompletionType.Type: case CompletionType.Namespace: case CompletionType.ParameterValue: case CompletionType.Method: case CompletionType.Property: detailString = completionDetails.ToolTipText; break; case CompletionType.Variable: case CompletionType.ParameterName: // Look for type encoded in the tooltip for parameters and variables. // Display PowerShell type names in [] to be consistent with PowerShell syntax // and how the debugger displays type names. var matches = Regex.Matches(completionDetails.ToolTipText, @"^(\[.+\])"); if ((matches.Count > 0) && (matches[0].Groups.Count > 1)) { detailString = matches[0].Groups[1].Value; } // The comparison operators (-eq, -not, -gt, etc) are unfortunately fall into ParameterName // but they don't have a type associated to them. This allows those tooltips to show up. else if (!string.IsNullOrEmpty(completionDetails.ToolTipText)) { detailString = completionDetails.ToolTipText; } break; case CompletionType.Command: // For Commands, let's extract the resolved command or the path for an exe // from the ToolTipText - if there is any ToolTipText. if (completionDetails.ToolTipText != null) { // Fix for #240 - notepad++.exe in tooltip text caused regex parser to throw. string escapedToolTipText = Regex.Escape(completionDetails.ToolTipText); // Don't display ToolTipText if it is the same as the ListItemText. // Reject command syntax ToolTipText - it's too much to display as a detailString. if (!completionDetails.ListItemText.Equals( completionDetails.ToolTipText, StringComparison.OrdinalIgnoreCase) && !Regex.IsMatch(completionDetails.ToolTipText, @"^\s*" + escapedToolTipText + @"\s+\[")) { detailString = completionDetails.ToolTipText; } } break; case CompletionType.Folder: // Insert a final "tab stop" as identified by $0 in the snippet provided for completion. // For folder paths, we take the path returned by PowerShell e.g. 'C:\Program Files' and insert // the tab stop marker before the closing quote char e.g. 'C:\Program Files$0'. // This causes the editing cursor to be placed *before* the final quote after completion, // which makes subsequent path completions work. See this part of the LSP spec for details: // https://microsoft.github.io/language-server-protocol/specification#textDocument_completion // Since we want to use a "tab stop" we need to escape a few things for Textmate to render properly. if (EndsWithQuote(completionText)) { var sb = new StringBuilder(completionDetails.CompletionText) .Replace(@"\", @"\\") .Replace(@"}", @"\}") .Replace(@"$", @"\$"); completionText = sb.Insert(sb.Length - 1, "$0").ToString(); insertTextFormat = InsertTextFormat.Snippet; } break; } // Force the client to maintain the sort order in which the // original completion results were returned. We just need to // make sure the default order also be the lexicographical order // which we do by prefixing the ListItemText with a leading 0's // four digit index. var sortText = $"{sortIndex:D4}{completionDetails.ListItemText}"; return(new CompletionItem { InsertText = completionText, InsertTextFormat = insertTextFormat, Label = completionDetails.ListItemText, Kind = MapCompletionKind(completionDetails.CompletionType), Detail = detailString, Documentation = documentationString, SortText = sortText, FilterText = completionDetails.CompletionText, TextEdit = new TextEdit { NewText = completionText, Range = new Range { Start = new Position { Line = completionRange.Start.Line - 1, Character = completionRange.Start.Column - 1 }, End = new Position { Line = completionRange.End.Line - 1, Character = completionRange.End.Column - 1 } } } }); }
/// <summary> /// Initializes static members of the <see cref="TextFormatTypesQueryEngine"/> class. /// </summary> static TextFormatTypesQueryEngine() { _insertTextFormat = new StoredProcedures().InsertTextFormat; }
public override bool TryResolveInsertion(Position position, FormattingContext context, out TextEdit edit, out InsertTextFormat format) { Called = true; edit = ResolvedTextEdit; format = default; return(_canResolve); }
public override bool TryResolveInsertion(Position position, FormattingContext context, out TextEdit edit, out InsertTextFormat format) { if (position is null) { throw new ArgumentNullException(nameof(position)); } if (context is null) { throw new ArgumentNullException(nameof(context)); } var syntaxTree = context.CodeDocument.GetSyntaxTree(); var absoluteIndex = position.GetAbsoluteIndex(context.SourceText); var change = new SourceChange(absoluteIndex, 0, string.Empty); var owner = syntaxTree.Root.LocateOwner(change); if (!IsAtEnterRuleLocation(owner)) { format = default; edit = default; return(false); } // We're currently at: // <someTag> // |</someTag> context.SourceText.GetLineAndOffset(owner.SpanStart, out var lineNumber, out _); var existingIndentation = context.Indentations[lineNumber].ExistingIndentation; var existingIndentationString = context.GetIndentationString(existingIndentation); var increasedIndentationString = context.GetIndentationLevelString(indentationLevel: 1); var innerIndentationString = string.Concat(increasedIndentationString, existingIndentationString); // We mark start position at the beginning of the line in order to remove any pre-existing whitespace. var startPosition = new Position(position.Line, 0); format = InsertTextFormat.Snippet; edit = new TextEdit() { NewText = $"{innerIndentationString}$0{Environment.NewLine}{existingIndentationString}", Range = new Range(startPosition, position) }; return(true); }
internal static async Task <(IReadOnlyList <CompletionItem>, bool)> BuildCompletionItemsAsync( Document document, SourceText sourceText, long cacheId, int position, CSharpCompletionService completionService, CSharpCompletionList completions, TextSpan typedSpan, bool expectingImportedItems, bool isSuggestionMode) { var completionsBuilder = new List <CompletionItem>(completions.Items.Length); var seenUnimportedCompletions = false; var commitCharacterRuleCache = new Dictionary <ImmutableArray <CharacterSetModificationRule>, IReadOnlyList <char> >(); var commitCharacterRuleBuilder = new HashSet <char>(); var isOverrideOrPartialCompletion = completions.Items.Length > 0 && completions.Items[0].GetProviderName() is OverrideCompletionProvider or PartialMethodCompletionProvider; for (int i = 0; i < completions.Items.Length; i++) { var completion = completions.Items[i]; string labelText = completion.DisplayTextPrefix + completion.DisplayText + completion.DisplayTextSuffix; string?insertText; string?filterText = null; List <LinePositionSpanTextChange>?additionalTextEdits = null; InsertTextFormat insertTextFormat = InsertTextFormat.PlainText; TextSpan changeSpan; string? sortText; bool hasAfterInsertStep = false; if (completion.IsComplexTextEdit) { // The completion is somehow expensive. Currently, this one of two categories: import completion, or override/partial // completion. Debug.Assert(completion.GetProviderName() is OverrideCompletionProvider or PartialMethodCompletionProvider or TypeImportCompletionProvider or ExtensionMethodImportCompletionProvider); changeSpan = typedSpan; if (isOverrideOrPartialCompletion) { // For override and partial completion, we don't want to use the DisplayText as the insert text because they contain // characters that will affect our ability to asynchronously resolve the change later. insertText = completion.FilterText; sortText = GetSortText(completion, labelText, expectingImportedItems); hasAfterInsertStep = true; } else { insertText = completion.DisplayText; sortText = '1' + completion.SortText; seenUnimportedCompletions = true; } } else { // For non-complex completions, just await the text edit. It's cheap enough that it doesn't impact our ability // to pop completions quickly // If the completion item is the misc project name, skip it. if (completion.DisplayText == Configuration.OmniSharpMiscProjectName) { continue; } GetCompletionInfo( sourceText, position, completion, await completionService.GetChangeAsync(document, completion), typedSpan, labelText, expectingImportedItems, out insertText, out filterText, out sortText, out insertTextFormat, out changeSpan, out additionalTextEdits); } var commitCharacters = BuildCommitCharacters(completion.Rules.CommitCharacterRules, isSuggestionMode, commitCharacterRuleCache, commitCharacterRuleBuilder); completionsBuilder.Add(new CompletionItem { Label = labelText, TextEdit = GetChangeForTextAndSpan(insertText !, changeSpan, sourceText), InsertTextFormat = insertTextFormat, AdditionalTextEdits = additionalTextEdits, SortText = sortText, FilterText = filterText, Kind = GetCompletionItemKind(completion.Tags), Detail = completion.InlineDescription, Data = (cacheId, i), Preselect = completion.Rules.SelectionBehavior == CompletionItemSelectionBehavior.HardSelection, CommitCharacters = commitCharacters, HasAfterInsertStep = hasAfterInsertStep, });