public void Init(GherkinBuffer buffer, bool isPartialScan)
        {
            gherkinBuffer = buffer;

            InitializeFirstBlock(gherkinBuffer.GetLineStartPosition(gherkinBuffer.LineOffset));
            VisualStudioTracer.Assert(currentFileBlockBuilder != null, "no current file block builder");
        }
        public static SnapshotSpan CreateSpan(this IEnumerable <IGherkinFileBlock> changedBlocks, ITextSnapshot textSnapshot)
        {
            VisualStudioTracer.Assert(changedBlocks.Any(), "there is no changed block");

            int minLineNumber = changedBlocks.First().GetStartLine();
            int maxLineNumber = changedBlocks.Last().GetEndLine();

            var minLine = textSnapshot.GetLineFromLineNumber(minLineNumber);
            var maxLine = minLineNumber == maxLineNumber ? minLine : textSnapshot.GetLineFromLineNumber(maxLineNumber);

            return(new SnapshotSpan(minLine.Start, maxLine.EndIncludingLineBreak));
        }
        public void Build(GherkinFileScope gherkinFileEditorInfo, int endLine, int contentEndLine)
        {
            VisualStudioTracer.Assert(IsComplete, "The block builder is not complete");
            int blockRelativeEndLine        = endLine - KeywordLine;
            int blockRelativeContentEndLine = contentEndLine - KeywordLine;

            if (BlockType == typeof(IInvalidFileBlock))
            {
                VisualStudioTracer.Assert(gherkinFileEditorInfo.InvalidFileEndingBlock == null, "no invalid file block");
                if (gherkinFileEditorInfo.InvalidFileEndingBlock == null)
                {
                    gherkinFileEditorInfo.InvalidFileEndingBlock =
                        new InvalidFileBlock(StartLine, endLine, blockRelativeContentEndLine, ClassificationSpans.ToArray(), OutliningRegions.ToArray(), Errors.ToArray());
                }
            }
            else if (BlockType == typeof(IHeaderBlock))
            {
                VisualStudioTracer.Assert(gherkinFileEditorInfo.HeaderBlock == null, "no header block");
                if (gherkinFileEditorInfo.HeaderBlock == null)
                {
                    gherkinFileEditorInfo.HeaderBlock =
                        new HeaderBlock(Keyword, Title, KeywordLine, Tags.ToArray(), BlockRelativeStartLine, blockRelativeEndLine, blockRelativeContentEndLine, ClassificationSpans.ToArray(), OutliningRegions.ToArray(), Errors.ToArray());
                }
            }
            else if (BlockType == typeof(IBackgroundBlock))
            {
                VisualStudioTracer.Assert(gherkinFileEditorInfo.BackgroundBlock == null, "no background block");
                if (gherkinFileEditorInfo.BackgroundBlock == null)
                {
                    gherkinFileEditorInfo.BackgroundBlock =
                        new BackgroundBlock(Keyword, Title, KeywordLine, BlockRelativeStartLine, blockRelativeEndLine, blockRelativeContentEndLine, ClassificationSpans.ToArray(), OutliningRegions.ToArray(), Errors.ToArray(), Steps.ToArray());
                }
            }
            else if (BlockType == typeof(IScenarioBlock))
            {
                var scenarioBlock = new ScenarioBlock(Keyword, Title, KeywordLine, BlockRelativeStartLine, blockRelativeEndLine, blockRelativeContentEndLine, ClassificationSpans.ToArray(), OutliningRegions.ToArray(), Errors.ToArray(), Steps.ToArray());
                gherkinFileEditorInfo.ScenarioBlocks.Add(scenarioBlock);
            }
            else if (BlockType == typeof(IScenarioOutlineBlock))
            {
                var scenarioBlock = new ScenarioOutlineBlock(Keyword, Title, KeywordLine, BlockRelativeStartLine, blockRelativeEndLine, blockRelativeContentEndLine, ClassificationSpans.ToArray(), OutliningRegions.ToArray(), Errors.ToArray(), Steps.ToArray(), ExampleSets.ToArray());
                gherkinFileEditorInfo.ScenarioBlocks.Add(scenarioBlock);
            }
            else
            {
                throw new NotSupportedException("Block type not supported: " + BlockType);
            }
        }
