/// <summary> /// Implements Intellisense dropdown. /// </summary> /// <param name="editor"></param> /// <param name="currentFunction"></param> public static void GetIntelliSenseList(ref SyntaxEditor editor, FunctionInfo currentFunction) { Editor = editor; if (Editor.IntelliPrompt.MemberList.ImageList == null) { Editor.IntelliPrompt.MemberList.ImageList = SyntaxEditor.ReflectionImageList; } Editor.IntelliPrompt.MemberList.HideOnParentFormDeactivate = true; Editor.IntelliPrompt.MemberList.MatchBasedOnItemPreText = true; Editor.IntelliPrompt.MemberList.Clear(); string fullTypeString = GetFullString(); if (fullTypeString == "UserOptions") { ListAllUserOptions(null); return; } if (fullTypeString.Length > 0) { // Process in order of least expensive to most expensive if (FindInUserOptions(fullTypeString)) { return; } if (FindInFunctions(fullTypeString)) { return; } if (FindInFunctionParameters(currentFunction, fullTypeString)) { return; } AddedProperties.Clear(); if (FindInLocalVariables(fullTypeString, editor)) { return; } if (FindInAssemblies(fullTypeString)) { return; } } }
/// <summary> /// AutoCompletes the current word. /// </summary> /// <param name="editor"></param> /// <param name="currentFunction"></param> public static void AutoComplete(ref SyntaxEditor editor, FunctionInfo currentFunction) { try { InAutoCompleteMode = true; Editor = editor; if (Editor.IntelliPrompt.MemberList.ImageList == null) { Editor.IntelliPrompt.MemberList.ImageList = SyntaxEditor.ReflectionImageList; } Editor.IntelliPrompt.MemberList.HideOnParentFormDeactivate = true; Editor.IntelliPrompt.MemberList.MatchBasedOnItemPreText = true; Editor.IntelliPrompt.MemberList.Clear(); string fullTypeString = GetFullString(); if (fullTypeString.Length > 0) { // Process in order of least expensive to most expensive AutoCompleteSpecialWords(fullTypeString); AutoCompleteUserOptions(fullTypeString); AutoCompleteConstants(fullTypeString); AutoCompleteFunctions(fullTypeString); AutoCompleteLocalVariables(fullTypeString, editor); AutoCompleteFunctionParameters(currentFunction, fullTypeString); if (FindInAssemblies(fullTypeString) && !InAutoCompleteMode) { return; } } } finally { InAutoCompleteMode = false; } }
public void NotifyDocumentTextChanged(SyntaxEditor editor, EditorSnapshotChangedEventArgs e) { if (e.TextChange.Type == TextChangeTypes.Typing && e.TypedText == ".") { editor.ActiveView.IntelliPrompt.RequestCompletionSession(); } }
///////////////////////////////////////////////////////////////////////////////////////////////////// // NON-PUBLIC PROCEDURES ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Completes the element tag at the specified offset. /// </summary> /// <param name="syntaxEditor">The <see cref="SyntaxEditor"/> to examine.</param> /// <param name="offset">The offset at which to base the context.</param> private void CompleteElementTag(SyntaxEditor syntaxEditor, int offset) { string elementName = null; // Ensure the previous token is a > and not a /> TextStream stream = syntaxEditor.Document.GetTextStream(offset); if (!stream.GoToPreviousToken()) return; if ((stream.Token.Key != "StartTagEndToken") || (offset - stream.Offset != 1)) return; // Search backward for a start element name bool exitLoop = false; while (stream.GoToPreviousToken()) { switch (stream.Token.Key) { case "StartTagNameToken": elementName = stream.TokenText.Trim(); exitLoop = true; break; case "StartTagStartToken": case "EndTagEndToken": return; } if (exitLoop) break; } // Quit if no element name was found if (elementName == null) return; // Search forward to ensure that the next element is not an end element for the same element stream.Offset = offset; exitLoop = false; while (!stream.IsAtDocumentEnd) { switch (stream.Token.Key) { case "EndTagDefaultToken": if (elementName == stream.TokenText.Trim()) return; else exitLoop = true; break; case "StartTagStartToken": case "EndTagEndToken": exitLoop = true; break; } if (exitLoop) break; stream.GoToNextToken(); } // Insert the end element text syntaxEditor.SelectedView.InsertSurroundingText(DocumentModificationType.AutoComplete, null, "</" + elementName + ">"); }
protected DiffDisplayAlgorithm(ucTextMergeEditor editor) { mergeEditor = editor; editorOriginal = editor.EditorOriginal; editorResolved = editor.EditorResolved; fileInformation = editor.FileInformation; }
public frmFind(Control owner, SyntaxEditor editor, FindReplaceOptions options, bool OnlyFiles, string SearchStr) { // // Required for Windows Form Designer support // InitializeComponent(); RehashRecent(); // // Add any constructor code after InitializeComponent call // this.owner = owner; this.editor = editor; this.options = options; // Set the form owner this.Owner = g.Main; // Clear the status //owner.SetStatusMessage("Ready"); // Select the first search type searchTypeDropDownList.SelectedIndex = 0; // Update options findTextBox.Text = options.FindText; matchCaseCheckBox.Checked = options.MatchCase; matchWholeWordCheckBox.Checked = options.MatchWholeWord; searchUpCheckBox.Checked = options.SearchUp; searchHiddenTextCheckBox.Checked = options.SearchHiddenText; searchInSelectionCheckBox.Checked = options.SearchInSelection; searchTypeCheckBox.Checked = (options.SearchType != FindReplaceSearchType.Normal); searchTypeDropDownList.SelectedIndex = (options.SearchType != FindReplaceSearchType.Wildcard ? 0 : 1); this.findTextBox.Text = SearchStr; if (OnlyFiles) { this.optAllFiles.Enabled = false; this.optCurFile.Enabled = false; this.optEntireProject.Checked = true; this.optSelection.Enabled = false; this.markAllButton.Enabled = false; this.Text = "Find in Project"; this.markWithCheckBox.Enabled = false; this.markWithCheckBox.Checked = false; this.searchUpCheckBox.Enabled = false; this.searchHiddenTextCheckBox.Enabled = false; this.bOnlyFiles = OnlyFiles; } }
/// <summary> /// Occurs after a <see cref="Trigger"/> is activated /// for a <see cref="SyntaxEditor"/> that has a <see cref="Document"/> using this language. /// </summary> /// <param name="syntaxEditor">The <see cref="SyntaxEditor"/> that will raise the event.</param> /// <param name="e">An <c>TriggerEventArgs</c> that contains the event data.</param> protected override void OnSyntaxEditorTriggerActivated(SyntaxEditor syntaxEditor, TriggerEventArgs e) { switch (e.Trigger.Key) { case "TagAutoCompleteTrigger": { if (!syntaxEditor.SelectedView.Selection.IsReadOnly) { // Complete an element tag if appropriate this.CompleteElementTag(syntaxEditor, syntaxEditor.Caret.Offset); } break; } } }
///////////////////////////////////////////////////////////////////////////////////////////////////// // OBJECT ///////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Initializes a new instance of the <c>FindReplaceForm</c> class. /// </summary> /// <param name="syntaxEditor">The <see cref="SyntaxEditor"/> for which to display the form.</param> /// <param name="options">The <see cref="FindReplaceOptions"/> to use.</param> public FindReplaceForm(SyntaxEditor syntaxEditor, FindReplaceOptions options) { // // Required for Windows Form Designer support // InitializeComponent(); // Ensure there are options if (options == null) throw new ArgumentNullException("options"); // Initalize parameters this.syntaxEditor = syntaxEditor; this.options = options; // Load text from resources //this.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_Text"); //closeButton.Text = AssemblyInfo.Instance.Resources.GetString("General_CloseButton_Text"); //findButton.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_FindButton_Text"); //findWhatLabel.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_FindWhatLabel_Text"); //markAllButton.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_MarkAllButton_Text"); //markWithCheckBox.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_MarkWithCheckBox_Text"); //matchCaseCheckBox.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_MatchCaseCheckBox_Text"); //matchWholeWordCheckBox.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_MatchWholeWordCheckBox_Text"); //replaceButton.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_ReplaceButton_Text"); //replaceAllButton.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_ReplaceAllButton_Text"); //replaceWithLabel.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_ReplaceWithLabel_Text"); //searchHiddenTextCheckBox.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_SearchHiddenTextCheckBox_Text"); //searchInSelectionCheckBox.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_SearchInSelectionCheckBox_Text"); //searchTypeCheckBox.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_SearchTypeCheckBox_Text"); //this.searchTypeDropDownList.Items.AddRange(new object[] { // AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_SearchTypeDropDownList_Item_RegularExpressions"), // AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_SearchTypeDropDownList_Item_Wildcards") // }); //searchUpCheckBox.Text = AssemblyInfo.Instance.Resources.GetString("FindReplaceForm_SearchUpCheckBox_Text"); this.searchTypeDropDownList.Items.AddRange(new object[] { "�W�h�B�⦡", "�U�Φr��" }); // Select the first search type searchTypeDropDownList.SelectedIndex = 0; // Update options this.UpdateUIFromFindReplaceOptions(); }
///// <summary> ///// Diffs two files and displays the diffed content in a single SyntaxEditor, with no striking out of lines. ///// </summary> ///// <param name="editor"></param> ///// <param name="fileBodyLeft"></param> ///// <param name="fileBodyRight"></param> ///// <returns></returns> //public static bool Perform2WayDiffInSingleEditor( // ActiproSoftware.SyntaxEditor.SyntaxEditor editor, // ref string fileBodyLeft, // ref string fileBodyRight) //{ // return Perform2WayDiffInSingleEditor(editor, ref fileBodyLeft, ref fileBodyRight, true); //} public static bool Perform2WayDiffInSingleEditor(SyntaxEditor editor, string text1, string text2) { text1 = text1.Replace("\r\n", "\n"); text2 = text2.Replace("\r\n", "\n"); var dmp = new DiffMatchPatch.diff_match_patch(); dmp.Diff_Timeout = 5.0F; dmp.Diff_EditCost = 4; dmp.Match_Threshold = 0.5F; var diffs = dmp.diff_main(text1, text2, true); dmp.diff_cleanupSemantic(diffs); if (diffs.Count == 1 && diffs[0].operation == DiffMatchPatch.Operation.EQUAL) { editor.Document.Text = diffs[0].text; return true; } DiffInSingleEditor(diffs, editor); return false; }
public frmFindReplace(Control owner, SyntaxEditor editor, FindReplaceOptions options, string DefaultText) { // // Required for Windows Form Designer support // InitializeComponent(); // // Add any constructor code after InitializeComponent call // this.owner = owner; this.editor = editor; this.options = options; // Set the form owner this.Owner = g.Main; // Clear the status //owner.SetStatusMessage("Ready"); // Select the first search type searchTypeDropDownList.SelectedIndex = 0; // Update options findTextBox.Text = options.FindText; replaceTextBox.Text = options.ReplaceText; matchCaseCheckBox.Checked = options.MatchCase; matchWholeWordCheckBox.Checked = options.MatchWholeWord; searchUpCheckBox.Checked = options.SearchUp; searchHiddenTextCheckBox.Checked = options.SearchHiddenText; searchInSelectionCheckBox.Checked = options.SearchInSelection; searchTypeCheckBox.Checked = (options.SearchType != FindReplaceSearchType.Normal); searchTypeDropDownList.SelectedIndex = (options.SearchType != FindReplaceSearchType.Wildcard ? 0 : 1); this.findTextBox.Text = DefaultText; RehashRecent(); }
protected override async Task FixAllAsync( Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { // Fix-All for this feature is somewhat complicated. As Collection-Initializers // could be arbitrarily nested, we have to make sure that any edits we make // to one Collection-Initializer are seen by any higher ones. In order to do this // we actually process each object-creation-node, one at a time, rewriting // the tree for each node. In order to do this effectively, we use the '.TrackNodes' // feature to keep track of all the object creation nodes as we make edits to // the tree. If we didn't do this, then we wouldn't be able to find the // second object-creation-node after we make the edit for the first one. var services = document.Project.Solution.Workspace.Services; var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); var originalRoot = editor.OriginalRoot; var originalObjectCreationNodes = new Stack <TObjectCreationExpressionSyntax>(); foreach (var diagnostic in diagnostics) { var objectCreation = (TObjectCreationExpressionSyntax)originalRoot.FindNode( diagnostic.AdditionalLocations[0].SourceSpan, getInnermostNodeForTie: true); originalObjectCreationNodes.Push(objectCreation); } // We're going to be continually editing this tree. Track all the nodes we // care about so we can find them across each edit. document = document.WithSyntaxRoot(originalRoot.TrackNodes(originalObjectCreationNodes)); var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var currentRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); while (originalObjectCreationNodes.Count > 0) { var originalObjectCreation = originalObjectCreationNodes.Pop(); var objectCreation = currentRoot.GetCurrentNodes(originalObjectCreation).Single(); var matches = UseCollectionInitializerAnalyzer <TExpressionSyntax, TStatementSyntax, TObjectCreationExpressionSyntax, TMemberAccessExpressionSyntax, TInvocationExpressionSyntax, TExpressionStatementSyntax, TVariableDeclaratorSyntax> .Analyze( semanticModel, syntaxFacts, objectCreation, cancellationToken); if (matches == null || matches.Value.Length == 0) { continue; } var statement = objectCreation.FirstAncestorOrSelf <TStatementSyntax>(); Contract.ThrowIfNull(statement); var newStatement = GetNewStatement(statement, objectCreation, matches.Value) .WithAdditionalAnnotations(Formatter.Annotation); var subEditor = new SyntaxEditor(currentRoot, services); subEditor.ReplaceNode(statement, newStatement); foreach (var match in matches) { subEditor.RemoveNode(match, SyntaxRemoveOptions.KeepUnbalancedDirectives); } document = document.WithSyntaxRoot(subEditor.GetChangedRoot()); semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); currentRoot = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); } editor.ReplaceNode(originalRoot, currentRoot); }
protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) => WrapFixAsync( document, diagnostics, (d, localFunction, captures) => MakeLocalFunctionStaticCodeFixHelper.MakeLocalFunctionStaticAsync( d, localFunction, captures, editor, cancellationToken), cancellationToken);
protected abstract void InsertStatement( SyntaxEditor editor, SyntaxNode functionDeclaration, IMethodSymbol method, SyntaxNode statementToAddAfterOpt, TStatementSyntax statement);
protected abstract void InsertStatement( SyntaxEditor editor, TMemberDeclarationSyntax memberDeclaration, SyntaxNode statementToAddAfterOpt, TStatementSyntax statement);
/// <summary> /// Occurs before a text change occurs to an <see cref="IEditorDocument"/> that uses this language. /// </summary> /// <param name="editor">The <see cref="SyntaxEditor"/> whose <see cref="IEditorDocument"/> that is changing.</param> /// <param name="e">The <c>EditorSnapshotChangingEventArgs</c> that contains the event data.</param> protected virtual void OnDocumentTextChanging(SyntaxEditor editor, EditorSnapshotChangingEventArgs e) { }
protected abstract Task FixAllAsync( Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken);
public override void Convert(SyntaxEditor editor, bool convertToQuery, CancellationToken cancellationToken) { var queryOrLinqInvocationExpression = CreateQueryExpressionOrLinqInvocation( _selectExpression, Enumerable.Empty <SyntaxToken>(), Enumerable.Empty <SyntaxToken>(), convertToQuery); var previous = ForEachInfo.ForEachStatement.GetPreviousStatement(); if (previous != null && !previous.ContainsDirectives) { switch (previous.Kind()) { case SyntaxKind.LocalDeclarationStatement: var variables = ((LocalDeclarationStatementSyntax)previous).Declaration.Variables; var lastDeclaration = variables.Last(); // Check if // var ...., list = new List<T>(); or var ..., counter = 0; // is just before the foreach. // If so, join the declaration with the query. if (_modifyingExpression is IdentifierNameSyntax identifierName && lastDeclaration.Identifier.ValueText.Equals(identifierName.Identifier.ValueText) && CanReplaceInitialization(lastDeclaration.Initializer.Value, cancellationToken)) { Convert(lastDeclaration.Initializer.Value, variables.Count == 1 ? (SyntaxNode)previous : lastDeclaration); return; } break; case SyntaxKind.ExpressionStatement: // Check if // list = new List<T>(); or counter = 0; // is just before the foreach. // If so, join the assignment with the query. if (((ExpressionStatementSyntax)previous).Expression is AssignmentExpressionSyntax assignmentExpression && SymbolEquivalenceComparer.Instance.Equals( ForEachInfo.SemanticModel.GetSymbolInfo(assignmentExpression.Left, cancellationToken).Symbol, ForEachInfo.SemanticModel.GetSymbolInfo(_modifyingExpression, cancellationToken).Symbol) && CanReplaceInitialization(assignmentExpression.Right, cancellationToken)) { Convert(assignmentExpression.Right, previous); return; } break; } } // At least, we already can convert to // list.AddRange(query) or counter += query.Count(); editor.ReplaceNode( ForEachInfo.ForEachStatement, CreateDefaultStatement(queryOrLinqInvocationExpression, _modifyingExpression).WithAdditionalAnnotations(Formatter.Annotation)); return; void Convert(ExpressionSyntax replacingExpression, SyntaxNode nodeToRemoveIfFollowedByReturn) { SyntaxTrivia[] leadingTrivia; // Check if expressionAssigning is followed by a return statement. var expresisonSymbol = ForEachInfo.SemanticModel.GetSymbolInfo(_modifyingExpression, cancellationToken).Symbol; if (expresisonSymbol is ILocalSymbol && ForEachInfo.ForEachStatement.GetNextStatement() is ReturnStatementSyntax returnStatement && !returnStatement.ContainsDirectives && SymbolEquivalenceComparer.Instance.Equals( expresisonSymbol, ForEachInfo.SemanticModel.GetSymbolInfo(returnStatement.Expression, cancellationToken).Symbol)) { // Input: // var list = new List<T>(); or var counter = 0; // foreach(...) // { // ... // ... // list.Add(item); or counter++; // } // return list; or return counter; // // Output: // return queryGenerated.ToList(); or return queryGenerated.Count(); replacingExpression = returnStatement.Expression; leadingTrivia = GetTriviaFromNode(nodeToRemoveIfFollowedByReturn) .Concat(SyntaxNodeOrTokenExtensions.GetTrivia(replacingExpression)).ToArray(); editor.RemoveNode(nodeToRemoveIfFollowedByReturn); }
private void MarkErrorWord(SyntaxEditor editor, int lineNumber, int characterPos, string message) { string text = editor.Document.Lines[lineNumber].Text; string compileText = CompileHelper.ReplaceUserOptionCalls(text); string preceedingText = characterPos <= compileText.Length ? compileText.Substring(0, characterPos) : ""; #region Find all GetUserOption calls and discount them int index = preceedingText.LastIndexOf("GetUserOption"); int offsetUO = "GetUserOptionValue('')".Length - "UserOptions.".Length; int castEndPos = 0; int castStartPos = 0; while (index >= 0) { characterPos -= offsetUO; while (preceedingText[index] != ')') { castEndPos = index; index -= 1; } while (preceedingText[index] != '(') { castStartPos = index; index -= 1; } characterPos -= castEndPos - castStartPos + 1; index = preceedingText.LastIndexOf("GetUserOption", index); } #endregion DocumentPosition position = new DocumentPosition(lineNumber, characterPos); int offset = editor.Document.PositionToOffset(position); DynamicToken token = (DynamicToken)editor.Document.Tokens.GetTokenAtOffset(offset); SpanIndicator indicator = new WaveLineSpanIndicator("ErrorIndicator", Color.Red); indicator.Tag = message; SpanIndicatorLayer indicatorLayer = editor.Document.SpanIndicatorLayers[ErrorLayerKey]; if (indicatorLayer == null) { indicatorLayer = new SpanIndicatorLayer(ErrorLayerKey, 1); editor.Document.SpanIndicatorLayers.Add(indicatorLayer); } int startOffset = Math.Min(token.StartOffset, indicatorLayer.Document.Length - 1); int length = Math.Max(token.Length, 1); SpanIndicator[] indicators = indicatorLayer.GetIndicatorsForTextRange(new TextRange(startOffset, startOffset + length)); foreach (SpanIndicator i in indicators) { // If there is already an error indicator on that word, don't add another one. if (i.TextRange.StartOffset == startOffset && i.TextRange.Length == length) return; } indicatorLayer.Add(indicator, startOffset, length); }
public SyntaxEditorUndoRedoHandler(SyntaxEditor syntaxEditor) { _syntaxEditor = syntaxEditor; }
public SyntaxEditorClipboardHandler(SyntaxEditor syntaxEditor) { _syntaxEditor = syntaxEditor; }
protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CodeActionOptionsProvider fallbackOptions, CancellationToken cancellationToken) { foreach (var diagnostic in diagnostics) { var node = editor.OriginalRoot.FindNode(diagnostic.Location.SourceSpan); editor.RemoveNode(node); } return(Task.CompletedTask); }
private static async Task HandleDeclarationExpressionAsync(Document document, SyntaxEditor editor, DeclarationExpressionSyntax declarationExpression, CancellationToken cancellationToken) { var typeSyntax = declarationExpression.Type; typeSyntax = typeSyntax.StripRefIfNeeded(); var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (declarationExpression.Designation.IsKind(SyntaxKind.ParenthesizedVariableDesignation, out ParenthesizedVariableDesignationSyntax? variableDesignation)) { RoslynDebug.AssertNotNull(typeSyntax.Parent); var tupleTypeSymbol = GetConvertedType(semanticModel, typeSyntax.Parent, cancellationToken); var leadingTrivia = declarationExpression.GetLeadingTrivia() .Concat(variableDesignation.GetAllPrecedingTriviaToPreviousToken().Where(t => !t.IsWhitespace()).Select(t => t.WithoutAnnotations(SyntaxAnnotation.ElasticAnnotation))); var tupleDeclaration = GenerateTupleDeclaration(tupleTypeSymbol, variableDesignation).WithLeadingTrivia(leadingTrivia); editor.ReplaceNode(declarationExpression, tupleDeclaration); } else { var typeSymbol = GetConvertedType(semanticModel, typeSyntax, cancellationToken); editor.ReplaceNode(typeSyntax, GenerateTypeDeclaration(typeSyntax, typeSymbol)); } }
/// <summary> /// Notifies before a text change occurs to an <see cref="IEditorDocument"/>. /// </summary> /// <param name="editor">The <see cref="SyntaxEditor"/> whose <see cref="IEditorDocument"/> that is changing.</param> /// <param name="e">The <c>EditorSnapshotChangingEventArgs</c> that contains the event data.</param> void IEditorDocumentTextChangeEventSink.NotifyDocumentTextChanging(SyntaxEditor editor, EditorSnapshotChangingEventArgs e) { this.OnDocumentTextChanging(editor, e); }
private void AddButton(SyntaxEditor editor, IList<DiffLine> diffLines, Panel buttonPanel, EventHandler button_Click, List<Button> buttonList) { if (editor.Visible == false) { return; } if (diffLines.Count == 0) return; int firstDisplayLine = editor.SelectedView.FirstVisibleDisplayLineIndex; int lineHeight = editor.SelectedView.DisplayLineHeight; for (int i = firstDisplayLine; i < firstDisplayLine + editor.SelectedView.VisibleDisplayLineCount && i < editor.Document.Lines.Count; i++) { DocumentLine line = editor.SelectedView.DisplayLines[i].DocumentLine; if ((diffLines[line.Index].Change & ChangeType.UserAndTemplate) == 0) continue; // Someone Deleted a line CreateButton(firstDisplayLine, i, lineHeight, buttonPanel, "Use This", "Use the text block to the left in the merged text", button_Click, buttonList); i = GetLastUndoLine(i, diffLines); } }
protected abstract void AddComment(SyntaxEditor editor, SyntaxToken stringLiteral, string commentContents);
private void RemoveAwaitFromCallerIfPresent( SyntaxEditor editor, ISyntaxFactsService syntaxFacts, SyntaxNode root, ReferenceLocation referenceLocation, CancellationToken cancellationToken) { if (referenceLocation.IsImplicit) { return; } var location = referenceLocation.Location; var token = location.FindToken(cancellationToken); var nameNode = token.Parent; if (nameNode == null) { return; } // Look for the following forms: // await M(...) // await <expr>.M(...) // await M(...).ConfigureAwait(...) // await <expr>.M(...).ConfigureAwait(...) var expressionNode = nameNode; if (syntaxFacts.IsNameOfMemberAccessExpression(nameNode)) { expressionNode = nameNode.Parent; } if (!syntaxFacts.IsExpressionOfInvocationExpression(expressionNode)) { return; } // We now either have M(...) or <expr>.M(...) var invocationExpression = expressionNode.Parent; Debug.Assert(syntaxFacts.IsInvocationExpression(invocationExpression)); if (syntaxFacts.IsExpressionOfAwaitExpression(invocationExpression)) { // Handle the case where we're directly awaited. var awaitExpression = invocationExpression.Parent; editor.ReplaceNode(awaitExpression, (currentAwaitExpression, generator) => syntaxFacts.GetExpressionOfAwaitExpression(currentAwaitExpression) .WithTriviaFrom(currentAwaitExpression)); } else if (syntaxFacts.IsExpressionOfMemberAccessExpression(invocationExpression)) { // Check for the .ConfigureAwait case. var parentMemberAccessExpression = invocationExpression.Parent; var parentMemberAccessExpressionNameNode = syntaxFacts.GetNameOfMemberAccessExpression( parentMemberAccessExpression); var parentMemberAccessExpressionName = syntaxFacts.GetIdentifierOfSimpleName(parentMemberAccessExpressionNameNode).ValueText; if (parentMemberAccessExpressionName == nameof(Task.ConfigureAwait)) { var parentExpression = parentMemberAccessExpression.Parent; if (syntaxFacts.IsExpressionOfAwaitExpression(parentExpression)) { var awaitExpression = parentExpression.Parent; editor.ReplaceNode(awaitExpression, (currentAwaitExpression, generator) => { var currentConfigureAwaitInvocation = syntaxFacts.GetExpressionOfAwaitExpression(currentAwaitExpression); var currentMemberAccess = syntaxFacts.GetExpressionOfInvocationExpression(currentConfigureAwaitInvocation); var currentInvocationExpression = syntaxFacts.GetExpressionOfMemberAccessExpression(currentMemberAccess); return(currentInvocationExpression.WithTriviaFrom(currentAwaitExpression)); }); } } } }
protected override Task HandleDeclarationAsync(Document document, SyntaxEditor editor, SyntaxNode node, CancellationToken cancellationToken) => UseExplicitTypeCodeFixProvider.HandleDeclarationAsync(document, editor, node, cancellationToken);
protected override async Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); using var spansDisposer = ArrayBuilder <TextSpan> .GetInstance(diagnostics.Length, out var spans); foreach (var diagnostic in diagnostics) { cancellationToken.ThrowIfCancellationRequested(); var span = diagnostic.AdditionalLocations[0].SourceSpan; if (spans.Any((s, nodeSpan) => s.Contains(nodeSpan), span)) { // Skip nested switch expressions in case of a fix-all operation. continue; } spans.Add(span); var properties = diagnostic.Properties; var nodeToGenerate = (SyntaxKind)int.Parse(properties[Constants.NodeToGenerateKey]); var shouldRemoveNextStatement = bool.Parse(properties[Constants.ShouldRemoveNextStatementKey]); var switchStatement = (SwitchStatementSyntax)editor.OriginalRoot.FindNode(span); editor.ReplaceNode(switchStatement, Rewriter.Rewrite(switchStatement, semanticModel, editor, nodeToGenerate, shouldMoveNextStatementToSwitchExpression: shouldRemoveNextStatement) .WithAdditionalAnnotations(Formatter.Annotation)); if (shouldRemoveNextStatement) { // Already morphed into the top-level switch expression. var nextStatement = switchStatement.GetNextStatement(); Debug.Assert(nextStatement.IsKind(SyntaxKind.ThrowStatement, SyntaxKind.ReturnStatement)); editor.RemoveNode(nextStatement); } } }
protected abstract void ConvertToForStatement( SemanticModel model, ForEachInfo info, SyntaxEditor editor, CancellationToken cancellationToken);
protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) { var root = editor.OriginalRoot; foreach (var diagnostic in diagnostics) { var token = diagnostic.Location.FindToken(cancellationToken); if (IsCatchDeclarationIdentifier(token)) { editor.ReplaceNode( token.Parent, token.Parent.ReplaceToken(token, default(SyntaxToken)).WithAdditionalAnnotations(Formatter.Annotation)); } else { var variableDeclarator = token.GetAncestor <TVariableDeclarator>(); var variableDeclarators = token.GetAncestor <TVariableDeclaration>().ChildNodes().Where(x => x is TVariableDeclarator); if (variableDeclarators.Count() == 1) { editor.RemoveNode(token.GetAncestor <TLocalDeclarationStatement>()); } else if (variableDeclarators.Count() > 1) { editor.RemoveNode(variableDeclarator); } } } return(SpecializedTasks.EmptyTask); }
private async Task <Solution> ProcessResultAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken cancellationToken) { var locations = diagnostic.AdditionalLocations; var propertyLocation = locations[0]; var declaratorLocation = locations[1]; var declarator = declaratorLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TVariableDeclarator>(); var fieldDocument = context.Document.Project.GetDocument(declarator.SyntaxTree); var fieldSemanticModel = await fieldDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var fieldSymbol = (IFieldSymbol)fieldSemanticModel.GetDeclaredSymbol(declarator); var property = propertyLocation.FindToken(cancellationToken).Parent.FirstAncestorOrSelf <TPropertyDeclaration>(); var propertyDocument = context.Document.Project.GetDocument(property.SyntaxTree); var propertySemanticModel = await propertyDocument.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var propertySymbol = (IPropertySymbol)propertySemanticModel.GetDeclaredSymbol(property); Debug.Assert(fieldDocument.Project == propertyDocument.Project); var project = fieldDocument.Project; var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); var solution = context.Document.Project.Solution; var fieldLocations = await Renamer.GetRenameLocationsAsync( solution, SymbolAndProjectId.Create(fieldSymbol, fieldDocument.Project.Id), solution.Options, cancellationToken).ConfigureAwait(false); // First, create the updated property we want to replace the old property with var isWrittenToOutsideOfConstructor = IsWrittenToOutsideOfConstructorOrProperty(fieldSymbol, fieldLocations, property, cancellationToken); var updatedProperty = await UpdatePropertyAsync( propertyDocument, compilation, fieldSymbol, propertySymbol, property, isWrittenToOutsideOfConstructor, cancellationToken).ConfigureAwait(false); // Note: rename will try to update all the references in linked files as well. However, // this can lead to some very bad behavior as we will change the references in linked files // but only remove the field and update the property in a single document. So, you can // end in the state where you do this in one of the linked file: // // int Prop { get { return this.field; } } => int Prop { get { return this.Prop } } // // But in the main file we'll replace: // // int Prop { get { return this.field; } } => int Prop { get; } // // The workspace will see these as two irreconcilable edits. To avoid this, we disallow // any edits to the other links for the files containing the field and property. i.e. // rename will only be allowed to edit the exact same doc we're removing the field from // and the exact doc we're updating the property in. It can't touch the other linked // files for those docs. (It can of course touch any other documents unrelated to the // docs that the field and prop are declared in). var linkedFiles = new HashSet <DocumentId>(); linkedFiles.AddRange(fieldDocument.GetLinkedDocumentIds()); linkedFiles.AddRange(propertyDocument.GetLinkedDocumentIds()); var canEdit = new Dictionary <SyntaxTree, bool>(); // Now, rename all usages of the field to point at the property. Except don't actually // rename the field itself. We want to be able to find it again post rename. // // We're asking the rename API to update a bunch of references to an existing field to the same name as an // existing property. Rename will often flag this situation as an unresolvable conflict because the new // name won't bind to the field anymore. // // To address this, we let rename know that there is no conflict if the new symbol it resolves to is the // same as the property we're trying to get the references pointing to. var updatedSolution = await Renamer.RenameAsync( fieldLocations.Filter( location => !location.IntersectsWith(declaratorLocation) && CanEditDocument(solution, location.SourceTree, linkedFiles, canEdit)), propertySymbol.Name, nonConflictSymbols : ImmutableHashSet.Create <ISymbol>(propertySymbol), cancellationToken).ConfigureAwait(false); solution = updatedSolution; // Now find the field and property again post rename. fieldDocument = solution.GetDocument(fieldDocument.Id); propertyDocument = solution.GetDocument(propertyDocument.Id); Debug.Assert(fieldDocument.Project == propertyDocument.Project); compilation = await fieldDocument.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); fieldSymbol = (IFieldSymbol)fieldSymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol; propertySymbol = (IPropertySymbol)propertySymbol.GetSymbolKey().Resolve(compilation, cancellationToken: cancellationToken).Symbol; Debug.Assert(fieldSymbol != null && propertySymbol != null); declarator = (TVariableDeclarator)await fieldSymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false); var temp = await propertySymbol.DeclaringSyntaxReferences[0].GetSyntaxAsync(cancellationToken).ConfigureAwait(false); property = temp.FirstAncestorOrSelf <TPropertyDeclaration>(); var nodeToRemove = GetNodeToRemove(declarator); // If we have a situation where the property is the second member in a type, and it // would become the first, then remove any leading blank lines from it so we don't have // random blanks above it that used to space it from the field that was there. // // The reason we do this special processing is that the first member of a type tends to // be special wrt leading trivia. i.e. users do not normally put blank lines before the // first member. And so, when a type now becomes the first member, we want to follow the // user's common pattern here. // // In all other code cases, i.e.when there are multiple fields above, or the field is // below the property, then the property isn't now becoming "the first member", and as // such, it doesn't want this special behavior about it's leading blank lines. i.e. if // the user has: // // class C // { // int i; // int j; // // int Prop => j; // } // // Then if we remove 'j' (or even 'i'), then 'Prop' would stay the non-first member, and // would definitely want to keep that blank line above it. // // In essence, the blank line above the property exists for separation from what's above // it. As long as something is above it, we keep the separation. However, if the // property becomes the first member in the type, the separation is now inappropriate // because there's nothing to actually separate it from. if (fieldDocument == propertyDocument) { var syntaxFacts = fieldDocument.GetLanguageService <ISyntaxFactsService>(); if (WillRemoveFirstFieldInTypeDirectlyAboveProperty(syntaxFacts, property, nodeToRemove) && syntaxFacts.GetLeadingBlankLines(nodeToRemove).Length == 0) { updatedProperty = syntaxFacts.GetNodeWithoutLeadingBlankLines(updatedProperty); } } var syntaxRemoveOptions = CreateSyntaxRemoveOptions(nodeToRemove); if (fieldDocument == propertyDocument) { // Same file. Have to do this in a slightly complicated fashion. var declaratorTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var editor = new SyntaxEditor(declaratorTreeRoot, fieldDocument.Project.Solution.Workspace); editor.ReplaceNode(property, updatedProperty); editor.RemoveNode(nodeToRemove, syntaxRemoveOptions); var newRoot = editor.GetChangedRoot(); newRoot = await FormatAsync(newRoot, fieldDocument, cancellationToken).ConfigureAwait(false); return(solution.WithDocumentSyntaxRoot(fieldDocument.Id, newRoot)); } else { // In different files. Just update both files. var fieldTreeRoot = await fieldDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var propertyTreeRoot = await propertyDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var newFieldTreeRoot = fieldTreeRoot.RemoveNode(nodeToRemove, syntaxRemoveOptions); var newPropertyTreeRoot = propertyTreeRoot.ReplaceNode(property, updatedProperty); newFieldTreeRoot = await FormatAsync(newFieldTreeRoot, fieldDocument, cancellationToken).ConfigureAwait(false); newPropertyTreeRoot = await FormatAsync(newPropertyTreeRoot, propertyDocument, cancellationToken).ConfigureAwait(false); updatedSolution = solution.WithDocumentSyntaxRoot(fieldDocument.Id, newFieldTreeRoot); updatedSolution = updatedSolution.WithDocumentSyntaxRoot(propertyDocument.Id, newPropertyTreeRoot); return(updatedSolution); } }
protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) { // We need to track unique set of processed nodes when removing the nodes. // This is because we generate an unnecessary pragma suppression diagnostic at both the pragma disable and matching pragma restore location // with the corresponding restore/disable location as an additional location to be removed. // Our code fix ensures that we remove both the disable and restore directives with a single code fix application. // So, we need to ensure that we do not attempt to remove the same node multiple times when performing a FixAll in document operation. using var _ = PooledHashSet <SyntaxNode> .GetInstance(out var processedNodes); foreach (var diagnostic in diagnostics) { RemoveNode(diagnostic.Location, editor, processedNodes); foreach (var location in diagnostic.AdditionalLocations) { RemoveNode(location, editor, processedNodes); } } return(Task.CompletedTask);
private static void DiffInSingleEditor(List<DiffMatchPatch.Diff> diffs, SyntaxEditor editor) { //editor.SuspendLayout(); //editor.SuspendPainting(); Document doc = new Document(); Color backColorGreen = Color.FromArgb(230, 255, 230); Color backColorRed = Color.FromArgb(255, 230, 230); #region Deleted style SpanIndicatorLayer deletedLayer = new SpanIndicatorLayer("Deleted", 1000); HighlightingStyle deletedHighlightingStyle = new HighlightingStyle("Deleted", null, Color.Empty, backColorRed) { StrikeOutStyle = HighlightingStyleLineStyle.Solid, StrikeOutColor = Color.Red }; doc.SpanIndicatorLayers.Add(deletedLayer); #endregion #region New style SpanIndicatorLayer newLayer = new SpanIndicatorLayer("New", 1000); HighlightingStyle newHighlightingStyle = new HighlightingStyle("New", null, Color.Empty, backColorGreen); doc.SpanIndicatorLayers.Add(newLayer); #endregion System.Text.StringBuilder sb = new System.Text.StringBuilder(10000); foreach (DiffMatchPatch.Diff aDiff in diffs) sb.Append(aDiff.text); doc.Text = sb.ToString(); int start = 0; int endOffset = 0; int i = 0; foreach (DiffMatchPatch.Diff aDiff in diffs) { int diffLength = aDiff.text.Length; switch (aDiff.operation) { case DiffMatchPatch.Operation.INSERT://green start = i; endOffset = i + diffLength; if (endOffset > start) newLayer.Add(new HighlightingStyleSpanIndicator("New", newHighlightingStyle), new TextRange(start, endOffset)); break; case DiffMatchPatch.Operation.DELETE://red start = i; endOffset = i + diffLength; if (endOffset > start) deletedLayer.Add(new HighlightingStyleSpanIndicator("Deleted", deletedHighlightingStyle), new TextRange(start, endOffset)); break; //case Operation.EQUAL: // start = i;// editor.Document.GetText(LineTerminator.Newline).Length; // //editor.Document.InsertText(DocumentModificationType.Custom, start, aDiff.text); // //editor.Document.AppendText(aDiff.text); // break; } //if (aDiff.operation != Operation.DELETE) i += diffLength; } editor.Document = doc; //editor.SelectedView.EnsureVisible(1, false); //editor.ResumeLayout(); //editor.ResumePainting(); }
private static void AutoCompleteLocalVariables(string fullString, SyntaxEditor editor) { // Let's find if this variable was declared anywhere string parentVar2 = fullString; if (fullString.IndexOf(".") > 0) { parentVar2 = fullString.Substring(0, fullString.IndexOf(".")); } Regex regex = new Regex(@"([a-zA-Z0-9]+)\s+(" + parentVar2 + "[a-zA-Z0-9]+)", RegexOptions.RightToLeft | RegexOptions.Multiline); MatchCollection matches = regex.Matches(editor.Text, editor.Caret.Offset - fullString.Length); foreach (Match match in matches) { if (match != null) { string dataTypeName = match.Value; string variableName; if (match.Groups.Count > 1) { dataTypeName = match.Groups[1].Value.Trim(); variableName = match.Groups[2].Value.Trim(); bool alreadyExists = false; for (int itemCounter = 0; itemCounter < Editor.IntelliPrompt.MemberList.Count; itemCounter++) { if (Editor.IntelliPrompt.MemberList[itemCounter].Text == variableName) { alreadyExists = true; break; } } if (!alreadyExists) { IntelliPromptMemberListItem item = new IntelliPromptMemberListItem(variableName, (int)ActiproSoftware.Products.SyntaxEditor.IconResource.InternalField, "(local variable) " + dataTypeName + " " + variableName); Editor.IntelliPrompt.MemberList.Add(item); } } } } return; }
/// <summary> /// Gets the end offset of the specified language. /// </summary> /// <param name="editor">The editor that contains the Document to search.</param> /// <param name="startOffset">The offset to start searching from.</param> /// <param name="languageTag">The value of language.Tag.ToString() that we are currently in.</param> /// <returns></returns> private static int GetEndOffsetLanguageBlock(SyntaxEditor editor, int startOffset, string languageTag) { TextStream stream = editor.Document.GetTextStream(startOffset); SyntaxLanguage language = stream.Token.Language; while (language.Tag.ToString() == languageTag) { if (stream.GoToNextToken() == false) { return stream.Token.EndOffset; } language = stream.Token.Language; } return stream.Token.StartOffset; }
private static bool FindInLocalVariables(string fullString, SyntaxEditor editor) { string[] words = fullString.Split('.'); Type parentType = null; // Let's find if this variable was declared anywhere string parentVar2 = fullString; if (fullString.IndexOf(".") > 0) { parentVar2 = fullString.Substring(0, fullString.IndexOf(".")); } if (parentVar2.IndexOf("[") >= 0) { // Typing attributes such as [Serializable] causes the Regex to blow up. int startOfWord = fullString.IndexOf("[") + 1; if (fullString.Length >= startOfWord) { parentVar2 = fullString.Substring(startOfWord); } } //Regex regex = new Regex(@"([a-zA-Z0-9]+)\s+" + parentVar2, RegexOptions.RightToLeft | RegexOptions.Multiline); // Look for type followed by a space then the variable name eg: 'String mystring.....' Regex regex = new Regex(@"([a-zA-Z0-9.]+)\s+" + parentVar2 + @"(\s+|;|,)", RegexOptions.RightToLeft | RegexOptions.Multiline); MatchCollection matches = regex.Matches(editor.Document.GetText(LineTerminator.Newline), editor.Caret.Offset - fullString.Length); foreach (Match match in matches) { if (match != null) { if (match.Groups.Count > 1) { string dataTypeName = match.Groups[1].Value.Trim(); if (dataTypeName == "in") { continue; } dataTypeName = GetValueType(dataTypeName); GetValueType(dataTypeName, ref parentType); if (parentType == null) { parentType = GetTypeFromAssemblies(dataTypeName, words.Length == 1); if (fullString.IndexOf(".") > 0) { FindInAssemblies(dataTypeName + "." + fullString.Substring(fullString.IndexOf(".") + 1)); } else { FindInAssemblies(dataTypeName); } //parentType = Project.Instance.GetTypeFromReferencedAssemblies(dataTypeName, false); } if (parentType != null) { ProcessChildren(parentType, words); } return parentType != null; } } } return false; }
private void SetCommonLineColours(int lineIndex, SyntaxEditor editor, IList<DiffLine> lines) { switch (lines[lineIndex].Change) { case ChangeType.Template: editor.Document.Lines[lineIndex].BackColor = TemplateChangeColour; break; case ChangeType.User: editor.Document.Lines[lineIndex].BackColor = UserChangeColour; break; case ChangeType.UserAndTemplate: editor.Document.Lines[lineIndex].BackColor = UserAndTemplateChangeColour; break; } if (lines[lineIndex].IsVirtual) { editor.Document.Lines[lineIndex].BackColor = VirtualLineColour; } }
/// <summary> /// Updates the find/replace options. /// </summary> private void UpdateFindReplaceOptions() { //this.editor = (owner as UCEditor).txtEditor; if (g.Main.GetActiveEditor() != null) this.editor = g.Main.GetActiveEditor().txtEditor; else this.editor = null; options.FindText = findTextBox.Text; options.ReplaceText = replaceTextBox.Text; options.MatchCase = matchCaseCheckBox.Checked; options.MatchWholeWord = matchWholeWordCheckBox.Checked; options.SearchHiddenText = searchHiddenTextCheckBox.Checked; options.SearchInSelection = searchInSelectionCheckBox.Checked; options.SearchUp = searchUpCheckBox.Checked; options.SearchType = (!searchTypeCheckBox.Checked ? FindReplaceSearchType.Normal : (searchTypeDropDownList.SelectedIndex == 0 ? FindReplaceSearchType.RegularExpression : FindReplaceSearchType.Wildcard)); }
protected override Task FixAllAsync(Document document, ImmutableArray <Diagnostic> diagnostics, SyntaxEditor editor, CancellationToken cancellationToken) { var root = editor.OriginalRoot; // Order diagnostics in reverse (from latest in file to earliest) so that we process // all inner local functions before processing outer local functions. If we don't // do this, then SyntaxEditor will fail if it tries to remove an inner local function // after already removing the outer one. var localFunctions = diagnostics.OrderBy((d1, d2) => d2.Location.SourceSpan.Start - d1.Location.SourceSpan.Start) .Select(d => root.FindToken(d.Location.SourceSpan.Start)) .Select(t => t.GetAncestor <LocalFunctionStatementSyntax>()); foreach (var localFunction in localFunctions) { editor.RemoveNode(localFunction); } return(Task.CompletedTask); }
public static async Task MakeLocalFunctionStaticAsync( Document document, LocalFunctionStatementSyntax localFunction, ImmutableArray <ISymbol> captures, SyntaxEditor syntaxEditor, CancellationToken cancellationToken) { var root = (await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false)) !; var semanticModel = (await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false)) !; var localFunctionSymbol = semanticModel.GetDeclaredSymbol(localFunction, cancellationToken); var documentImmutableSet = ImmutableHashSet.Create(document); // Finds all the call sites of the local function var referencedSymbols = await SymbolFinder.FindReferencesAsync( localFunctionSymbol, document.Project.Solution, documentImmutableSet, cancellationToken).ConfigureAwait(false); // Now we need to find all the references to the local function that we might need to fix. var shouldWarn = false; using var builderDisposer = ArrayBuilder <InvocationExpressionSyntax> .GetInstance(out var invocations); foreach (var referencedSymbol in referencedSymbols) { foreach (var location in referencedSymbol.Locations) { // We limited the search scope to the single document, // so all reference should be in the same tree. var referenceNode = root.FindNode(location.Location.SourceSpan); if (!(referenceNode is IdentifierNameSyntax identifierNode)) { // Unexpected scenario, skip and warn. shouldWarn = true; continue; } if (identifierNode.Parent is InvocationExpressionSyntax invocation) { invocations.Add(invocation); } else { // We won't be able to fix non-invocation references, // e.g. creating a delegate. shouldWarn = true; } } } var parameterAndCapturedSymbols = CreateParameterSymbols(captures); // Fix all invocations by passing in additional arguments. foreach (var invocation in invocations) { syntaxEditor.ReplaceNode( invocation, (node, generator) => { var currentInvocation = (InvocationExpressionSyntax)node; var seenNamedArgument = currentInvocation.ArgumentList.Arguments.Any(a => a.NameColon != null); var seenDefaultArgumentValue = currentInvocation.ArgumentList.Arguments.Count < localFunction.ParameterList.Parameters.Count; var newArguments = parameterAndCapturedSymbols.Select( p => (ArgumentSyntax)generator.Argument( seenNamedArgument || seenDefaultArgumentValue ? p.symbol.Name : null, p.symbol.RefKind, p.capture.Name.ToIdentifierName())); var newArgList = currentInvocation.ArgumentList.WithArguments(currentInvocation.ArgumentList.Arguments.AddRange(newArguments)); return(currentInvocation.WithArgumentList(newArgList)); }); } // In case any of the captured variable isn't camel-cased, // we need to change the referenced name inside local function to use the new parameter's name. foreach (var(parameter, capture) in parameterAndCapturedSymbols) { if (parameter.Name == capture.Name) { continue; } var referencedCaptureSymbols = await SymbolFinder.FindReferencesAsync( capture, document.Project.Solution, documentImmutableSet, cancellationToken).ConfigureAwait(false); foreach (var referencedSymbol in referencedCaptureSymbols) { foreach (var location in referencedSymbol.Locations) { var referenceSpan = location.Location.SourceSpan; if (!localFunction.FullSpan.Contains(referenceSpan)) { continue; } var referenceNode = root.FindNode(referenceSpan); if (referenceNode is IdentifierNameSyntax identifierNode) { syntaxEditor.ReplaceNode( identifierNode, (node, generator) => generator.IdentifierName(parameter.Name.ToIdentifierToken()).WithTriviaFrom(node)); } } } } // Updates the local function declaration with variables passed in as parameters syntaxEditor.ReplaceNode( localFunction, (node, generator) => { var localFunctionWithNewParameters = CodeGenerator.AddParameterDeclarations( node, parameterAndCapturedSymbols.SelectAsArray(p => p.symbol), document.Project.Solution.Workspace); if (shouldWarn) { var annotation = WarningAnnotation.Create(CSharpCodeFixesResources.Warning_colon_Adding_parameters_to_local_function_declaration_may_produce_invalid_code); localFunctionWithNewParameters = localFunctionWithNewParameters.WithAdditionalAnnotations(annotation); } return(AddStaticModifier(localFunctionWithNewParameters, CSharpSyntaxGenerator.Instance)); }); }
public void RemoveSetMethod(SyntaxEditor editor, SyntaxNode setMethodDeclaration) { editor.RemoveNode(setMethodDeclaration); }
private static async Task MoveDeclarationToFirstReferenceAsync(Document document, State state, SyntaxEditor editor, SyntaxAnnotation warningAnnotation, CancellationToken cancellationToken) { // If we're not merging with an existing declaration, make the declaration semantically // explicit to improve the chances that it won't break code. var explicitDeclarationStatement = await Simplifier.ExpandAsync( state.DeclarationStatement, document, cancellationToken : cancellationToken).ConfigureAwait(false); // place the declaration above the first statement that references it. var declarationStatement = warningAnnotation == null ? explicitDeclarationStatement : explicitDeclarationStatement.WithAdditionalAnnotations(warningAnnotation); declarationStatement = declarationStatement.WithAdditionalAnnotations(Formatter.Annotation); var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>(); var newNextStatement = state.FirstStatementAffectedInInnermostBlock; declarationStatement = declarationStatement.WithPrependedLeadingTrivia( syntaxFacts.GetLeadingBlankLines(newNextStatement)); editor.InsertBefore( state.FirstStatementAffectedInInnermostBlock, declarationStatement); editor.ReplaceNode( newNextStatement, newNextStatement.WithAdditionalAnnotations(Formatter.Annotation).WithLeadingTrivia( syntaxFacts.GetTriviaAfterLeadingBlankLines(newNextStatement))); // Move leading whitespace from the declaration statement to the next statement. var statementIndex = state.OutermostBlockStatements.IndexOf(state.DeclarationStatement); if (statementIndex + 1 < state.OutermostBlockStatements.Count) { var originalNextStatement = state.OutermostBlockStatements[statementIndex + 1]; editor.ReplaceNode( originalNextStatement, (current, generator) => current.WithAdditionalAnnotations(Formatter.Annotation).WithPrependedLeadingTrivia( syntaxFacts.GetLeadingBlankLines(state.DeclarationStatement))); } }
protected override Task HandleDeclarationAsync(Document document, SyntaxEditor editor, TypeSyntax type, CancellationToken cancellationToken) { UseImplicitTypeCodeFixProvider.ReplaceTypeWithVar(editor, type); return(Task.CompletedTask); }
public static void InsertStatement( SyntaxEditor editor, SyntaxNode functionDeclaration, IMethodSymbol method, SyntaxNode statementToAddAfterOpt, StatementSyntax statement) { var body = GetBody(functionDeclaration); if (IsExpressionBody(body)) { var semicolonToken = TryGetSemicolonToken(functionDeclaration) ?? SyntaxFactory.Token(SyntaxKind.SemicolonToken); if (!TryConvertExpressionBodyToStatement(body, semicolonToken, !method.ReturnsVoid, out var convertedStatement)) { return; } // Add the new statement as the first/last statement of the new block // depending if we were asked to go after something or not. editor.SetStatements(functionDeclaration, statementToAddAfterOpt == null ? ImmutableArray.Create(statement, convertedStatement) : ImmutableArray.Create(convertedStatement, statement)); } else if (body is BlockSyntax block) { // Look for the statement we were asked to go after. var indexToAddAfter = block.Statements.IndexOf(s => s == statementToAddAfterOpt); if (indexToAddAfter >= 0) { // If we find it, then insert the new statement after it. editor.InsertAfter(block.Statements[indexToAddAfter], statement); } else if (block.Statements.Count > 0) { // Otherwise, if we have multiple statements already, then insert ourselves // before the first one. editor.InsertBefore(block.Statements[0], statement); } else { // Otherwise, we have no statements in this block. Add the new statement // as the single statement the block will have. Debug.Assert(block.Statements.Count == 0); editor.ReplaceNode(block, (currentBlock, _) => ((BlockSyntax)currentBlock).AddStatements(statement)); } // If the block was on a single line before, the format it so that the formatting // engine will update it to go over multiple lines. Otherwise, we can end up in // the strange state where the { and } tokens stay where they were originally, // which will look very strange like: // // a => { // if (...) { // } }; if (CSharpSyntaxFacts.Instance.IsOnSingleLine(block, fullSpan: false)) { editor.ReplaceNode( block, (currentBlock, _) => currentBlock.WithAdditionalAnnotations(Formatter.Annotation)); } } else { editor.SetStatements(functionDeclaration, ImmutableArray.Create(statement)); } }
protected override void AssignOutParameters( SyntaxEditor editor, SyntaxNode container, MultiDictionary <SyntaxNode, (SyntaxNode exprOrStatement, ImmutableArray <IParameterSymbol> unassignedParameters)> .ValueSet values,
protected override void InsertAtStartOfSwitchCaseBlockForDeclarationInCaseLabelOrClause(SwitchSectionSyntax switchCaseBlock, SyntaxEditor editor, LocalDeclarationStatementSyntax declarationStatement) { var firstStatement = switchCaseBlock.Statements.FirstOrDefault(); if (firstStatement != null) { editor.InsertBefore(firstStatement, declarationStatement); } else { // Switch section without any statements is an error case. // Insert before containing switch statement. editor.InsertBefore(switchCaseBlock.Parent, declarationStatement); } }
protected abstract Task HandleDeclarationAsync( Document document, SyntaxEditor editor, TypeSyntax type, CancellationToken cancellationToken );
public void NotifyDocumentTextChanging(SyntaxEditor editor, EditorSnapshotChangingEventArgs e) { }
public void ReplaceSetReference(SyntaxEditor editor, SyntaxToken nameToken, string propertyName, bool nameChanged) => ReplaceInvocation(editor, nameToken, propertyName, nameChanged, s_replaceSetReferenceInvocation);
private TabPage AddNewProgramToTab(TabControl tabControl, string FileName) { SyntaxEditor edit = new SyntaxEditor(this); TabPage toAdd = AddNewTab(tabControl); edit.AddToTab(toAdd); toAdd.Tag = new Data(FileName, edit, false); SetTabPageText(toAdd); edit.SetHighlightingStrategyForFile(FileName); //ivan AddBreakPointHandler(toAdd); //\ivan return toAdd; }
/// <summary> /// Loads two languages and creates a state transition from XML to C# within ASP-style directives. /// </summary> public static void SetupEditorTemplateAndScriptLanguages(SyntaxEditor editor, TemplateContentLanguage textLanguage, ScriptLanguageTypes scriptLanguage, string delimiterStart, string delimiterEnd) { DynamicSyntaxLanguage language = GetDynamicLanguage(textLanguage); DynamicSyntaxLanguage cSharpLanguage = GetDynamicLanguage(GetScriptingLanguage(scriptLanguage)); language.AutomaticOutliningBehavior = AutomaticOutliningBehavior.PostSemanticParse; cSharpLanguage.AutomaticOutliningBehavior = AutomaticOutliningBehavior.PostSemanticParse; language.Tag = "TemplateLanguage"; cSharpLanguage.Tag = "ScriptLanguage"; // Mark that updating is starting language.IsUpdating = true; cSharpLanguage.IsUpdating = true; // Add StateTransitions to current language as well nested languages eg: HTML -> JavaScript, VBScript etc. for (int i = 0; i <= language.ChildLanguages.Count; i++) { DynamicSyntaxLanguage lan; if (i == language.ChildLanguages.Count) { lan = language; } else { lan = (DynamicSyntaxLanguage)language.ChildLanguages[i]; } // Add a highlighting style lan.HighlightingStyles.Add(new HighlightingStyle("ASPDirectiveDelimiterStyle", null, Color.Black, ASP_DIRECTIVE_COLOUR)); lan.AutomaticOutliningBehavior = AutomaticOutliningBehavior.SemanticParseDataChange; // Create a new lexical state DynamicLexicalState lexicalState = new DynamicLexicalState(0, "ASPDirectiveState"); lexicalState.DefaultTokenKey = "ASPDirectiveDefaultToken"; lexicalState.DefaultHighlightingStyle = lan.HighlightingStyles["DefaultStyle"]; lexicalState.LexicalStateTransitionLexicalState = cSharpLanguage.LexicalStates["DefaultState"]; lan.LexicalStates.Add(lexicalState); // Add the new lexical state at the beginning of the child states... // Remember that with an NFA regular expression, the first match is taken... // So since a < scope pattern is already in place, we must insert the new one before it lan.LexicalStates["DefaultState"].ChildLexicalStates.Insert(0, lexicalState); #region Extra Transition points - Eg: comments if (lan.LexicalStates.IndexOf("XMLCommentState") >= 0) // C# { lan.LexicalStates["XMLCommentState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } if (lan.LexicalStates.IndexOf("CommentState") >= 0) // C# { lan.LexicalStates["CommentState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } if (lan.LexicalStates.IndexOf("StringState") >= 0) // SQL { // Note: Had to modify the RegexPatternGroup for StringState in ActiproSoftware.SQL.xml to: <RegexPatternGroup TokenKey="StringDefaultToken" PatternValue="[^<^']+" /> lan.LexicalStates["StringState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } if (lan.LexicalStates.IndexOf("SquareStringState") >= 0) // SQL { lan.LexicalStates["SquareStringState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } if (lan.LexicalStates.IndexOf("MultiLineCommentState") >= 0) // SQL { lan.LexicalStates["MultiLineCommentState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } if (lan.LexicalStates.IndexOf("StartTagState") >= 0) // HTML { lan.LexicalStates["StartTagState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } if (lan.LexicalStates.IndexOf("StartTagAttributeStringValueState") >= 0) // HTML { lan.LexicalStates["StartTagAttributeStringValueState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } if (lan.LexicalStates.IndexOf("StartTagAttributeState") >= 0) // HTML { lan.LexicalStates["StartTagAttributeState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } if (lan.LexicalStates.IndexOf("StartTagAttributeValueState") >= 0) // HTML { lan.LexicalStates["StartTagAttributeValueState"].ChildLexicalStates.Insert(0, lexicalState); // Added this to ensure that transitions can occur in XML Comments } // Create a lexical scope with a lexical state transition DynamicLexicalScope lexicalScope = new DynamicLexicalScope(); lexicalState.LexicalScopes.Add(lexicalScope); lexicalScope.StartLexicalPatternGroup = new LexicalPatternGroup(LexicalPatternType.Explicit, "ASPDirectiveStartToken", lan.HighlightingStyles["ASPDirectiveDelimiterStyle"], delimiterStart); lexicalScope.StartLexicalPatternGroup.LookBehindPattern = @"\\{2}|([^\\]|^)";// @"\\{2}|[^\\]"; lexicalScope.EndLexicalPatternGroup = new LexicalPatternGroup(LexicalPatternType.Explicit, "ASPDirectiveEndToken", lan.HighlightingStyles["ASPDirectiveDelimiterStyle"], delimiterEnd); lexicalScope.AncestorEndScopeCheckEnabled = false; } #endregion // Mark that updating is complete (since linking is complete, the flag setting // will filter from the XML language into the C# language) language.IsUpdating = false; editor.Document.Language = language; }