private void Add( string displayText, string suffix, string description, bool standard, bool isDefault ) { using var _1 = PooledStringBuilder.GetInstance(out var descriptionBuilder); using var _2 = ArrayBuilder <string> .GetInstance(out var examples); AddExamples(examples, standard, displayText); descriptionBuilder.AppendLine( examples.Count == 1 ? FeaturesResources.Example : FeaturesResources.Examples ); foreach (var example in examples) { descriptionBuilder.AppendLine(example); } descriptionBuilder.AppendLine(); descriptionBuilder.Append(description); _items.Add( new DateAndTimeItem( displayText, suffix, descriptionBuilder.ToString(), CompletionChange.Create(new TextChange(_replacementSpan, displayText)), isDefault ) ); }
public void AddIfMissing( string displayText, string suffix, string description, RegexNode parentOpt, int?positionOffset = null, string insertionText = null) { var replacementStart = parentOpt != null ? parentOpt.GetSpan().Start : Position; var replacementSpan = TextSpan.FromBounds(replacementStart, Position); var newPosition = replacementStart + positionOffset; insertionText ??= displayText; var escapedInsertionText = _language.EscapeText(insertionText, StringToken); if (escapedInsertionText != insertionText) { newPosition += escapedInsertionText.Length - insertionText.Length; } AddIfMissing(new RegexItem( displayText, suffix, description, CompletionChange.Create( new TextChange(replacementSpan, escapedInsertionText), newPosition))); }
private static async Task <CompletionChange> GetConversionChangeAsync( Document document, CompletionItem item, CancellationToken cancellationToken) { var position = SymbolCompletionItem.GetContextPosition(item); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var(dotToken, _) = GetDotAndExpressionStart(root, position, cancellationToken); var questionToken = dotToken.GetPreviousToken().Kind() == SyntaxKind.QuestionToken ? dotToken.GetPreviousToken() : (SyntaxToken?)null; var expression = (ExpressionSyntax)dotToken.GetRequiredParent(); expression = expression.GetRootConditionalAccessExpression() ?? expression; var replacement = questionToken != null ? $"(({item.DisplayText}){text.ToString(TextSpan.FromBounds(expression.SpanStart, questionToken.Value.FullSpan.Start))}){questionToken.Value}" : $"(({item.DisplayText}){text.ToString(TextSpan.FromBounds(expression.SpanStart, dotToken.SpanStart))})"; // If we're at `x.$$.y` then we only want to replace up through the first dot. var tokenOnLeft = root.FindTokenOnLeftOfPosition(position, includeSkipped: true); var fullTextChange = new TextChange( TextSpan.FromBounds( expression.SpanStart, tokenOnLeft.Kind() == SyntaxKind.DotDotToken ? tokenOnLeft.SpanStart + 1 : tokenOnLeft.Span.End), replacement); var newPosition = expression.SpanStart + replacement.Length; return(CompletionChange.Create(fullTextChange, newPosition)); }
public override Task <CompletionChange> GetChangeAsync( Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { int?spanStart = null; int?spanLength = null; if (item.Properties.TryGetValue("GodotSpan.Start", out string spanStartStr)) { if (int.TryParse(spanStartStr, out int startResult)) { spanStart = startResult; } if (item.Properties.TryGetValue("GodotSpan.Length", out string spanLengthStr)) { if (int.TryParse(spanLengthStr, out int lengthResult)) { spanLength = lengthResult; } } } var span = spanStart.HasValue && spanLength.HasValue ? new TextSpan(spanStart.Value, spanLength.Value) : item.Span; return(Task.FromResult(CompletionChange.Create(new TextChange(span, item.DisplayText)))); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { var change = (await GetTextChangeAsync(document, item, commitKey, cancellationToken).ConfigureAwait(false)) ?? new TextChange(item.Span, item.DisplayText); return(CompletionChange.Create(change)); }
//===================================================================== /// <inheritdoc /> public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitChar, CancellationToken cancellationToken) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); if (!item.Properties.TryGetValue(nameof(CommentsElement.TextBeforeCaret), out string replacementText)) { replacementText = item.DisplayText; } var itemSpan = item.Span; var replacementSpan = TextSpan.FromBounds(text[itemSpan.Start - 1] == '<' && replacementText.Length > 0 && replacementText[0] == '<' ? itemSpan.Start - 1 : itemSpan.Start, itemSpan.End); int newPosition = replacementSpan.Start + replacementText.Length; // Include the commit character? if (commitChar != null && !Char.IsWhiteSpace(commitChar.Value) && commitChar.Value != replacementText[replacementText.Length - 1]) { replacementText += commitChar.Value; newPosition++; } if (item.Properties.TryGetValue(nameof(CommentsElement.TextAfterCaret), out string afterCaretText)) { replacementText += afterCaretText; } return(CompletionChange.Create(new TextChange(replacementSpan, replacementText), newPosition, true)); }
private void ProvideEscapeCategoryCompletions(EmbeddedCompletionContext context) { foreach (var(name, (shortDesc, longDesc)) in RegexCharClass.EscapeCategories) { var displayText = name; // There are some internal escape categories the regex engine has (like _xmlI). // Just filter out here so we only show the main documented regex categories. // Note: we still include those in RegexCharClass.EscapeCategories because we // don't want to report an error on code that does use these since the .net // regex engine will allow them. if (displayText.StartsWith("_")) { continue; } var description = longDesc.Length > 0 ? longDesc : string.Format(Regex_unicode_general_category_0, name); context.AddIfMissing(new RegexItem( displayText, shortDesc, description, change: CompletionChange.Create( new TextChange(new TextSpan(context.Position, 0), name), newPosition: null))); } }
public override Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { var insertText = item.DisplayText; var textChange = new TextChange(item.Span, insertText + " KEY"); return(Task.FromResult(CompletionChange.Create(textChange))); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitChar = default(char?), CancellationToken cancellationToken = default(CancellationToken)) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var beforeCaretText = XmlDocCommentCompletionItem.GetBeforeCaretText(item); var afterCaretText = XmlDocCommentCompletionItem.GetAfterCaretText(item); var itemSpan = item.Span; var replacementSpan = TextSpan.FromBounds(text[itemSpan.Start - 1] == '<' && beforeCaretText[0] == '<' ? itemSpan.Start - 1 : itemSpan.Start, itemSpan.End); var replacementText = beforeCaretText; var newPosition = replacementSpan.Start + beforeCaretText.Length; if (commitChar.HasValue && !char.IsWhiteSpace(commitChar.Value) && commitChar.Value != replacementText[replacementText.Length - 1]) { // include the commit character replacementText += commitChar.Value; // The caret goes after whatever commit character we spit. newPosition++; } replacementText += afterCaretText; return(CompletionChange.Create( new TextChange(replacementSpan, replacementText), newPosition, includesCommitCharacter: true)); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey = null, CancellationToken cancellationToken = default) { // IsComplexTextEdit is true when we want to add async to the container. if (!item.IsComplexTextEdit) { return(await base.GetChangeAsync(document, item, commitKey, cancellationToken).ConfigureAwait(false)); } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var declaration = root.FindToken(item.Span.Start).GetAncestor(node => node.IsAsyncSupportingFunctionSyntax()); if (declaration is null) { // We already check that in ProvideCompletionsAsync above. Debug.Assert(false, "Expected non-null value for declaration."); return(await base.GetChangeAsync(document, item, commitKey, cancellationToken).ConfigureAwait(false)); } using var _ = ArrayBuilder <TextChange> .GetInstance(out var builder); builder.Add(new TextChange(new TextSpan(GetSpanStart(declaration), 0), "async ")); builder.Add(new TextChange(item.Span, item.DisplayText)); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var newText = text.WithChanges(builder); return(CompletionChange.Create(CodeAnalysis.Completion.Utilities.Collapse(newText, builder.ToImmutableArray()))); }
public static async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, CancellationToken cancellationToken) { var insertText = item.DisplayText; int?newPosition = null; if (item.Properties.TryGetValue(CompletionItemProperties.NewPositionOffset, out string positionOffsetString) && int.TryParse(positionOffsetString, out int positionOffset) && positionOffset != 0) { int originalNewPosition = item.Span.End + insertText.Length; newPosition = originalNewPosition + positionOffset; } var textChange = new TextChange(item.Span, insertText); // Create TextChange with added using if (item.Properties.TryGetValue(CompletionItemProperties.NamespaceToImport, out string nsName)) { int position = item.Span.End; var sourceTextTask = document.GetTextAsync(cancellationToken).ConfigureAwait(false); var docWithUsing = await _namespaceResolver.AddNamespaceImportAsync(nsName, document, position, cancellationToken).ConfigureAwait(false); var usingChange = await docWithUsing.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(false); var changes = usingChange.Union(new[] { textChange }).ToList(); var sourceText = await sourceTextTask; sourceText = sourceText.WithChanges(changes); textChange = Collapse(sourceText, changes); } return(CompletionChange.Create(textChange, newPosition)); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey = default(char?), CancellationToken cancellationToken = default(CancellationToken)) { var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var newDocument = await DetermineNewDocumentAsync(item, text, cancellationToken).ConfigureAwait(false); var newText = await newDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); var newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); int?newPosition = null; // Attempt to find the inserted node and move the caret appropriately if (newRoot != null) { var caretTarget = newRoot.GetAnnotatedNodesAndTokens(_annotation).FirstOrNullable(); if (caretTarget != null) { var targetPosition = GetTargetCaretPosition(caretTarget.Value.AsNode()); // Something weird happened and we failed to get a valid position. // Bail on moving the caret. if (targetPosition > 0 && targetPosition <= newText.Length) { newPosition = targetPosition; } } } var changes = await newDocument.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(false); return(CompletionChange.Create(ImmutableArray.CreateRange(changes), newPosition, includesCommitCharacter: true)); }
public sealed override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey = null, CancellationToken cancellationToken = default) { // IsComplexTextEdit is true when we want to add async to the container. if (!item.IsComplexTextEdit) { return(await base.GetChangeAsync(document, item, commitKey, cancellationToken).ConfigureAwait(false)); } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var declaration = GetAsyncSupportingDeclaration(root.FindToken(item.Span.Start)); if (declaration is null) { // IsComplexTextEdit should only be true when GetAsyncSupportingDeclaration returns non-null. // This is ensured by the ShouldMakeContainerAsync overrides. Debug.Assert(false, "Expected non-null value for declaration."); return(await base.GetChangeAsync(document, item, commitKey, cancellationToken).ConfigureAwait(false)); } var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); var syntaxKinds = document.GetRequiredLanguageService <ISyntaxKindsService>(); using var _ = ArrayBuilder <TextChange> .GetInstance(out var builder); builder.Add(new TextChange(new TextSpan(GetSpanStart(declaration), 0), syntaxFacts.GetText(syntaxKinds.AsyncKeyword) + " ")); builder.Add(new TextChange(item.Span, item.DisplayText)); var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var newText = text.WithChanges(builder); return(CompletionChange.Create(Utilities.Collapse(newText, builder.ToImmutableArray()))); }
public RegexItem( string displayText, string inlineDescription, string fullDescription, CompletionChange change) { DisplayText = displayText; InlineDescription = inlineDescription; FullDescription = fullDescription; Change = change; }
public override Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { // These values have always been added by us. var startString = item.Properties[StartKey]; var lengthString = item.Properties[LengthKey]; var newText = item.Properties[NewTextKey]; return(Task.FromResult(CompletionChange.Create(new TextChange(new TextSpan(int.Parse(startString), int.Parse(lengthString)), newText)))); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(); var node = GetCurrentLiteral(tree, item.Span.Start); // insert the insertion text property return(CompletionChange.Create(ImmutableArray <TextChange> .Empty.Add(new TextChange(node.Span, item.Properties[InsertionTextKey])))); }
public DateAndTimeItem( string displayText, string inlineDescription, string fullDescription, CompletionChange change, bool isDefault) { DisplayText = displayText; InlineDescription = inlineDescription; FullDescription = fullDescription; Change = change; IsDefault = isDefault; }
public override Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { if (item.Properties.TryGetValue("Start", out var start) && int.TryParse(start, out var s) && item.Properties.TryGetValue("Length", out var length) && int.TryParse(length, out var l)) { return(Task.FromResult(CompletionChange.Create(new TextChange(new TextSpan(s, l), item.SortText)))); } return(base.GetChangeAsync(document, item, commitKey, cancellationToken)); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { string insertText; if (!item.Properties.TryGetValue(CompletionItemProperties.InsertText, out insertText)) { insertText = item.DisplayText; } // Add using for required symbol. // Any better place to put this? if (TryGetSymbolMapping(item, out ISymbol symbol) && IsCommitContext()) { if (symbol.IsStaticImportable()) { if (Options.StaticSuggestionsAsCodeFixes) { var ns = symbol.GetNamespace(); var fullname = symbol.ToDisplayString(); insertText = fullname //change insertText so that it includes Class name and import namespace if necessary .Replace(ns + ".", "") //remove namespace from the fully qualified name ; //remove (list of params) var index_of_parenthesis = insertText.IndexOf('('); if (index_of_parenthesis > -1) { insertText = insertText.Remove(index_of_parenthesis); } //we may still need to import namespace for the class, so we check for that here var syntaxTree = await document.GetSyntaxTreeAsync().ConfigureAwait(false); var importedNamespaces = syntaxTree.GetImportedNamespaces(); if (!importedNamespaces.Contains(ns)) { _namespaceResolver.AddNamespaceOrStatic(ns, true); } } else { _namespaceResolver.AddNamespaceOrStatic(symbol.ContainingType.ToDisplayString(), false); } } else { _namespaceResolver.AddNamespaceOrStatic(symbol.GetNamespace(), true); } } return(CompletionChange.Create(new TextChange(item.Span, insertText))); }
public override Task <CompletionChange> GetChangeAsync( Document document, CodeAnalysis.Completion.CompletionItem item, char?commitCharacter = null, CancellationToken cancellationToken = default) { var textChange = new TextChange(span: new TextSpan(start: 77, length: 9), newText: @"public override void M() { throw new System.NotImplementedException(); }"); return(Task.FromResult(CompletionChange.Create(textChange, newPosition: 0))); }
public override async Task <CompletionChange> GetChangeAsync(Document doc, CompletionItem item, char?commitKey = default(char?), CancellationToken cancellationToken = default(CancellationToken)) { (string beforeText, string afterText, string newMethod) = await GetInsertText(item.Properties); TextChange change; if (newMethod != null) { change = new TextChange(new TextSpan(item.Span.Start, item.Span.Length), item.Properties [MethodNameKey] + ";"); var semanticModel = await doc.GetSemanticModelAsync(cancellationToken); if (!doc.IsOpen() || await doc.IsForkedDocumentWithSyntaxChangesAsync(cancellationToken)) { return(CompletionChange.Create(change)); } await Runtime.RunInMainThread(delegate { var document = IdeApp.Workbench.ActiveDocument; var editor = document.Editor; if (editor.EditMode != EditMode.Edit) { return; } var parsedDocument = document.ParsedDocument; var declaringType = semanticModel.GetEnclosingSymbolMD <INamedTypeSymbol> (item.Span.Start, default(CancellationToken)); var insertionPoints = InsertionPointService.GetInsertionPoints( document.Editor, semanticModel, declaringType, editor.CaretOffset ); var options = new InsertionModeOptions( GettextCatalog.GetString("Create new method"), insertionPoints, point => { if (!point.Success) { return; } point.InsertionPoint.Insert(document.Editor, document, newMethod); } ); editor.StartInsertionMode(options); }); return(CompletionChange.Create(change)); } change = new TextChange(new TextSpan(item.Span.Start, item.Span.Length), beforeText + afterText); return(CompletionChange.Create(change, item.Span.Start + beforeText.Length)); }
public override Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { // These values have always been added by us. var startString = item.Properties[StartKey]; var lengthString = item.Properties[LengthKey]; var newText = item.Properties[NewTextKey]; // This value is optionally added in some cases and may not always be there. item.Properties.TryGetValue(NewPositionKey, out var newPositionString); return(Task.FromResult(CompletionChange.Create( new TextChange(new TextSpan(int.Parse(startString), int.Parse(lengthString)), newText), newPositionString == null ? default(int?) : int.Parse(newPositionString)))); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { // custom completion logic var model = await document.GetSemanticModelAsync(); var tree = model.SyntaxTree; var root = tree.GetRoot(); var memberAccess = tree.GetRoot().GetCurrentMemberAccess(item.Span.Start); if (!item.Properties.TryGetValue(CurrentSnipperProperty, out var currentSnippet)) { return(CompletionChange.Create(ImmutableArray <TextChange> .Empty)); } if (memberAccess != null) { var snip = snippets.FirstOrDefault(s => s.GetType().ToString() == currentSnippet); var newRoot = snip.ChangeTree(document, model, memberAccess, commitKey); string expectedText = null; TextSpan nodeSpan = default(TextSpan); if (snip is IWorkspaceUpdatingSnippet wsnip) { ll = async(workspace, solution) => { var doc = solution.GetDocument(document.Id); if ((await doc.GetTextAsync()).ToString() == expectedText) { wsnip.Update(doc, (await doc.GetSyntaxRootAsync()).FindNode(nodeSpan) as ExpressionSyntax, commitKey); } }; } //if (newRoot == null) newRoot = root.ReplaceNode(memberAccess, memberAccess.Expression); if (newRoot == null) { newRoot = root.ReplaceNode(memberAccess, memberAccess.WithName(SyntaxFactory.IdentifierName(item.DisplayText))); } // format tree var newTree = tree.WithRootAndOptions(Formatter.Format(newRoot, Formatter.Annotation, document.Project.Solution.Workspace), tree.Options); // return changes done in the new tree var changes = newTree.GetChanges(tree).Select(c => TrimWhitespaceChnage(c, tree.GetText())).Select(c => MoveToNode(c, tree.GetText(), memberAccess.Expression.Span)).ToArray(); ImmutableArray <TextChange> finalChanges = ImmutableArray.Create(MergeChanges(changes, tree.GetText())); expectedText = tree.GetText().WithChanges(finalChanges).ToString(); nodeSpan = MoveSpan(memberAccess.Expression.Span, finalChanges); return(CompletionChange.Create(finalChanges, includesCommitCharacter: false)); } return(await base.GetChangeAsync(document, item, commitKey, cancellationToken)); }
// Точка расширения для замены подставляемого при completion текста public override Task <CompletionChange> GetChangeAsync( Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { // Если это свойство DTO-класса, то экранируем его квадратными скобками (escaping) if (item.Tags.Contains(WellKnownTags.Property)) { string[] splitted = item.DisplayText.Split('.'); string newText = splitted.Length > 1 ? $"[{splitted[0]}].[{splitted[1]}]" : $"[{splitted[0]}]"; return(Task.FromResult( CompletionChange.Create(new TextChange(item.Span, newText)))); } return(base.GetChangeAsync(document, item, commitKey, cancellationToken)); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey = default(char?), CancellationToken cancellationToken = default(CancellationToken)) { var projectIdGuid = item.Properties[ProjectGuidKey]; var projectId = ProjectId.CreateFromSerialized(new System.Guid(projectIdGuid)); var project = document.Project.Solution.GetProject(projectId); var assemblyName = item.DisplayText; var publicKey = await GetPublicKeyOfProjectAsync(project, cancellationToken).ConfigureAwait(false); if (!string.IsNullOrEmpty(publicKey)) { assemblyName += $", PublicKey={ publicKey }"; } var textChange = new TextChange(item.Span, assemblyName); return(CompletionChange.Create(textChange)); }
public override Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { string insertText; if (!item.Properties.TryGetValue(CompletionItemProperties.InsertText, out insertText)) { insertText = item.DisplayText; } var change = Task.FromResult(CompletionChange.Create(new TextChange(item.Span, insertText))); // Add using for required symbol. // Any better place to put this? if (TryGetSymbolMapping(item, out ISymbol symbol) && IsCommitContext()) { _namespaceResolver.AddNamespace(symbol.GetNamespace()); } return(change); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey = null, CancellationToken cancellationToken = default) { // This retrieves the document without the text used to invoke completion // as well as the new cursor position after that has been removed. var(strippedDocument, position) = await GetDocumentWithoutInvokingTextAsync(document, SnippetCompletionItem.GetInvocationPosition(item), cancellationToken).ConfigureAwait(false); var service = strippedDocument.GetRequiredLanguageService <ISnippetService>(); var snippetIdentifier = SnippetCompletionItem.GetSnippetIdentifier(item); var snippetProvider = service.GetSnippetProvider(snippetIdentifier); // This retrieves the generated Snippet var snippet = await snippetProvider.GetSnippetAsync(strippedDocument, position, cancellationToken).ConfigureAwait(false); var strippedText = await strippedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); // This introduces the text changes of the snippet into the document with the completion invoking text var allChangesText = strippedText.WithChanges(snippet.TextChanges); // This retrieves ALL text changes from the original document which includes the TextChanges from the snippet // as well as the clean up. var allChangesDocument = document.WithText(allChangesText); var allTextChanges = await allChangesDocument.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(false); var change = Utilities.Collapse(allChangesText, allTextChanges.AsImmutable()); // Converts the snippet to an LSP formatted snippet string. var lspSnippet = await RoslynLSPSnippetConverter.GenerateLSPSnippetAsync(allChangesDocument, snippet.CursorPosition, snippet.Placeholders, change, item.Span.Start, cancellationToken).ConfigureAwait(false); // If the TextChanges retrieved starts after the trigger point of the CompletionItem, // then we need to move the bounds backwards and encapsulate the trigger point. if (change.Span.Start > item.Span.Start) { var textSpan = TextSpan.FromBounds(item.Span.Start, change.Span.End); var snippetText = change.NewText; Contract.ThrowIfNull(snippetText); change = new TextChange(textSpan, snippetText); } var props = ImmutableDictionary <string, string> .Empty .Add(SnippetCompletionItem.LSPSnippetKey, lspSnippet); return(CompletionChange.Create(change, allTextChanges.AsImmutable(), properties: props, snippet.CursorPosition, includesCommitCharacter: true)); }
public override async Task <CompletionChange> GetChangeAsync(Document doc, CompletionItem item, char?commitKey = default(char?), CancellationToken cancellationToken = default(CancellationToken)) { TextChange change; if (item.Properties.ContainsKey("NewMethod")) { change = new TextChange(new TextSpan(item.Span.Start, item.Span.Length), item.Properties ["MethodName"] + ";"); var document = IdeApp.Workbench.ActiveDocument; var editor = document.Editor; var parsedDocument = document.ParsedDocument; var semanticModel = await doc.GetSemanticModelAsync(cancellationToken); var declaringType = semanticModel.GetEnclosingSymbolMD <INamedTypeSymbol> (item.Span.Start, default(CancellationToken)); var insertionPoints = InsertionPointService.GetInsertionPoints( document.Editor, parsedDocument, declaringType, editor.CaretOffset ); var options = new InsertionModeOptions( GettextCatalog.GetString("Create new method"), insertionPoints, point => { if (!point.Success) { return; } point.InsertionPoint.Insert(document.Editor, document, item.Properties ["NewMethod"]); } ); editor.StartInsertionMode(options); return(CompletionChange.Create(change)); } var beforeText = item.Properties ["InsertBefore"]; var afterText = item.Properties ["InsertAfter"]; change = new TextChange(new TextSpan(item.Span.Start, item.Span.Length), beforeText + afterText); return(CompletionChange.Create(change, item.Span.Start + beforeText.Length)); }
public override async Task <CompletionChange> GetChangeAsync(Document document, CompletionItem item, char?commitKey, CancellationToken cancellationToken) { if (await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false) is CompilationUnitSyntax rootNode) { if (rootNode.Usings.All(u => u.Name.GetText().ToString() != $"System.Reactive.Linq")) { rootNode = rootNode.InsertNodesAfter(rootNode.Usings.Last(), new[] { SyntaxFactory.UsingDirective(SyntaxFactory.ParseName($"System.Reactive.Linq")) .NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed) }); } if (rootNode.Usings.All(u => u.Name.GetText().ToString() != "RxMethodGenerator")) { rootNode = rootNode.InsertNodesAfter(rootNode.Usings.Last(), new[] { SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("RxMethodGenerator")) .NormalizeWhitespace().WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed) }); } Document?newDocument = document.WithSyntaxRoot(rootNode); document.Project.Solution.Workspace.TryApplyChanges(newDocument.Project.Solution); } string newText = $".{item.DisplayText}()"; TextSpan newSpan = new TextSpan(item.Span.Start - 1, 1); TextChange textChange = new TextChange(newSpan, newText); return(await Task.FromResult(CompletionChange.Create(textChange))); }
private void Add(string displayText, string suffix, string description, bool standard) { using var _ = PooledStringBuilder.GetInstance(out var descriptionBuilder); // Single letter custom strings need a %, or else they're interpreted as a format // standard format string (and will throw a format exception). var formatString = !standard && displayText.Length == 1 ? "%" + displayText : displayText; descriptionBuilder.AppendLine(@$ "{s_primaryCulture.Name}: {s_exampleDateTime.ToString(formatString)}"); if (s_secondaryCulture != null) { descriptionBuilder.AppendLine(@$ "{s_secondaryCulture.Name}: {s_exampleDateTime.ToString(formatString)}"); } descriptionBuilder.AppendLine(); descriptionBuilder.Append(description); _items.Add(new DateAndTimeItem( displayText, suffix, descriptionBuilder.ToString(), CompletionChange.Create( new TextChange(_replacementSpan, displayText)))); }