/// <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);
        }
Exemple #2
0
        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();
                }
            }
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #7
0
        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);
        }
Exemple #8
0
        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();
            }
        }
Exemple #9
0
        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);
        }
Exemple #10
0
        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)
//                    {
//                    }
//                }
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        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);
        }
Exemple #13
0
 private static CodeFunction FindBindingMethodCodeFunction(GherkinEditorContext editorContext, IStepDefinitionBinding binding)
 {
     return(new VsBindingMethodLocator().FindCodeFunction(((VsProjectScope)editorContext.ProjectScope), binding.Method));
 }