Best Gherkin-dotnet code snippet using Gherkin.Token.Token
GherkinStepTagger.cs
Source:GherkinStepTagger.cs
...12 public static readonly char[] Chars = new[] { '\t', ' ', '\r', '\n' };13 }14 public class GherkinStepTagger15 {16 private readonly Dictionary<GherkinTokenType, Func<SnapshotSpan, GherkinParseEvent, IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>>>> tagHandler;17 private bool cellToggle;18 public GherkinStepTagger()19 {20 tagHandler = new Dictionary<GherkinTokenType, Func<SnapshotSpan, GherkinParseEvent, IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>>>>21 {22 {GherkinTokenType.SyntaxError, SyntaxError},23 {GherkinTokenType.Feature, HandleFeature},24 {GherkinTokenType.Scenario, HandleScenario},25 {GherkinTokenType.Background, HandleBackground},26 {GherkinTokenType.Comment, HandleComment},27 {GherkinTokenType.Tag, HandleTag},28 {GherkinTokenType.DocString, HandleDocString},29 {GherkinTokenType.Examples, HandleSpan},30 {GherkinTokenType.Step, HandleStep},31 {GherkinTokenType.TableHeader, HandleTableHeader},32 {GherkinTokenType.TableCell, HandleTableCell},33 };34 }35 public IEnumerable<ITagSpan<GherkinTokenTag>> CreateTags(IEnumerable<GherkinParseEvent> events, SnapshotSpan span)36 {37 var value = span.GetText();38 if (string.IsNullOrWhiteSpace(value))39 return new ITagSpan<GherkinTokenTag>[0];40 var tags = new List<ITagSpan<GherkinTokenTag>>();41 var line = span.Start.GetContainingLine();42 int lineNumber = line.LineNumber;43 var evt = FindMatchingEvent(events, lineNumber);44 if (evt != null)45 {46 Func<SnapshotSpan, GherkinParseEvent, IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>>> tagger;47 if (tagHandler.TryGetValue(evt.GherkinTokenType, out tagger))48 {49 var items = tagger(span, evt).ToList();50 var intersectingTags = items.Where(_ => _.Item1.IntersectsWith(span)).Select(_ => _.Item2);51 tags.AddRange(intersectingTags);52 }53 }54 return tags;55 }56 private GherkinParseEvent FindMatchingEvent(IEnumerable<GherkinParseEvent> events, int lineNumber)57 {58 var evt = events.FirstOrDefault(_ => _.Tokens.Any(λ => λ.LineInFile.Line == lineNumber))59 ?? events.Where(_ => _.Tokens.Any(λ => λ.LineInFile.Line < lineNumber))60 .OrderByDescending(_ => _.Tokens.First().LineInFile.Line)61 .FirstOrDefault();62 if (evt != null && evt.GherkinTokenType == GherkinTokenType.SyntaxError && lineNumber > evt.Tokens.Max(_ => _.LineInFile.Line))63 return null;64 return evt;65 }66 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleSpan(SnapshotSpan span, GherkinParseEvent evt)67 {68 ITextSnapshotLine containingLine = span.Start.GetContainingLine();69 var tokenSpan = new SnapshotSpan(span.Snapshot, new Span(containingLine.Start.Position, containingLine.Length));70 var tagSpan = new TagSpan<GherkinTokenTag>(tokenSpan, new GherkinTokenTag(evt.GherkinTokenType));71 yield return new Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>(tokenSpan, tagSpan);72 }73 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleFeature(SnapshotSpan span, GherkinParseEvent evt)74 {75 if (!evt.Tokens.Any())76 yield break;77 var t1 = HandleType(span, evt.Tokens.First(), GherkinTokenType.Feature);78 if (t1 != null) yield return t1;79 if (evt.Tokens.Count >= 2)80 {81 var t2 = HandleTitle(span, evt.Tokens[1], GherkinTokenType.FeatureTitle);82 foreach (var tuple in t2)83 yield return tuple;84 }85 if (evt.Tokens.Count == 3)86 {87 var t3 = HandleTitle(span, evt.Tokens[2], GherkinTokenType.FeatureDescription);88 foreach (var tuple in t3)89 yield return tuple;90 }91 }92 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleScenario(SnapshotSpan span, GherkinParseEvent evt)93 {94 return HandleTag(span, evt, GherkinTokenType.Scenario, GherkinTokenType.ScenarioTitle);95 }96 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleBackground(SnapshotSpan span, GherkinParseEvent evt)97 {98 return HandleTag(span, evt, GherkinTokenType.Background, GherkinTokenType.BackgroundTitle);99 }100 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleStep(SnapshotSpan span, GherkinParseEvent evt)101 {102 return HandleTag(span, evt, GherkinTokenType.Step, GherkinTokenType.StepText);103 }104 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleTag(SnapshotSpan span, GherkinParseEvent evt)105 {106 var tags = new List<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>>();107 foreach (var token in evt.Tokens)108 tags.AddRange(HandleTitle(span, token, GherkinTokenType.Tag));109 return tags;110 }111 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleComment(SnapshotSpan span, GherkinParseEvent evt)112 {113 var text = span.GetText();114 var isLanguage = new Regex(@"\s*#\s*language\s*(:|\s)\s*(?<language>[a-zA-Z\-]+)");115 var match = isLanguage.Match(text);116 if (match.Success)117 {118 foreach (var commentTag in TagLanguageComment(span, evt, match, text))119 yield return commentTag;120 }121 else122 {123 var r = new Regex(string.Format(@"^\s*#\s*{0}\s*$", evt.Tokens[0].Content));124 if (r.IsMatch(text))125 {126 var t = new Token(text, evt.Tokens[0].LineInFile);127 var tag = CreateTag(t, span, evt);128 if (tag != null)129 yield return tag;130 }131 }132 }133 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> TagLanguageComment(SnapshotSpan span, GherkinParseEvent evt, Match match, string text)134 {135 var i = text.IndexOf("language");136 var t1 = new Token(text.Substring(0, i), evt.Tokens[0].LineInFile);137 var comment = CreateTag(t1, span, evt);138 if (comment != null)139 yield return comment;140 var t2 = new Token(match.Value.Substring(i), evt.Tokens[0].LineInFile);141 var lang = CreateTag(t2, span, new GherkinParseEvent(GherkinTokenType.Tag, evt.Tokens.ToArray()));142 if (lang != null)143 yield return lang;144 var t3 = new Token(text.Substring(i + t2.Content.Length).TrimEnd(WhiteSpaces.Chars), evt.Tokens[0].LineInFile);145 if (t3.Content != "")146 {147 var end = CreateTag(t3, span, evt);148 if (end != null)149 yield return end;150 }151 }152 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> SyntaxError(SnapshotSpan span, GherkinParseEvent evt)153 {154 var text = span.GetText();155 var token = new Token(text, new LineInFile(-1));156 var tag = CreateTag(token, span, GherkinTokenType.SyntaxError, text);157 if (tag != null)158 yield return tag;159 }160 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleTableHeader(SnapshotSpan span, GherkinParseEvent evt)161 {162 cellToggle = false;163 return TableItem(span, evt.GherkinTokenType);164 }165 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleTableCell(SnapshotSpan span, GherkinParseEvent evt)166 {167 var tokenType = cellToggle ? GherkinTokenType.TableCell : GherkinTokenType.TableCellAlt;168 cellToggle = !cellToggle;169 return TableItem(span, tokenType);170 }171 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> TableItem(SnapshotSpan span, GherkinTokenType tokenType)172 {173 return HandleText(span, tokenType, "|");174 }175 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleDocString(SnapshotSpan span, GherkinParseEvent evt)176 {177 var text = span.GetText().Trim(WhiteSpaces.Chars);178 if (text == "\"\"\"")179 return HandleText(span, GherkinTokenType.Tag, "\"");180 //TODO: dont color the spaces that will be removed181 ITextSnapshotLine containingLine = span.Start.GetContainingLine();182 var tokenSpan = new SnapshotSpan(span.Snapshot, new Span(containingLine.Start.Position, containingLine.Length));183 var tagSpan = new TagSpan<GherkinTokenTag>(tokenSpan, new GherkinTokenTag(evt.GherkinTokenType));184 return new[] { new Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>(tokenSpan, tagSpan) };185 }186 private static IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleText(187 SnapshotSpan span, GherkinTokenType tokenType,188 string surroundingText)189 {190 var str = span.GetText().TrimEnd(WhiteSpaces.Chars);191 var idx = str.IndexOf(surroundingText, StringComparison.InvariantCulture);192 var idx2 = str.LastIndexOf(surroundingText, StringComparison.InvariantCulture);193 if (idx == -1 || idx2 == -1)194 yield break;195 ITextSnapshotLine containingLine = span.Start.GetContainingLine();196 var tokenSpan = new SnapshotSpan(span.Snapshot, new Span(containingLine.Start.Position + idx, idx2 - idx + 1));197 var tagSpan = new TagSpan<GherkinTokenTag>(tokenSpan, new GherkinTokenTag(tokenType));198 yield return new Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>(tokenSpan, tagSpan);199 }200 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleTag(SnapshotSpan span, GherkinParseEvent evt, GherkinTokenType tokenType, GherkinTokenType tokenTitleType)201 {202 if (!evt.Tokens.Any())203 yield break;204 var t1 = HandleType(span, evt.Tokens.First(), tokenType);205 if (t1 != null) yield return t1;206 if (evt.Tokens.Count >= 2)207 {208 var t2 = HandleTitle(span, evt.Tokens[1], tokenTitleType);209 foreach (var tuple in t2)210 yield return tuple;211 }212 }213 private Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>> HandleType(SnapshotSpan span, Token token, GherkinTokenType tokenType)214 {215 var text = span.GetText();216 if (text.TrimStart(WhiteSpaces.Chars).StartsWith(token.Content))217 {218 var idx = text.IndexOf(token.Content, StringComparison.Ordinal);219 ITextSnapshotLine containingLine = span.Start.GetContainingLine();220 var tokenSpan = new SnapshotSpan(span.Snapshot, new Span(containingLine.Start.Position + idx, token.Content.Length));221 var tagSpan = new TagSpan<GherkinTokenTag>(tokenSpan, new GherkinTokenTag(tokenType));222 return new Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>(tokenSpan, tagSpan);223 }224 return null;225 }226 private IEnumerable<Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>> HandleTitle(SnapshotSpan span, Token token, GherkinTokenType tokenType)227 {228 var spanText = span.GetText();229 var tokenText = token.Content.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries).Select(_ => _.Trim(WhiteSpaces.Chars)).ToList();230 foreach (var row in tokenText)231 {232 var idx = spanText.IndexOf(row, StringComparison.CurrentCulture);233 if (idx == -1)234 continue;235 ITextSnapshotLine containingLine = span.Start.GetContainingLine();236 var tokenSpan = new SnapshotSpan(span.Snapshot, new Span(containingLine.Start.Position + idx, row.Length));237 var tagSpan = new TagSpan<GherkinTokenTag>(tokenSpan, new GherkinTokenTag(tokenType));238 yield return new Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>(tokenSpan, tagSpan);239 }240 }241 private Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>> CreateTag(Token token, SnapshotSpan span, GherkinParseEvent evt)242 {243 var text = span.GetText();244 return CreateTag(token, span, evt.GherkinTokenType, text);245 }246 private Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>> CreateTag(Token token, SnapshotSpan span, GherkinTokenType tokenType, string text)247 {248 foreach (var row in token.Content.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))249 {250 string rowText = row.Trim(WhiteSpaces.Chars);251 var idx = text.IndexOf(rowText, StringComparison.Ordinal);252 if (idx == -1)253 continue;254 ITextSnapshotLine containingLine = span.Start.GetContainingLine();255 var tokenSpan = new SnapshotSpan(span.Snapshot, new Span(containingLine.Start.Position + idx, rowText.Length));256 var tagSpan = new TagSpan<GherkinTokenTag>(tokenSpan, new GherkinTokenTag(tokenType));257 return new Tuple<SnapshotSpan, TagSpan<GherkinTokenTag>>(tokenSpan, tagSpan);258 }259 return null;260 }261 }262}...
GherkinParser.cs
Source:GherkinParser.cs
...9{10 public class GherkinParser : IParser11 {12 // ReSharper disable once InconsistentNaming13 private static readonly NodeTypeSet SCENARIO_END_TOKENS = new NodeTypeSet(GherkinTokenTypes.BACKGROUND_KEYWORD,14 GherkinTokenTypes.SCENARIO_KEYWORD,15 GherkinTokenTypes.SCENARIO_OUTLINE_KEYWORD,16 GherkinTokenTypes.RULE_KEYWORD,17 GherkinTokenTypes.FEATURE_KEYWORD);18 private readonly ILexer _lexer;19 private readonly IPsiSourceFile _sourceFile;20 public GherkinParser(ILexer lexer, IPsiSourceFile sourceFile)21 {22 _lexer = lexer;23 _sourceFile = sourceFile;24 }25 public IFile ParseFile()26 {27 using (var lifetimeDefinition = Lifetime.Define())28 {29 var builder = new PsiBuilder(_lexer, GherkinNodeTypes.FILE, null, lifetimeDefinition.Lifetime);30 var fileMarker = builder.Mark();31 while (!builder.Eof())32 {33 var tokenType = builder.GetTokenType();34 if (tokenType == GherkinTokenTypes.FEATURE_KEYWORD)35 ParseFeature(builder);36 else if (tokenType == GherkinTokenTypes.TAG)37 ParseTags(builder);38 else39 builder.AdvanceLexer();40 }41 builder.Done(fileMarker, GherkinNodeTypes.FILE, _sourceFile.Name);42 var resultTree = (GherkinFile) builder.BuildTree();43 return resultTree;44 }45 }46 private static void ParseTags(PsiBuilder builder)47 {48 while (builder.GetTokenType() == GherkinTokenTypes.TAG)49 {50 var tagMarker = builder.Mark();51 builder.AdvanceLexer();52 builder.Done(tagMarker, GherkinNodeTypes.TAG, null);53 if (builder.GetTokenType() == GherkinTokenTypes.WHITE_SPACE)54 builder.AdvanceLexer();55 }56 }57 private static void ParseFeature(PsiBuilder builder)58 {59 var featureMarker = builder.Mark();60 Assertion.Assert(builder.GetTokenType() == GherkinTokenTypes.FEATURE_KEYWORD,61 "_builder.GetTokenType() == GherkinTokenTypes.FEATURE_KEYWORD");62 int? descMarker = null;63 bool wasLineBreak = false;64 do65 {66 builder.AdvanceLexer();67 var tokenType = builder.GetTokenType();68 if (tokenType == GherkinTokenTypes.TEXT && descMarker == null)69 {70 if (wasLineBreak)71 descMarker = builder.Mark();72 }73 if (GherkinTokenTypes.SCENARIOS_KEYWORDS[tokenType] ||74 tokenType == GherkinTokenTypes.RULE_KEYWORD ||75 tokenType == GherkinTokenTypes.BACKGROUND_KEYWORD ||76 tokenType == GherkinTokenTypes.TAG)77 {78 if (descMarker != null)79 {80 builder.Done(descMarker.Value, GherkinNodeTypes.FEATURE_HEADER, null);81 descMarker = null;82 }83 ParseFeatureElements(builder);84 }85 wasLineBreak = IsLineBreak(builder);86 } while (builder.GetTokenType() != GherkinTokenTypes.FEATURE_KEYWORD && !builder.Eof());87 if (descMarker != null)88 builder.Done(descMarker.Value, GherkinNodeTypes.FEATURE_HEADER, null);89 builder.Done(featureMarker, GherkinNodeTypes.FEATURE, null);90 }91 private static void ParseFeatureElements(PsiBuilder builder)92 {93 int? ruleMarker = null;94 while (builder.GetTokenType() != GherkinTokenTypes.FEATURE_KEYWORD && !builder.Eof())95 {96 if (builder.GetTokenType() == GherkinTokenTypes.WHITE_SPACE)97 {98 builder.AdvanceLexer();99 continue;100 }101 ruleMarker = ParseRule(builder, ruleMarker);102 ParseScenario(builder);103 }104 if (ruleMarker.HasValue)105 builder.Done(ruleMarker.Value, GherkinNodeTypes.RULE, null);106 }107 private static int? ParseRule(PsiBuilder builder, int? ruleMarker)108 {109 if (builder.GetTokenType() == GherkinTokenTypes.RULE_KEYWORD)110 {111 if (ruleMarker != null)112 builder.Done(ruleMarker.Value, GherkinNodeTypes.RULE, null);113 ruleMarker = builder.Mark();114 builder.AdvanceLexer();115 if (builder.GetTokenType() == GherkinTokenTypes.COLON)116 builder.AdvanceLexer();117 else118 return ruleMarker;119 while (builder.GetTokenType() == GherkinTokenTypes.TEXT ||120 builder.GetTokenType() == GherkinTokenTypes.WHITE_SPACE)121 builder.AdvanceLexer();122 }123 return ruleMarker;124 }125 private static void ParseScenario(PsiBuilder builder)126 {127 var scenarioMarker = builder.Mark();128 ParseTags(builder);129 // scenarios130 var startTokenType = builder.GetTokenType();131 var outline = startTokenType == GherkinTokenTypes.SCENARIO_OUTLINE_KEYWORD;132 builder.AdvanceLexer();133 while (!AtScenarioEnd(builder))134 {135 ParseTags(builder);136 if (ParseStepParameter(builder))137 continue;138 if (builder.GetTokenType() == GherkinTokenTypes.STEP_KEYWORD)139 ParseStep(builder);140 else if (builder.GetTokenType() == GherkinTokenTypes.EXAMPLES_KEYWORD)141 ParseExamplesBlock(builder);142 else143 builder.AdvanceLexer();144 }145 builder.Done(scenarioMarker, outline ? GherkinNodeTypes.SCENARIO_OUTLINE : GherkinNodeTypes.SCENARIO, null);146 }147 private static void ParseStep(PsiBuilder builder)148 {149 var marker = builder.Mark();150 builder.AdvanceLexer();151 while (builder.GetTokenType() == GherkinTokenTypes.TEXT ||152 builder.GetTokenType() == GherkinTokenTypes.STEP_PARAMETER_BRACE ||153 builder.GetTokenType() == GherkinTokenTypes.STEP_PARAMETER_TEXT ||154 builder.GetTokenType() == GherkinTokenTypes.WHITE_SPACE)155 {156 if (IsLineBreak(builder))157 break;158 if (!ParseStepParameter(builder))159 builder.AdvanceLexer();160 }161 var nextToken = builder.GetTokenType(1);162 if (nextToken == GherkinTokenTypes.PIPE)163 {164 builder.AdvanceLexer();165 ParseTable(builder);166 }167 else if (nextToken == GherkinTokenTypes.PYSTRING)168 {169 builder.AdvanceLexer();170 ParsePystring(builder);171 }172 builder.Done(marker, GherkinNodeTypes.STEP, null);173 }174 private static void ParseExamplesBlock(PsiBuilder builder)175 {176 var marker = builder.Mark();177 builder.AdvanceLexer();178 if (builder.GetTokenType() == GherkinTokenTypes.COLON)179 builder.AdvanceLexer();180 while (builder.GetTokenType() == GherkinTokenTypes.TEXT ||181 builder.GetTokenType() == GherkinTokenTypes.WHITE_SPACE)182 builder.AdvanceLexer();183 if (builder.GetTokenType() == GherkinTokenTypes.PIPE)184 ParseTable(builder);185 builder.Done(marker, GherkinNodeTypes.EXAMPLES_BLOCK, null);186 }187 private static void ParseTable(PsiBuilder builder)188 {189 var marker = builder.Mark();190 var rowMarker = builder.Mark();191 var headerNodeType = GherkinNodeTypes.TABLE_HEADER_ROW;192 int? cellMarker = null;193 var wasLineBreak = false;194 var possibleEmptyCell = false;195 while (builder.GetTokenType() == GherkinTokenTypes.PIPE ||196 builder.GetTokenType() == GherkinTokenTypes.TABLE_CELL ||197 builder.GetTokenType() == GherkinTokenTypes.WHITE_SPACE)198 {199 var tokenType = builder.GetTokenType();200 if (tokenType == GherkinTokenTypes.TABLE_CELL && cellMarker == null)201 {202 cellMarker = builder.Mark();203 }204 else if (tokenType != GherkinTokenTypes.TABLE_CELL && cellMarker != null)205 {206 builder.Done(cellMarker.Value, GherkinNodeTypes.TABLE_CELL, null);207 cellMarker = null;208 possibleEmptyCell = false;209 }210 if (tokenType == GherkinTokenTypes.PIPE)211 {212 if (wasLineBreak)213 {214 possibleEmptyCell = true;215 builder.Done(rowMarker, headerNodeType, null);216 headerNodeType = GherkinNodeTypes.TABLE_ROW;217 rowMarker = builder.Mark();218 }219 else220 {221 if (possibleEmptyCell)222 {223 cellMarker = builder.Mark();224 builder.Done(cellMarker.Value, GherkinNodeTypes.TABLE_CELL, null);225 cellMarker = null;226 }227 possibleEmptyCell = true;228 }229 }230 wasLineBreak = IsLineBreak(builder);231 builder.AdvanceLexer();232 }233 if (cellMarker.HasValue)234 builder.Done(cellMarker.Value, GherkinNodeTypes.TABLE_CELL, null);235 builder.Done(rowMarker, headerNodeType, null);236 builder.Done(marker, GherkinNodeTypes.TABLE, null);237 }238 private static void ParsePystring(PsiBuilder builder)239 {240 if (!builder.Eof())241 {242 var marker = builder.Mark();243 builder.AdvanceLexer();244 while (!builder.Eof() && builder.GetTokenType() != GherkinTokenTypes.PYSTRING)245 {246 if (!ParseStepParameter(builder))247 builder.AdvanceLexer();248 }249 if (!builder.Eof())250 builder.AdvanceLexer();251 builder.Done(marker, GherkinNodeTypes.PYSTRING, null);252 }253 }254 private static bool ParseStepParameter(PsiBuilder builder)255 {256 if (builder.GetTokenType() != GherkinTokenTypes.STEP_PARAMETER_TEXT)257 return false;258 var stepParameterMarker = builder.Mark();259 builder.AdvanceLexer();260 builder.Done(stepParameterMarker, GherkinNodeTypes.STEP_PARAMETER, null);261 return true;262 }263 private static bool AtScenarioEnd(PsiBuilder builder)264 {265 var i = 0;266 while (builder.GetTokenType(i) == GherkinTokenTypes.TAG ||267 builder.GetTokenType(i) == GherkinTokenTypes.WHITE_SPACE)268 i++;269 var tokenType = builder.GetTokenType(i);270 return tokenType == null || SCENARIO_END_TOKENS[tokenType];271 }272 private static bool IsLineBreak(PsiBuilder builder)273 {274 if (builder.GetTokenType() != GherkinTokenTypes.WHITE_SPACE)275 return false;276 return builder.GetTokenText()?.Contains("\n") == true;277 }278 }279}...
GherkinFileClassifier.cs
Source:GherkinFileClassifier.cs
...8using Microsoft.VisualStudio.Text.Tagging;9using SpecFlow.VisualStudio.Editor.Parser;10namespace SpecFlow.VisualStudio.Editor.Classification11{12 internal class GherkinFileClassifier : GherkinTokenTagConsumer, IClassifier13 {14 private readonly GherkinFileEditorClassifications gherkinFileEditorClassifications;15 public GherkinFileClassifier(ITextBuffer buffer, ITagAggregator<GherkinTokenTag> gherkinTagAggregator, IClassificationTypeRegistryService classificationTypeRegistryService)16 : base(buffer, gherkinTagAggregator)17 {18 gherkinFileEditorClassifications = new GherkinFileEditorClassifications(classificationTypeRegistryService);19 }20 public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan span)21 {22 List<ClassificationSpan> classifications = new List<ClassificationSpan>();23 foreach (var gherkinTagSpan in GetGherkinTags(span, t => t.IsToken))24 {25 AddClassifications(classifications, gherkinTagSpan.Value, gherkinTagSpan.Key);26 }27 return classifications;28 }29 private void AddClassifications(List<ClassificationSpan> classifications, GherkinTokenTag tag, SnapshotSpan tagSpan)30 {31 switch (tag.Token.MatchedType)32 {33 case TokenType.FeatureLine:34 case TokenType.ScenarioLine:35 case TokenType.ScenarioOutlineLine:36 case TokenType.BackgroundLine:37 case TokenType.ExamplesLine:38 classifications.Add(new ClassificationSpan(new SnapshotSpan(tagSpan.Start, tag.Token.MatchedKeyword.Length), gherkinFileEditorClassifications.Keyword));39 //classifications.Add(new ClassificationSpan(new SnapshotSpan(tagSpan.Start.Add(tag.Token.MatchedKeyword.Length + 1), tagSpan.End), gherkinFileEditorClassifications.UnboundStepText));40 break;41 case TokenType.StepLine:42 var classification = GetClassification(tag.StepType);43 classifications.Add(new ClassificationSpan(new SnapshotSpan(tagSpan.Start, tag.Token.MatchedKeyword.Length), classification));44 //classifications.Add(new ClassificationSpan(new SnapshotSpan(tagSpan.Start.Add(tag.Token.MatchedKeyword.Length), tagSpan.End), gherkinFileEditorClassifications.StepText));45 break;46 case TokenType.Comment:47 case TokenType.Language:48 classifications.Add(new ClassificationSpan(new SnapshotSpan(tagSpan.Start, tagSpan.End), gherkinFileEditorClassifications.Comment));49 break;50 case TokenType.TagLine:51 AddItemClassifications(classifications, tag, tagSpan, gherkinFileEditorClassifications.Tag);52 break;53 case TokenType.TableRow:54 AddItemClassifications(classifications, tag, tagSpan, gherkinFileEditorClassifications.TableCell);55 break;56 case TokenType.DocStringSeparator:57 classifications.Add(new ClassificationSpan(new SnapshotSpan(tagSpan.Start, tagSpan.End), gherkinFileEditorClassifications.MultilineText));58 break;59 case TokenType.Other:60 var classificationType = 61 tag.RuleTypesStarted.Contains(RuleType.DocString) ? 62 gherkinFileEditorClassifications.MultilineText :63 gherkinFileEditorClassifications.Description;64 classifications.Add(new ClassificationSpan(new SnapshotSpan(tagSpan.Start, tagSpan.End), classificationType));65 break;66 case TokenType.Empty:67 break;68 }69 }70 private IClassificationType GetClassification(StepType stepType)71 {72 switch (stepType)73 {74 case StepType.Given:75 return gherkinFileEditorClassifications.KeywordGiven;76 case StepType.When:77 return gherkinFileEditorClassifications.KeywordWhen;78 case StepType.Then:79 return gherkinFileEditorClassifications.KeywordThen;80 case StepType.NotAStep:81 return gherkinFileEditorClassifications.Keyword;82 default:83 throw new InvalidEnumArgumentException("stepType", (int)stepType, typeof (StepType));84 }85 }86 private static void AddItemClassifications(List<ClassificationSpan> classifications, GherkinTokenTag tag, SnapshotSpan tagSpan,87 IClassificationType classificationType)88 {89 foreach (var gherkinLineSpan in tag.Token.MatchedItems)90 {91 classifications.Add(92 new ClassificationSpan(93 new SnapshotSpan(tagSpan.Start.Add(gherkinLineSpan.Column - tag.Token.Location.Column), gherkinLineSpan.Text.Length), classificationType));94 }95 }96 // This event gets raised if a non-text change would affect the classification in some way,97 // for example typing /* would cause the classification to change in C# without directly98 // affecting the span.99 public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;100 protected override void RaiseChanged(SnapshotSpan span)101 {102 var classificationChanged = ClassificationChanged;103 if (classificationChanged != null)104 classificationChanged(this, new ClassificationChangedEventArgs(span));105 }106 }107}...
GherkinKeywordList.cs
Source:GherkinKeywordList.cs
...10 public class GherkinKeywordList11 {12 // i18n.json file contains list of keywords and some meta-information about the language. At the moment it's three attributes below. 13 private static readonly string[] GherkinLanguageMetaAttributes = {"name", "native", "encoding"};14 private static readonly Dictionary<string, GherkinTokenType> TokenTypes =15 new Dictionary<string, GherkinTokenType>16 {17 {"Feature", GherkinTokenTypes.FEATURE_KEYWORD},18 {"Background", GherkinTokenTypes.BACKGROUND_KEYWORD},19 {"Scenario", GherkinTokenTypes.SCENARIO_KEYWORD},20 {"Rule", GherkinTokenTypes.RULE_KEYWORD},21 {"Example", GherkinTokenTypes.EXAMPLE_KEYWORD},22 {"Scenario Outline", GherkinTokenTypes.SCENARIO_OUTLINE_KEYWORD},23 {"Examples", GherkinTokenTypes.EXAMPLES_KEYWORD},24 {"Scenarios", GherkinTokenTypes.EXAMPLES_KEYWORD},25 {"Given", GherkinTokenTypes.STEP_KEYWORD},26 {"When", GherkinTokenTypes.STEP_KEYWORD},27 {"Then", GherkinTokenTypes.STEP_KEYWORD},28 {"And", GherkinTokenTypes.STEP_KEYWORD},29 {"But", GherkinTokenTypes.STEP_KEYWORD},30 {"*", GherkinTokenTypes.STEP_KEYWORD}31 };32 private readonly HashSet<string> _spaceAfterKeywords = new HashSet<string>();33 private readonly Dictionary<string, string> _translatedKeywords = new Dictionary<string, string>();34 private readonly Dictionary<string, GherkinTokenType> _translatedTokenTypes = new Dictionary<string, GherkinTokenType>();35 // Need to use Descending comparer, because long keywords should be first.36 // For example: "Scenario" keyword is a part of "Scenario Outline" keyword.37 private readonly SortedSet<string> _allKeywords = new SortedSet<string>(new DescendingComparer<string>());38 public GherkinKeywordList(JObject keywords)39 {40 foreach (var (key, values) in keywords)41 {42 if (GherkinLanguageMetaAttributes.Contains(key))43 continue;44 var keyword = CapitalizeAndFixSpace(key);45 var tokenType = TokenTypes[keyword];46 foreach (var jToken in values)47 {48 var translatedKeyword = jToken.Value<string>();49 if (translatedKeyword.EndsWith(" "))50 {51 translatedKeyword = translatedKeyword.Substring(0, translatedKeyword.Length - 1);52 _spaceAfterKeywords.Add(translatedKeyword);53 }54 55 _translatedKeywords[translatedKeyword] = keyword;56 _translatedTokenTypes[translatedKeyword] = tokenType;57 _allKeywords.Add(translatedKeyword);58 }59 }60 }61 private static string CapitalizeAndFixSpace(string keyword)62 {63 var result = new StringBuilder();64 for (var i = 0; i < keyword.Length; i++)65 {66 var c = keyword[i];67 if (i == 0)68 c = char.ToUpper(c);69 if (char.IsUpper(c) && i > 0)70 result.Append(' ');71 result.Append(c);72 }73 return result.ToString();74 }75 public IReadOnlyCollection<string> GetAllKeywords()76 {77 return _allKeywords;78 }79 80 public bool IsSpaceRequiredAfterKeyword(string keyword)81 {82 return _spaceAfterKeywords.Contains(keyword);83 }84 public TokenNodeType GetTokenType(string keyword)85 {86 return _translatedTokenTypes[keyword];87 }88 private class DescendingComparer<T> : IComparer<T> where T : IComparable<T>89 {90 public int Compare(T x, T y)91 {92 return y.CompareTo(x);93 }94 }95 }96}...
GherkinTokenTagger.cs
Source:GherkinTokenTagger.cs
...8using Microsoft.VisualStudio.Text;9using Microsoft.VisualStudio.Text.Tagging;10namespace SpecFlow.VisualStudio.Editor.Parser11{12 internal sealed class GherkinTokenTagger : ITagger<GherkinTokenTag>13 {14 private class ParsingResult15 {16 public int SnapshotVersion { get; private set; }17 public GherkinTokenTag[] Tags { get; private set; }18 public ParsingResult(int snapshotVersion, GherkinTokenTag[] tags)19 {20 SnapshotVersion = snapshotVersion;21 Tags = tags;22 }23 }24 private readonly ITextBuffer buffer;25 private ParsingResult lastResult = null;26 internal GherkinTokenTagger(ITextBuffer buffer)27 {28 this.buffer = buffer;29 }30 public event EventHandler<SnapshotSpanEventArgs> TagsChanged;31 public IEnumerable<ITagSpan<GherkinTokenTag>> GetTags(NormalizedSnapshotSpanCollection spans)32 {33 var snapshot = spans[0].Snapshot;34 var tokenTags = Parse(snapshot);35 if (tokenTags == null)36 yield break;37 foreach (SnapshotSpan queriedSpan in spans)38 {39 foreach (var tokenTag in tokenTags)40 {41 var tokenSpan = tokenTag.Span;42 if (tokenSpan.IntersectsWith(queriedSpan))43 yield return new TagSpan<GherkinTokenTag>(tokenSpan, tokenTag);44 if (tokenSpan.Start > queriedSpan.End)45 break;46 }47 }48 }49 private GherkinTokenTag[] Parse(ITextSnapshot snapshot)50 {51 var currentLastResult = lastResult;52 if (currentLastResult != null && currentLastResult.SnapshotVersion == snapshot.Version.VersionNumber)53 return currentLastResult.Tags;54 55 var fileContent = snapshot.GetText();56 var stopwatch = new Stopwatch();57 stopwatch.Start();58 var parserErrors = new List<ParserException>();59 var tokenTagBuilder = new GherkinTokenTagBuilder(snapshot);60 var parser = new GherkinEditorParser(tokenTagBuilder);61 var reader = new StringReader(fileContent);62 try63 {64 parser.Parse(new TokenScanner(reader), new TokenMatcher(VsGherkinDialectProvider.Instance));65 }66 catch (CompositeParserException compositeParserException)67 {68 parserErrors.AddRange(compositeParserException.Errors);69 }70 catch (ParserException parserException)71 {72 parserErrors.Add(parserException);73 }74 catch (Exception ex)75 {76 //nop;77 Debug.WriteLine(ex);78 }79 var tokenTags = new List<GherkinTokenTag>();80 tokenTags.AddRange((GherkinTokenTag[])tokenTagBuilder.GetResult());81 tokenTags.AddRange(parserErrors.Select(e => new GherkinTokenTag(e, snapshot)));82 tokenTags.Sort((t1, t2) => t1.Span.Start.Position.CompareTo(t2.Span.Start.Position));83 stopwatch.Stop();84 Debug.WriteLine("Gherkin3: parsed v{0} on thread {1} in {2} ms", snapshot.Version.VersionNumber, Thread.CurrentThread.ManagedThreadId, stopwatch.ElapsedMilliseconds);85 var result = new ParsingResult(snapshot.Version.VersionNumber, tokenTags.ToArray());86 Thread.MemoryBarrier();87 lastResult = result;88 //TODO: only for the changed scope89 if (TagsChanged != null)90 TagsChanged(this, new SnapshotSpanEventArgs(new SnapshotSpan(snapshot, 0, snapshot.Length)));91 return result.Tags;92 }93 }94}...
GherkinEventListener.cs
Source:GherkinEventListener.cs
...9 public List<GherkinParseEvent> Events10 {11 get { return events; }12 }13 public void Feature(Token keyword, Token title, Token narrative)14 {15 events.Add(new GherkinParseEvent(GherkinTokenType.Feature, keyword, title, narrative));16 }17 public void Scenario(Token keyword, Token title)18 {19 events.Add(new GherkinParseEvent(GherkinTokenType.Scenario, keyword, title));20 }21 public void Examples(Token keyword, Token name)22 {23 events.Add(new GherkinParseEvent(GherkinTokenType.Examples, keyword, name));24 }25 public void Step(Token keyword, Token name)26 {27 events.Add(new GherkinParseEvent(GherkinTokenType.Step, keyword, name));28 }29 public void Table(IList<IList<Token>> rows, LineInFile lineInFile)30 {31 if (rows.Any())32 {33 var header = rows.First();34 events.Add(new GherkinParseEvent(GherkinTokenType.TableHeader, new Token(string.Join(" | ", header).Trim(), lineInFile)));35 var cells = rows.Skip(1);36 var cellLine = lineInFile;37 foreach (var cell in cells)38 {39 cellLine = new LineInFile(cellLine.Line + 1);40 events.Add(new GherkinParseEvent(GherkinTokenType.TableCell, new Token(string.Join(" | ", cell).Trim(), cellLine)));41 }42 }43 }44 public void Background(Token keyword, Token name)45 {46 events.Add(new GherkinParseEvent(GherkinTokenType.Background, keyword, name));47 }48 public void Comment(Token comment)49 {50 events.Add(new GherkinParseEvent(GherkinTokenType.Comment, comment));51 }52 public void Tag(Token tag)53 {54 if (tag.Content != "@") //bug in gherkin parser?55 {56 var previous = events.LastOrDefault() ?? new GherkinParseEvent(GherkinTokenType.SyntaxError);57 if (previous.GherkinTokenType == GherkinTokenType.Tag && tag.LineInFile.Line == previous.Tokens[0].LineInFile.Line)58 previous.Tokens.Add(tag);59 else60 events.Add(new GherkinParseEvent(GherkinTokenType.Tag, tag));61 }62 }63 public void SyntaxError(string state, string @event, IEnumerable<string> legalEvents, LineInFile lineInFile)64 {65 events.Add(new GherkinParseEvent(GherkinTokenType.SyntaxError, new Token(@event, lineInFile)));66 }67 public void Eof()68 {69 events.Add(new GherkinParseEvent(GherkinTokenType.Eof));70 }71 public void DocString(Token docString)72 {73 events.Add(new GherkinParseEvent(GherkinTokenType.DocString, docString));74 }75 }76}...
GherkinTokenTypes.cs
Source:GherkinTokenTypes.cs
1using JetBrains.ReSharper.Psi.ExtensionsAPI.Tree;2// ReSharper disable InconsistentNaming3namespace ReSharperPlugin.SpecflowRiderPlugin.Psi4{5 public static class GherkinTokenTypes6 {7 public static readonly GherkinTokenType WHITE_SPACE = new GherkinTokenType("WHITE_SPACE", 1001);8 public static readonly GherkinTokenType COMMENT = new GherkinTokenType("COMMENT", 1002);9 public static readonly GherkinTokenType TEXT = new GherkinTokenType("TEXT", 1003);10 public static readonly GherkinTokenType EXAMPLES_KEYWORD = new GherkinTokenType("EXAMPLES_KEYWORD", 1004);11 public static readonly GherkinTokenType FEATURE_KEYWORD = new GherkinTokenType("FEATURE_KEYWORD", 1005);12 public static readonly GherkinTokenType RULE_KEYWORD = new GherkinTokenType("RULE_KEYWORD", 1006);13 public static readonly GherkinTokenType BACKGROUND_KEYWORD = new GherkinTokenType("BACKGROUND_KEYWORD", 1007);14 public static readonly GherkinTokenType SCENARIO_KEYWORD = new GherkinTokenType("SCENARIO_KEYWORD", 1008);15 public static readonly GherkinTokenType EXAMPLE_KEYWORD = new GherkinTokenType("EXAMPLE_KEYWORD", 1009);16 public static readonly GherkinTokenType SCENARIO_OUTLINE_KEYWORD = new GherkinTokenType("SCENARIO_OUTLINE_KEYWORD", 1010);17 public static readonly GherkinTokenType STEP_KEYWORD = new GherkinTokenType("STEP_KEYWORD", 1011);18 public static readonly GherkinTokenType STEP_PARAMETER_BRACE = new GherkinTokenType("STEP_PARAMETER_BRACE", 1012);19 public static readonly GherkinTokenType STEP_PARAMETER_TEXT = new GherkinTokenType("STEP_PARAMETER_TEXT", 1013);20 public static readonly GherkinTokenType COLON = new GherkinTokenType("COLON", 1014);21 public static readonly GherkinTokenType TAG = new GherkinTokenType("TAG", 1015);22 public static readonly GherkinTokenType PYSTRING = new GherkinTokenType("PYSTRING_QUOTES", 1016);23 public static readonly GherkinTokenType PYSTRING_TEXT = new GherkinTokenType("PYSTRING_TEXT", 1017);24 public static readonly GherkinTokenType PIPE = new GherkinTokenType("PIPE", 1018);25 public static readonly GherkinTokenType TABLE_CELL = new GherkinTokenType("TABLE_CELL", 1019);26 public static readonly NodeTypeSet KEYWORDS = new NodeTypeSet(FEATURE_KEYWORD, RULE_KEYWORD, EXAMPLE_KEYWORD,27 BACKGROUND_KEYWORD, SCENARIO_KEYWORD, SCENARIO_OUTLINE_KEYWORD,28 EXAMPLES_KEYWORD, EXAMPLES_KEYWORD,29 STEP_KEYWORD);30 public static readonly NodeTypeSet SCENARIOS_KEYWORDS = new NodeTypeSet(SCENARIO_KEYWORD, SCENARIO_OUTLINE_KEYWORD, EXAMPLE_KEYWORD);31 }32}...
GherkinSyntaxHighlightingProcessor.cs
Source:GherkinSyntaxHighlightingProcessor.cs
...19 return false;20 }21 return base.InteriorShouldBeProcessed(element, context);22 }23 public override string GetAttributeId(TokenNodeType tokenType)24 {25 if (tokenType == GherkinTokenTypes.TAG)26 return GherkinHighlightingAttributeIds.TAG;27 28 if (tokenType == GherkinTokenTypes.STEP_PARAMETER_TEXT)29 return GherkinHighlightingAttributeIds.OUTLINE_PARAMETER_SUBSTITUTION;30 if (tokenType == GherkinTokenTypes.TEXT)31 return GherkinHighlightingAttributeIds.TEXT;32 if (tokenType == GherkinTokenTypes.TABLE_CELL)33 return GherkinHighlightingAttributeIds.TABLE_CELL;34 if (tokenType == GherkinTokenTypes.STEP_PARAMETER_TEXT) //TODO Detect regex parameter like: "param"35 return GherkinHighlightingAttributeIds.REGEXP_PARAMETER;36 if (tokenType == GherkinTokenTypes.PIPE)37 return GherkinHighlightingAttributeIds.PIPE;38 return base.GetAttributeId(tokenType);39 }40 protected override bool IsLineComment(TokenNodeType tokenType)41 {42 return tokenType == GherkinTokenTypes.COMMENT;43 }44 protected override bool IsKeyword(TokenNodeType tokenType)45 {46 return GherkinTokenTypes.KEYWORDS[tokenType];47 }48 protected override bool IsString(TokenNodeType tokenType)49 {50 return tokenType == GherkinTokenTypes.PYSTRING;51 }52 protected override string KeywordAttributeId => GherkinHighlightingAttributeIds.KEYWORD;53 protected override string LineCommentAttributeId => GherkinHighlightingAttributeIds.LINE_COMMENT;54 55 protected override string StringAttributeId => GherkinHighlightingAttributeIds.PYSTRING;56 }57}...
Token
Using AI Code Generation
1using System;2using System.IO;3using Gherkin;4using Gherkin.Ast;5{6 {7 static void Main(string[] args)8 {9 var parser = new Parser();10 var feature = parser.Parse("Feature: Test Feature");11 Console.WriteLine(feature.Name);12 }13 }14}
Token
Using AI Code Generation
1using System;2using Gherkin;3{4 {5 public Token(int line, int column, int type, string text)6 {7 this.line = line;8 this.column = column;9 this.type = type;10 this.text = text;11 }12 public int getLine()13 {14 return line;15 }16 public int getColumn()17 {18 return column;19 }20 public int getType()21 {22 return type;23 }24 public string getText()25 {26 return text;27 }28 private int line;29 private int column;30 private int type;31 private string text;32 }33}34using System;35using Gherkin;36{37 {38 public Token(int line, int column, int type, string text)39 {40 this.line = line;41 this.column = column;42 this.type = type;43 this.text = text;44 }45 public int getLine()46 {47 return line;48 }49 public int getColumn()50 {51 return column;52 }53 public int getType()54 {55 return type;56 }57 public string getText()58 {59 return text;60 }61 private int line;62 private int column;63 private int type;64 private string text;65 }66}67using System;68using Gherkin;69{70 {71 public Token(int line, int column, int type, string text)72 {73 this.line = line;74 this.column = column;75 this.type = type;76 this.text = text;77 }78 public int getLine()79 {80 return line;81 }82 public int getColumn()83 {84 return column;85 }86 public int getType()87 {88 return type;89 }90 public string getText()91 {92 return text;93 }94 private int line;95 private int column;96 private int type;97 private string text;98 }99}100using System;101using Gherkin;102{103 {104 public Token(int line, int column, int type, string text)105 {106 this.line = line;107 this.column = column;108 this.type = type;
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!