You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

ast_lookup.rb 5.5 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. # frozen_string_literal: true
  2. module Cucumber
  3. module Formatter
  4. class AstLookup
  5. def initialize(config)
  6. @gherkin_documents = {}
  7. @test_case_lookups = {}
  8. @test_step_lookups = {}
  9. @step_keyword_lookups = {}
  10. config.on_event :gherkin_source_parsed, &method(:on_gherkin_source_parsed)
  11. end
  12. def on_gherkin_source_parsed(event)
  13. @gherkin_documents[event.gherkin_document.uri] = event.gherkin_document
  14. end
  15. def gherkin_document(uri)
  16. @gherkin_documents[uri]
  17. end
  18. def scenario_source(test_case)
  19. uri = test_case.location.file
  20. @test_case_lookups[uri] ||= TestCaseLookupBuilder.new(gherkin_document(uri)).lookup_hash
  21. @test_case_lookups[uri][test_case.location.lines.max]
  22. end
  23. def step_source(test_step)
  24. uri = test_step.location.file
  25. @test_step_lookups[uri] ||= TestStepLookupBuilder.new(gherkin_document(uri)).lookup_hash
  26. @test_step_lookups[uri][test_step.location.lines.min]
  27. end
  28. def snippet_step_keyword(test_step)
  29. uri = test_step.location.file
  30. document = gherkin_document(uri)
  31. dialect = ::Gherkin::Dialect.for(document.feature.language)
  32. given_when_then_keywords = [dialect.given_keywords, dialect.when_keywords, dialect.then_keywords].flatten.uniq.reject { |kw| kw == '* ' }
  33. keyword_lookup = step_keyword_lookup(uri)
  34. keyword = nil
  35. node = keyword_lookup[test_step.location.lines.min]
  36. while keyword.nil?
  37. if given_when_then_keywords.include?(node.keyword)
  38. keyword = node.keyword
  39. break
  40. end
  41. break if node.previous_node.nil?
  42. node = node.previous_node
  43. end
  44. keyword = dialect.given_keywords.reject { |kw| kw == '* ' }[0] if keyword.nil?
  45. Cucumber::Gherkin::I18n.code_keyword_for(keyword)
  46. end
  47. ScenarioSource = Struct.new(:type, :scenario)
  48. ScenarioOutlineSource = Struct.new(:type, :scenario_outline, :examples, :row)
  49. StepSource = Struct.new(:type, :step)
  50. private
  51. def step_keyword_lookup(uri)
  52. @step_keyword_lookups[uri] ||= KeywordLookupBuilder.new(gherkin_document(uri)).lookup_hash
  53. end
  54. class TestCaseLookupBuilder
  55. attr_reader :lookup_hash
  56. def initialize(gherkin_document)
  57. @lookup_hash = {}
  58. process_scenario_container(gherkin_document.feature)
  59. end
  60. private
  61. def process_scenario_container(container)
  62. container.children.each do |child|
  63. if child.respond_to?(:rule) && child.rule
  64. process_scenario_container(child.rule)
  65. elsif child.respond_to?(:scenario) && child.scenario
  66. process_scenario(child)
  67. end
  68. end
  69. end
  70. def process_scenario(child)
  71. if child.scenario.examples.empty?
  72. @lookup_hash[child.scenario.location.line] = ScenarioSource.new(:Scenario, child.scenario)
  73. else
  74. child.scenario.examples.each do |examples|
  75. examples.table_body.each do |row|
  76. @lookup_hash[row.location.line] = ScenarioOutlineSource.new(:ScenarioOutline, child.scenario, examples, row)
  77. end
  78. end
  79. end
  80. end
  81. end
  82. class TestStepLookupBuilder
  83. attr_reader :lookup_hash
  84. def initialize(gherkin_document)
  85. @lookup_hash = {}
  86. process_scenario_container(gherkin_document.feature)
  87. end
  88. private
  89. def process_scenario_container(container)
  90. container.children.each do |child|
  91. if child.respond_to?(:rule) && child.rule
  92. process_scenario_container(child.rule)
  93. elsif child.respond_to?(:scenario) && child.scenario
  94. child.scenario.steps.each do |step|
  95. @lookup_hash[step.location.line] = StepSource.new(:Step, step)
  96. end
  97. elsif !child.background.nil?
  98. child.background.steps.each do |step|
  99. @lookup_hash[step.location.line] = StepSource.new(:Step, step)
  100. end
  101. end
  102. end
  103. end
  104. end
  105. KeywordSearchNode = Struct.new(:keyword, :previous_node)
  106. class KeywordLookupBuilder
  107. attr_reader :lookup_hash
  108. def initialize(gherkin_document)
  109. @lookup_hash = {}
  110. process_scenario_container(gherkin_document.feature, nil)
  111. end
  112. private
  113. def process_scenario_container(container, original_previous_node)
  114. container.children.each do |child|
  115. previous_node = original_previous_node
  116. if child.respond_to?(:rule) && child.rule
  117. process_scenario_container(child.rule, original_previous_node)
  118. elsif child.respond_to?(:scenario) && child.scenario
  119. child.scenario.steps.each do |step|
  120. node = KeywordSearchNode.new(step.keyword, previous_node)
  121. @lookup_hash[step.location.line] = node
  122. previous_node = node
  123. end
  124. elsif child.respond_to?(:background) && child.background
  125. child.background.steps.each do |step|
  126. node = KeywordSearchNode.new(step.keyword, previous_node)
  127. @lookup_hash[step.location.line] = node
  128. previous_node = node
  129. original_previous_node = previous_node
  130. end
  131. end
  132. end
  133. end
  134. end
  135. end
  136. end
  137. end

No Description

Contributors (1)