/// <summary> /// Handle the Comment Selection and Uncomment Selection editor commands. These commands comment/uncomment /// the currently selected lines. /// </summary> /// <param name="editorContext">The editor context</param> /// <param name="action">The requested command is Comment Selection, otherwise Uncomment Selection</param> /// <returns>True if the operation succeeds to comment/uncomment the selected lines, false otherwise</returns> public bool CommentOrUncommentSelection(GherkinEditorContext editorContext, CommentUncommentAction action) { var selectionStartLine = editorContext.TextView.Selection.Start.Position.GetContainingLine(); var selectionEndLine = GetSelectionEndLine(selectionStartLine, editorContext.TextView); switch (action) { case CommentUncommentAction.Comment: CommentSelection(selectionStartLine, selectionEndLine); break; case CommentUncommentAction.Uncomment: UncommentSelection(selectionStartLine, selectionEndLine); break; case CommentUncommentAction.Toggle: if (IsCommented(selectionStartLine)) { UncommentSelection(selectionStartLine, selectionEndLine); } else { CommentSelection(selectionStartLine, selectionEndLine); } break; } // Select the entirety of the lines that were just commented or uncommented, have to update start/end lines due to snapshot changes selectionStartLine = editorContext.TextView.Selection.Start.Position.GetContainingLine(); selectionEndLine = GetSelectionEndLine(selectionStartLine, editorContext.TextView); editorContext.TextView.Selection.Select(new SnapshotSpan(selectionStartLine.Start, selectionEndLine.End), false); return(true); }
private void ReplaceStepBindingAttribute(CodeFunction codeFunction, IStepDefinitionBinding binding, string newRegex) { if (!codeFunction.ProjectItem.IsOpen) { codeFunction.ProjectItem.Open(); } var formattedOldRegex = FormatRegexForDisplay(binding.Regex); var navigatePoint = codeFunction.GetStartPoint(vsCMPart.vsCMPartHeader); navigatePoint.TryToShow(); navigatePoint.Parent.Selection.MoveToPoint(navigatePoint); var stepBindingEditorContext = GherkinEditorContext.FromDocument(codeFunction.DTE.ActiveDocument, _gherkinLanguageServiceFactory); var attributeLinesToUpdate = stepBindingEditorContext.TextView.TextViewLines.Where(x => x.Start.GetContainingLine().GetText().Contains("\"" + formattedOldRegex + "\"")); foreach (var attributeLineToUpdate in attributeLinesToUpdate) { using (var textEdit = attributeLineToUpdate.Snapshot.TextBuffer.CreateEdit()) { var regexStart = attributeLineToUpdate.Start.GetContainingLine().GetText().IndexOf(formattedOldRegex); textEdit.Replace(attributeLineToUpdate.Start.Position + regexStart, formattedOldRegex.Length, newRegex); textEdit.Apply(); } } }
private static IStepDefinitionBinding GetSingleStepDefinitionBinding(GherkinEditorContext editorContext, GherkinStep step) { var bindingMatchService = editorContext.LanguageService.ProjectScope.BindingMatchService; if (bindingMatchService == null) { return(null); } if (!bindingMatchService.Ready) { MessageBox.Show("Step bindings are still being analyzed. Please wait.", "Go to binding"); return(null); } List <BindingMatch> candidatingMatches; StepDefinitionAmbiguityReason ambiguityReason; CultureInfo bindingCulture = editorContext.ProjectScope.SpecFlowConfiguration.BindingCulture ?? step.StepContext.Language; var match = bindingMatchService.GetBestMatch(step, bindingCulture, out ambiguityReason, out candidatingMatches); if (candidatingMatches.Count > 1 || !match.Success) { MessageBox.Show("Cannot rename automatically. You need to have a single and unique binding for this step."); return(null); } return(match.StepBinding); }
public bool FormatTable(GherkinEditorContext editorContext) { if (!editorContext.LanguageService.ProjectScope.IntegrationOptionsProvider.GetOptions().EnableTableAutoFormat) { return(false); } var fileScope = editorContext.LanguageService.GetFileScope(waitForLatest: true); if (fileScope == null) { return(false); } SnapshotPoint caret = editorContext.TextView.Caret.Position.BufferPosition; var triggerLineNumber = caret.GetContainingLine().LineNumber; var stepBlock = fileScope.GetStepBlockFromStepPosition(triggerLineNumber); var step = stepBlock.Steps.LastOrDefault(s => s.BlockRelativeLine + stepBlock.KeywordLine < triggerLineNumber); if (step == null) { return(false); } var stepArgStartPoint = editorContext.TextView.TextSnapshot.GetLineFromLineNumber(stepBlock.KeywordLine + step.BlockRelativeLine + 1).Start; var stepArgsEndPoint = caret.GetContainingLine().End; // Determine what line the table starts on var startLine = caret.GetContainingLine().LineNumber; var previousLineText = caret.Snapshot.GetLineFromLineNumber(startLine - 1).GetText(); while (startLine > 0 && (IsTable(previousLineText) || CommentUncommentCommand.IsComment(previousLineText))) { previousLineText = caret.Snapshot.GetLineFromLineNumber(--startLine - 1).GetText(); } var start = caret.Snapshot.GetLineFromLineNumber(startLine).Start; var span = new SnapshotSpan(start, caret); string oldTable = span.GetText(); string formattedTable = FormatTableString(oldTable); if (formattedTable == null || formattedTable.Equals(oldTable)) { return(false); } var textEdit = span.Snapshot.TextBuffer.CreateEdit(); textEdit.Replace(span, formattedTable); textEdit.Apply(); return(true); }
private void ConfigureLineBreakOptions(GherkinEditorContext editorContext) { var options = editorContext.LanguageService.ProjectScope.IntegrationOptionsProvider.GetOptions(); _normalizeLineBreaks = options.NormalizeLineBreaks; _lineBreaksBeforeScenario = options.LineBreaksBeforeScenario; _lineBreaksBeforeExamples = options.LineBreaksBeforeExamples; var indentType = options.UseTabsForIndent ? '\t' : ' '; _featureIndent = new string(indentType, options.FeatureIndent); _scenarioIndent = new string(indentType, options.ScenarioIndent); _stepIndent = new string(indentType, options.StepIndent); _tableIndent = new string(indentType, options.TableIndent); _multilineIndent = new string(indentType, options.MultilineIndent); _exampleIndent = new string(indentType, options.ExampleIndent); }
public bool FormatDocument(GherkinEditorContext editorContext) { ConfigureLineBreakOptions(editorContext); var dialect = GetDialect(editorContext.LanguageService); var textSnapshot = editorContext.TextView.TextSnapshot; var textLines = textSnapshot.Lines .Select(line => line.GetText()) .ToList(); var formattedTextLines = FormatText(textLines, dialect); ReplaceText(textSnapshot, formattedTextLines); return(true); }
private static GherkinStep GetCurrentStep(GherkinEditorContext editorContext) { var fileScope = editorContext.LanguageService.GetFileScope(waitForLatest: true); if (fileScope == null) { return(null); } SnapshotPoint caret = editorContext.TextView.Caret.Position.BufferPosition; IStepBlock block; var step = fileScope.GetStepAtPosition(caret.GetContainingLine().LineNumber, out block); if (step != null && block is IScenarioOutlineBlock) { step = step.GetSubstitutedStep((IScenarioOutlineBlock)block); } return(step); }
private void RenameStep(StepInstanceWithProjectScope stepInstance, string newStepRegex, IStepDefinitionBinding binding) { var featureFileDocument = JumpToStep(stepInstance); if (featureFileDocument == null) { return; } var stepEditorContext = GherkinEditorContext.FromDocument(featureFileDocument, _gherkinLanguageServiceFactory); var stepToRename = GetCurrentStep(stepEditorContext); if (stepToRename == null) { return; } if (!binding.Regex.IsMatch(stepToRename.Text)) { return; } var stepLineStart = stepEditorContext.TextView.Selection.Start.Position.GetContainingLine(); using (var stepNameTextEdit = stepLineStart.Snapshot.TextBuffer.CreateEdit()) { var line = stepLineStart.Snapshot.GetLineFromLineNumber(stepLineStart.LineNumber); var lineText = line.GetText(); var trimmedText = lineText.Trim(); var numLeadingWhiteSpaces = lineText.Length - trimmedText.Length; var actualStepName = trimmedText.Substring(stepToRename.Keyword.Length); var newStepName = BuildStepNameWithNewRegex(actualStepName, newStepRegex, binding); var stepNamePosition = line.Start.Position + numLeadingWhiteSpaces + stepToRename.Keyword.Length; stepNameTextEdit.Replace(stepNamePosition, actualStepName.Length, newStepName); stepNameTextEdit.Apply(); } }
public bool Rename(GherkinEditorContext editorContext) { var step = GetCurrentStep(editorContext); if (step == null) { return(false); } var stepBinding = GetSingleStepDefinitionBinding(editorContext, step); if (stepBinding == null) { return(false); } var codeFunction = FindBindingMethodCodeFunction(editorContext, stepBinding); if (codeFunction == null) { return(false); } var newStepRegex = PromptForNewStepRegex(stepBinding.Regex); if (string.IsNullOrEmpty(newStepRegex)) { return(false); } var stepInstancesToRename = FindAllStepMatchingStepInstances(codeFunction.DTE.ActiveDocument, stepBinding.Method); foreach (var stepInstanceToRename in stepInstancesToRename) { RenameStep(stepInstanceToRename, newStepRegex, stepBinding); } ReplaceStepBindingAttribute(codeFunction, stepBinding, newStepRegex); return(true); }
public void PostExec(GherkinEditorContext editorContext, Guid pguidCmdGroup, uint nCmdID, IntPtr pvaIn) { if (pguidCmdGroup == VSConstants.VSStd2K) { switch ((VSConstants.VSStd2KCmdID)nCmdID) { case VSConstants.VSStd2KCmdID.TYPECHAR: var ch = GetTypeChar(pvaIn); if (ch == '|') { formatTableCommand.FormatTable(editorContext); } break; } } //uncomment this to add further command handlers // if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97) // { // switch ((VSConstants.VSStd97CmdID)nCmdID) // { // } // } }
public bool QueryStatus(GherkinEditorContext editorContext, Guid pguidCmdGroup, OLECMD prgCmd) { if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97) { var vsStd97CmdId = (VSConstants.VSStd97CmdID)prgCmd.cmdID; #if TRACE_VS_COMMANDS tracer.Trace("QueryStatus/VSStd97CmdID:{0}", this, vsStd97CmdId); #endif switch (vsStd97CmdId) { case VSConstants.VSStd97CmdID.GotoDefn: if (goToStepDefinitionCommand.CanGoToDefinition(editorContext)) { return(true); } break; } } else if (pguidCmdGroup == VSConstants.VSStd2K) { var vsStd2KCmdId = (VSConstants.VSStd2KCmdID)prgCmd.cmdID; #if TRACE_VS_COMMANDS tracer.Trace("QueryStatus/VSStd2KCmdID:{0}", this, vsStd2KCmdId); #endif switch (vsStd2KCmdId) { case VSConstants.VSStd2KCmdID.COMMENT_BLOCK: case VSConstants.VSStd2KCmdID.COMMENTBLOCK: case VSConstants.VSStd2KCmdID.UNCOMMENT_BLOCK: case VSConstants.VSStd2KCmdID.UNCOMMENTBLOCK: case VSConstants.VSStd2KCmdID.RENAME: return(true); } } else if (pguidCmdGroup == GuidList.guidSpecFlowCmdSet) { var specFlowCmdSet = (SpecFlowCmdSet)prgCmd.cmdID; #if TRACE_VS_COMMANDS tracer.Trace("QueryStatus/SpecFlowCmdSet:{0}", this, specFlowCmdSet); #endif switch (specFlowCmdSet) { case SpecFlowCmdSet.RunScenarios: case SpecFlowCmdSet.DebugScenarios: return(true); } } else if (pguidCmdGroup == ReSharperCommandGroups.CommandGroup) { var reSharperCmd = (ReSharperCommand)prgCmd.cmdID; #if TRACE_VS_COMMANDS tracer.Trace("QueryStatus/ReSharperCommand:{0}", this, reSharperCmd); #endif switch (reSharperCmd) { case ReSharperCommand.GotoDeclaration: if (goToStepDefinitionCommand.CanGoToDefinition(editorContext)) { return(true); } break; case ReSharperCommand.LineComment: return(true); case ReSharperCommand.UnitTestRunContext: case ReSharperCommand.UnitTestDebugContext: return(true); } } #if TRACE_VS_COMMANDS else { tracer.Trace("QueryStatus/Other:{0} / {1}", this, pguidCmdGroup, prgCmd.cmdID); } #endif return(false); }
public bool PreExec(GherkinEditorContext editorContext, Guid pguidCmdGroup, uint nCmdID) { if (pguidCmdGroup == VSConstants.GUID_VSStandardCommandSet97) { var vsStd97CmdId = (VSConstants.VSStd97CmdID)nCmdID; #if TRACE_VS_COMMANDS if (vsStd97CmdId != VSConstants.VSStd97CmdID.SearchCombo && vsStd97CmdId != VSConstants.VSStd97CmdID.SolutionCfg) { tracer.Trace("Exec/VSStd97CmdID:{0}", this, vsStd97CmdId); } #endif switch (vsStd97CmdId) { case VSConstants.VSStd97CmdID.GotoDefn: if (goToStepDefinitionCommand.GoToDefinition(editorContext)) { return(true); } break; } } else if (pguidCmdGroup == VSConstants.VSStd2K) { var vsStd2KCmdId = (VSConstants.VSStd2KCmdID)nCmdID; #if TRACE_VS_COMMANDS tracer.Trace("Exec/VSStd2KCmdID:{0}", this, vsStd2KCmdId); #endif switch (vsStd2KCmdId) { case VSConstants.VSStd2KCmdID.COMMENT_BLOCK: case VSConstants.VSStd2KCmdID.COMMENTBLOCK: if (commentUncommentCommand.CommentOrUncommentSelection(editorContext, CommentUncommentAction.Comment)) { return(true); } break; case VSConstants.VSStd2KCmdID.UNCOMMENT_BLOCK: case VSConstants.VSStd2KCmdID.UNCOMMENTBLOCK: if (commentUncommentCommand.CommentOrUncommentSelection(editorContext, CommentUncommentAction.Uncomment)) { return(true); } break; case VSConstants.VSStd2KCmdID.RENAME: if (renameCommand.Rename(editorContext)) { return(true); } break; } } else if (pguidCmdGroup == GuidList.guidSpecFlowCmdSet) { var specFlowCmdSet = (SpecFlowCmdSet)nCmdID; #if TRACE_VS_COMMANDS tracer.Trace("Exec/SpecFlowCmdSet:{0}", this, specFlowCmdSet); #endif } else if (pguidCmdGroup == ReSharperCommandGroups.CommandGroup) { var reSharperCmd = (ReSharperCommand)nCmdID; #if TRACE_VS_COMMANDS tracer.Trace("Exec/ReSharperCommand:{0}", this, reSharperCmd); #endif switch (reSharperCmd) { case ReSharperCommand.GotoDeclaration: if (goToStepDefinitionCommand.GoToDefinition(editorContext)) { return(true); } break; case ReSharperCommand.LineComment: if (commentUncommentCommand.CommentOrUncommentSelection(editorContext, CommentUncommentAction.Toggle)) { return(true); } break; } } #if TRACE_VS_COMMANDS else { tracer.Trace("Exec/Other:{0} / {1}", this, pguidCmdGroup, nCmdID); } #endif return(false); }
private static CodeFunction FindBindingMethodCodeFunction(GherkinEditorContext editorContext, IStepDefinitionBinding binding) { return(new VsBindingMethodLocator().FindCodeFunction(((VsProjectScope)editorContext.ProjectScope), binding.Method)); }