private GherkinFileScopeChange GetInvalidDialectScopeChange(GherkinTextBufferChange change) { var fileScope = new GherkinFileScope(null, change.ResultTextSnapshot) { InvalidFileEndingBlock = new InvalidFileBlock(0, change.ResultTextSnapshot.LineCount - 1, new ErrorInfo("Invalid Gherkin dialect!", 0, 0, null)) }; return GherkinFileScopeChange.CreateEntireScopeChange(fileScope); }
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); }
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)); }
public GherkinFileScopeChange Parse(GherkinTextBufferChange change, IGherkinFileScope previousScope = null) { var gherkinDialect = GetGherkinDialect(change.ResultTextSnapshot); if (gherkinDialect == null) return GetInvalidDialectScopeChange(change); bool fullParse = false; if (previousScope == null) fullParse = true; else if (!Equals(previousScope.GherkinDialect, gherkinDialect)) fullParse = true; else if (partialParseCount >= PartialParseCountLimit) fullParse = true; else if (GetFirstAffectedScenario(change, previousScope) == null) fullParse = true; if (fullParse) return FullParse(change.ResultTextSnapshot, gherkinDialect); return PartialParse(change, previousScope); }
public ParsingTask(GherkinLanguageService languageService, GherkinTextBufferChange change) { this.languageService = languageService; this.change = change; }
/// <summary> /// Registers a change in the text buffer for the language service. The processing of the change is asynchronous, so it does not block the caller. /// </summary> public void TextBufferChanged(GherkinTextBufferChange change) { if (isDisposed) throw new ObjectDisposedException("GherkinLanguageService"); lastRegisteredSnapshot = change.ResultTextSnapshot; var task = new ParsingTask(this, change); projectScope.GherkinProcessingScheduler.EnqueueParsingRequest(task); // task.Apply(); // synchronous execution }
private IScenarioBlock GetFirstAffectedScenario(GherkinTextBufferChange change, IGherkinFileScope previousScope) { if (change.Type == GherkinTextBufferChangeType.SingleLine) //single-line changes on the start cannot influence the previous scenario return previousScope.ScenarioBlocks.LastOrDefault(s => s.GetStartLine() <= change.StartLine); // if multiple lines are added at the first line of a block, it can happen that these lines will belong // to the previous block return previousScope.ScenarioBlocks.LastOrDefault(s => s.GetStartLine() < change.StartLine); }
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; }