private void TriggerChanges(GherkinFileEditorInfo gherkinFileEditorInfo, ChangeInfo changeInfo, ScenarioEditorInfo firstAffectedScenario = null, ScenarioEditorInfo firstUnchangedScenario = null) { this.GherkinFileEditorInfo = gherkinFileEditorInfo; var textSnapshot = changeInfo.TextSnapshot; int startPosition = 0; if (firstAffectedScenario != null) startPosition = textSnapshot.GetLineFromLineNumber(firstAffectedScenario.StartLine).Start; int endPosition = textSnapshot.Length; if (firstUnchangedScenario != null) endPosition = textSnapshot.GetLineFromLineNumber(firstUnchangedScenario.StartLine).Start; var snapshotSpan = new SnapshotSpan(textSnapshot, startPosition, endPosition - startPosition); if (ClassificationChanged != null) { ClassificationChanged(this, new ClassificationChangedEventArgs(snapshotSpan)); } if (TagsChanged != null) { TagsChanged(this, new SnapshotSpanEventArgs(snapshotSpan)); } }
private GherkinFileEditorInfo DoScan(string fileContent, ITextSnapshot textSnapshot, int lineOffset, I18n languageService, GherkinFileEditorParserListener gherkinListener, int errorRertyCount, out ScenarioEditorInfo firstUnchangedScenario) { const int MAX_ERROR_RETRY = 5; const int NO_ERROR_RETRY_FOR_LINES = 5; firstUnchangedScenario = null; try { Lexer lexer = languageService.lexer(gherkinListener); lexer.scan(fileContent, null, 0); } catch (PartialListeningDoneException partialListeningDoneException) { firstUnchangedScenario = partialListeningDoneException.FirstUnchangedScenario; } catch(LexingError lexingError) { int? errorLine = GetErrorLine(lexingError, lineOffset); if (errorLine != null && errorLine.Value < textSnapshot.LineCount - NO_ERROR_RETRY_FOR_LINES && errorRertyCount < MAX_ERROR_RETRY) { //add error classification & continue var restartLineNumber = errorLine.Value + 1; int restartPosition = textSnapshot.GetLineFromLineNumber(restartLineNumber).Start; string restartFileContent = textSnapshot.GetText(restartPosition, textSnapshot.Length - restartPosition); gherkinListener.LineOffset = restartLineNumber; return DoScan(restartFileContent, textSnapshot, restartLineNumber, languageService, gherkinListener, errorRertyCount + 1, out firstUnchangedScenario); } } // ReSharper disable EmptyGeneralCatchClause catch // ReSharper restore EmptyGeneralCatchClause { // unknown error } return gherkinListener.GetResult(); }
private void PartialParse(GherkinFileEditorInfo gherkinFileEditorInfo, ChangeInfo changeInfo, ScenarioEditorInfo firstAffectedScenario) { int parseStartPosition = changeInfo.TextSnapshot.GetLineFromLineNumber(firstAffectedScenario.StartLine).Start; string fileContent = changeInfo.TextSnapshot.GetText(parseStartPosition, changeInfo.TextSnapshot.Length - parseStartPosition); string fileHeader = changeInfo.TextSnapshot.GetText(0, parseStartPosition); I18n languageService = GetLanguageService(fileHeader); ScenarioEditorInfo firstUnchangedScenario; var partialResult = DoParsePartial(fileContent, languageService, firstAffectedScenario.StartLine, out firstUnchangedScenario, changeInfo.TextSnapshot, gherkinFileEditorInfo, changeInfo.ChangeLastLine, changeInfo.LineCountDelta); if (partialResult.HeaderClassificationSpans.Any()) { //TODO: merge to the prev scenario? partialResult.HeaderClassificationSpans.Clear(); } partialResult.HeaderClassificationSpans.AddRange( gherkinFileEditorInfo.HeaderClassificationSpans .Select(cs => cs.Shift(changeInfo.TextSnapshot, 0))); // inserting the non-affected scenarios partialResult.ScenarioEditorInfos.InsertRange(0, gherkinFileEditorInfo.ScenarioEditorInfos.TakeUntilItemExclusive(firstAffectedScenario) .Select(senario => senario.Shift(changeInfo.TextSnapshot, 0, 0))); if (firstUnchangedScenario != null) { // inserting the non-effected scenarios at the end partialResult.ScenarioEditorInfos.AddRange( gherkinFileEditorInfo.ScenarioEditorInfos.SkipFromItemInclusive(firstUnchangedScenario) .Select( scenario => scenario.Shift(changeInfo.TextSnapshot, changeInfo.LineCountDelta, changeInfo.PositionDelta))); } TriggerChanges(partialResult, changeInfo, firstAffectedScenario, firstUnchangedScenario); }
private GherkinFileEditorInfo DoParsePartial(string fileContent, I18n languageService, int lineOffset, out ScenarioEditorInfo firstUnchangedScenario, ITextSnapshot textSnapshot, GherkinFileEditorInfo previousGherkinFileEditorInfo, int changeLastLine, int changeLineDelta) { var gherkinListener = new GherkinFileEditorParserListener(textSnapshot, classifications, previousGherkinFileEditorInfo, lineOffset, changeLastLine, changeLineDelta); return DoScan(fileContent, textSnapshot, lineOffset, languageService, gherkinListener, 0, out firstUnchangedScenario); }
public PartialListeningDoneException(ScenarioEditorInfo firstUnchangedScenario) { FirstUnchangedScenario = firstUnchangedScenario; }
private GherkinFileEditorInfo DoParsePartial(string fileContent, I18n languageService, int lineOffset, out ScenarioEditorInfo firstUnchangedScenario, ITextSnapshot textSnapshot, GherkinFileEditorInfo previousGherkinFileEditorInfo, int changeLastLine, int changeLineDelta) { GherkinScanner scanner = new GherkinScanner(languageService, fileContent, lineOffset); var gherkinListener = new GherkinFileEditorParserListener(textSnapshot, classifications, previousGherkinFileEditorInfo, changeLastLine, changeLineDelta); firstUnchangedScenario = null; try { scanner.Scan(gherkinListener); } catch (PartialListeningDoneException partialListeningDoneException) { firstUnchangedScenario = partialListeningDoneException.FirstUnchangedScenario; } return gherkinListener.GetResult(); }
private void TriggerChanges(GherkinFileEditorInfo gherkinFileEditorInfo, ChangeInfo changeInfo, ScenarioEditorInfo firstAffectedScenario = null, ScenarioEditorInfo firstUnchangedScenario = null) { this.GherkinFileEditorInfo = gherkinFileEditorInfo; var textSnapshot = changeInfo.TextSnapshot; int startPosition = 0; if (firstAffectedScenario != null) startPosition = textSnapshot.GetLineFromLineNumber(firstAffectedScenario.StartLine).Start; int endPosition = textSnapshot.Length; if (firstUnchangedScenario != null) endPosition = textSnapshot.GetLineFromLineNumber(firstUnchangedScenario.StartLine).Start; // safety criteria to avoid argument execption in case of a wrong parser result if (startPosition >= endPosition) return; var snapshotSpan = new SnapshotSpan(textSnapshot, startPosition, endPosition - startPosition); if (ClassificationChanged != null) { ClassificationChanged(this, new ClassificationChangedEventArgs(snapshotSpan)); } if (TagsChanged != null) { TagsChanged(this, new SnapshotSpanEventArgs(snapshotSpan)); } }
private void PartialParse(GherkinFileEditorInfo gherkinFileEditorInfo, ChangeInfo changeInfo, ScenarioEditorInfo firstAffectedScenario) { visualStudioTracer.Trace("Start incremental parsing", ParserTraceCategory); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); partialParseCount++; int parseStartPosition = changeInfo.TextSnapshot.GetLineFromLineNumber(firstAffectedScenario.StartLine).Start; string fileContent = changeInfo.TextSnapshot.GetText(parseStartPosition, changeInfo.TextSnapshot.Length - parseStartPosition); string fileHeader = changeInfo.TextSnapshot.GetText(0, parseStartPosition); I18n languageService = GetLanguageService(fileHeader); ScenarioEditorInfo firstUnchangedScenario; var partialResult = DoParsePartial(fileContent, languageService, firstAffectedScenario.StartLine, out firstUnchangedScenario, changeInfo.TextSnapshot, gherkinFileEditorInfo, changeInfo.ChangeLastLine, changeInfo.LineCountDelta); if (partialResult.HeaderClassificationSpans.Any()) { //TODO: merge to the prev scenario? partialResult.HeaderClassificationSpans.Clear(); } partialResult.HeaderClassificationSpans.AddRange( gherkinFileEditorInfo.HeaderClassificationSpans .Select(cs => cs.Shift(changeInfo.TextSnapshot, 0))); // inserting the non-affected scenarios partialResult.ScenarioEditorInfos.InsertRange(0, gherkinFileEditorInfo.ScenarioEditorInfos.TakeUntilItemExclusive(firstAffectedScenario) .Select(senario => senario.Shift(changeInfo.TextSnapshot, 0, 0))); ScenarioEditorInfo firstUnchangedScenarioShifted = null; if (firstUnchangedScenario != null) { // inserting the non-effected scenarios at the end int firstNewScenarioIndex = partialResult.ScenarioEditorInfos.Count; partialResult.ScenarioEditorInfos.AddRange( gherkinFileEditorInfo.ScenarioEditorInfos.SkipFromItemInclusive(firstUnchangedScenario) .Select( scenario => scenario.Shift(changeInfo.TextSnapshot, changeInfo.LineCountDelta, changeInfo.PositionDelta))); firstUnchangedScenarioShifted = partialResult.ScenarioEditorInfos.Count > firstNewScenarioIndex ? partialResult.ScenarioEditorInfos[firstNewScenarioIndex] : null; } TriggerChanges(partialResult, changeInfo, firstAffectedScenario, firstUnchangedScenarioShifted); stopwatch.Stop(); TraceFinishParse(stopwatch, "incremental"); }