Example #4
0
        protected override string GenerateError(IVsGeneratorProgress pGenerateProgress, Exception ex)
        {
            if (ex == null)
            {
                VisualStudioTracer.Assert(generationResult != null, "no reneration result found");
                VisualStudioTracer.Assert(!generationResult.Success, "generation result is not a failure");

                foreach (var error in generationResult.Errors)
                {
                    pGenerateProgress.GeneratorError(0, 4, error.Message, (uint)error.Line, (uint)error.LinePosition);
                }

                return(string.Join(Environment.NewLine, generationResult.Errors.Select(e => e.Message)));
            }
            return(base.GenerateError(pGenerateProgress, ex));
        }
        private GherkinFileScopeChange MergePartialResult(IGherkinFileScope previousScope, IGherkinFileScope partialResult, IScenarioBlock firstAffectedScenario, IScenarioBlock firstUnchangedScenario, int lineCountDelta)
        {
            Debug.Assert(partialResult.HeaderBlock == null, "Partial parse cannot re-parse header");
            Debug.Assert(partialResult.BackgroundBlock == null, "Partial parse cannot re-parse background");

            List <IGherkinFileBlock> changedBlocks = new List <IGherkinFileBlock>();
            List <IGherkinFileBlock> shiftedBlocks = new List <IGherkinFileBlock>();

            GherkinFileScope fileScope = new GherkinFileScope(previousScope.GherkinDialect, partialResult.TextSnapshot)
            {
                HeaderBlock     = previousScope.HeaderBlock,
                BackgroundBlock = previousScope.BackgroundBlock
            };

            // inserting the non-affected scenarios
            fileScope.ScenarioBlocks.AddRange(previousScope.ScenarioBlocks.TakeUntilItemExclusive(firstAffectedScenario));

            //inserting partial result
            fileScope.ScenarioBlocks.AddRange(partialResult.ScenarioBlocks);
            changedBlocks.AddRange(partialResult.ScenarioBlocks);
            if (partialResult.InvalidFileEndingBlock != null)
            {
                VisualStudioTracer.Assert(firstUnchangedScenario == null, "first affected scenario is not null");
                // the last scenario was changed, but it became invalid
                fileScope.InvalidFileEndingBlock = partialResult.InvalidFileEndingBlock;
                changedBlocks.Add(fileScope.InvalidFileEndingBlock);
            }

            if (firstUnchangedScenario != null)
            {
                Tracing.VisualStudioTracer.Assert(partialResult.InvalidFileEndingBlock == null, "there is an invalid file ending block");

                // inserting the non-effected scenarios at the end
                var shiftedScenarioBlocks = previousScope.ScenarioBlocks.SkipFromItemInclusive(firstUnchangedScenario)
                                            .Select(scenario => scenario.Shift(lineCountDelta)).ToArray();
                fileScope.ScenarioBlocks.AddRange(shiftedScenarioBlocks);
                shiftedBlocks.AddRange(shiftedScenarioBlocks);

                if (previousScope.InvalidFileEndingBlock != null)
                {
                    fileScope.InvalidFileEndingBlock = previousScope.InvalidFileEndingBlock.Shift(lineCountDelta);
                    shiftedBlocks.Add(fileScope.InvalidFileEndingBlock);
                }
            }

            return(new GherkinFileScopeChange(fileScope, false, false, changedBlocks, shiftedBlocks));
        }
        private GherkinFileScopeChange PartialParse(GherkinTextBufferChange change, IGherkinFileScope previousScope)
        {
            visualStudioTracer.Trace("Start incremental parsing", ParserTraceCategory);
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();

            partialParseCount++;

            var textSnapshot = change.ResultTextSnapshot;

            IScenarioBlock firstAffectedScenario = GetFirstAffectedScenario(change, previousScope);

            VisualStudioTracer.Assert(firstAffectedScenario != null, "first affected scenario is null");
            int parseStartPosition = textSnapshot.GetLineFromLineNumber(firstAffectedScenario.GetStartLine()).Start;

            string fileContent = textSnapshot.GetText(parseStartPosition, textSnapshot.Length - parseStartPosition);

            var gherkinListener = new GherkinTextBufferPartialParserListener(
                previousScope.GherkinDialect,
                textSnapshot, projectScope,
                previousScope,
                change.EndLine, change.LineCountDelta);

            var scanner = new GherkinScanner(previousScope.GherkinDialect, fileContent, firstAffectedScenario.GetStartLine());

            IScenarioBlock firstUnchangedScenario = null;

            try
            {
                scanner.Scan(gherkinListener);
            }
            catch (PartialListeningDoneException partialListeningDoneException)
            {
                firstUnchangedScenario = partialListeningDoneException.FirstUnchangedScenario;
            }

            var partialResult = gherkinListener.GetResult();

            var result = MergePartialResult(previousScope, partialResult, firstAffectedScenario, firstUnchangedScenario, change.LineCountDelta);

            stopwatch.Stop();
            TraceFinishParse(stopwatch, "incremental", result);
            return(result);
        }
        public static GherkinTextBufferChange Merge(GherkinTextBufferChange change1, GherkinTextBufferChange change2)
        {
            VisualStudioTracer.Assert(change1.ResultTextSnapshot.Version.VersionNumber <= change2.ResultTextSnapshot.Version.VersionNumber, "different snapshot version numbers for merging");
            if (change1.Type == GherkinTextBufferChangeType.EntireFile || change2.Type == GherkinTextBufferChangeType.EntireFile)
            {
                return(CreateEntireBufferChange(change2.ResultTextSnapshot));
            }

            return(new GherkinTextBufferChange(
                       change1.Type == GherkinTextBufferChangeType.MultiLine || change2.Type == GherkinTextBufferChangeType.MultiLine ? GherkinTextBufferChangeType.MultiLine : GherkinTextBufferChangeType.SingleLine,
                       Math.Min(change1.StartLine, change2.StartLine),
                       Math.Max(change1.EndLine, change2.EndLine),
                       Math.Min(change1.StartPosition, change2.StartPosition),
                       Math.Max(change1.EndPosition, change2.EndPosition),
                       change1.LineCountDelta + change2.LineCountDelta,
                       change1.PositionDelta + change2.PositionDelta,
                       change2.ResultTextSnapshot));
        }