tryouts 3.7.1 → 4.0.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -2
  3. data/lib/tryouts/cli/formatters/agent.rb +2 -0
  4. data/lib/tryouts/cli/formatters/base.rb +2 -0
  5. data/lib/tryouts/cli/formatters/compact.rb +2 -0
  6. data/lib/tryouts/cli/formatters/factory.rb +2 -0
  7. data/lib/tryouts/cli/formatters/live_status_manager.rb +2 -0
  8. data/lib/tryouts/cli/formatters/output_manager.rb +2 -0
  9. data/lib/tryouts/cli/formatters/quiet.rb +2 -0
  10. data/lib/tryouts/cli/formatters/test_run_state.rb +2 -0
  11. data/lib/tryouts/cli/formatters/token_budget.rb +2 -0
  12. data/lib/tryouts/cli/formatters/tty_status_display.rb +2 -0
  13. data/lib/tryouts/cli/formatters/verbose.rb +2 -0
  14. data/lib/tryouts/cli/formatters.rb +2 -0
  15. data/lib/tryouts/cli/line_spec_parser.rb +2 -0
  16. data/lib/tryouts/cli/modes/generate.rb +2 -0
  17. data/lib/tryouts/cli/modes/inspect.rb +15 -3
  18. data/lib/tryouts/cli/opts.rb +2 -1
  19. data/lib/tryouts/cli/tty_detector.rb +2 -0
  20. data/lib/tryouts/cli.rb +2 -0
  21. data/lib/tryouts/console.rb +2 -0
  22. data/lib/tryouts/expectation_evaluators/base.rb +2 -0
  23. data/lib/tryouts/expectation_evaluators/boolean.rb +2 -0
  24. data/lib/tryouts/expectation_evaluators/exception.rb +2 -0
  25. data/lib/tryouts/expectation_evaluators/expectation_result.rb +2 -0
  26. data/lib/tryouts/expectation_evaluators/false.rb +2 -0
  27. data/lib/tryouts/expectation_evaluators/intentional_failure.rb +2 -0
  28. data/lib/tryouts/expectation_evaluators/non_nil.rb +2 -0
  29. data/lib/tryouts/expectation_evaluators/output.rb +2 -0
  30. data/lib/tryouts/expectation_evaluators/performance_time.rb +2 -0
  31. data/lib/tryouts/expectation_evaluators/regex_match.rb +2 -0
  32. data/lib/tryouts/expectation_evaluators/registry.rb +2 -0
  33. data/lib/tryouts/expectation_evaluators/regular.rb +2 -0
  34. data/lib/tryouts/expectation_evaluators/result_type.rb +2 -0
  35. data/lib/tryouts/expectation_evaluators/true.rb +2 -0
  36. data/lib/tryouts/failure_collector.rb +2 -0
  37. data/lib/tryouts/file_processor.rb +3 -4
  38. data/lib/tryouts/parser_warning.rb +2 -0
  39. data/lib/tryouts/parsers/base_parser.rb +3 -3
  40. data/lib/tryouts/parsers/enhanced_parser.rb +57 -3
  41. data/lib/tryouts/parsers/shared_methods.rb +67 -17
  42. data/lib/tryouts/test_batch.rb +155 -43
  43. data/lib/tryouts/test_case.rb +54 -6
  44. data/lib/tryouts/test_executor.rb +2 -0
  45. data/lib/tryouts/test_result_aggregator.rb +2 -0
  46. data/lib/tryouts/test_runner.rb +2 -1
  47. data/lib/tryouts/translators/minitest_translator.rb +36 -12
  48. data/lib/tryouts/translators/rspec_translator.rb +19 -0
  49. data/lib/tryouts/version.rb +3 -1
  50. data/lib/tryouts.rb +2 -1
  51. metadata +1 -2
  52. data/lib/tryouts/parsers/legacy_parser.rb +0 -254
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3934c079df9042f8ef837ea6eb7dc14a04706a1fcba4853d26a5f1ce69672bf
4
- data.tar.gz: adf6be71e206ad4747f83268370772ffdaeddfc6a9b49576bbd74cb6cf9b650c
3
+ metadata.gz: b43c7d018d4bb7bd546bb516a584903d7922d87a616dbec87d2e4b6d00e06652
4
+ data.tar.gz: d4068b53bbd8428f88bf1a4d4af62aa7db0ff4ecccfecca0c0b268f1d8fb0381
5
5
  SHA512:
6
- metadata.gz: d88b6998f1bd4d35329f501f4cbf710d1f653ca3faece95bc88c89ef626e6fe1413bd0129890817ff5d4cc15341e8c7bebd1209056cfc4fbd8bb730dc3ef4574
7
- data.tar.gz: 3d919417a2bc28cebb759a77a340bd2dd996ed290de6a7b96c2fe40f4936d5df6d952242b6991fb12d34646e325699f0837f817fc5aa2b6e03257e6d903a541c
6
+ metadata.gz: c11a368db40e8335a3d9eae238581ad6e0b4ea8b56862bb82f10adbb9746626762db1a89247be6e8eb2473aff90506f151a5b18452ab625d2a6e2f2753968f2d
7
+ data.tar.gz: 7ebec1c8923c423cd3ec2117d78e3a4a95fec48139bb1af2ecee48ebdfea7d02d1ceccfa8608fb5914cb21c762dfafc04a1f81835fc18723c3fbe79d495540db
data/README.md CHANGED
@@ -42,7 +42,7 @@ try try/core/basic_syntax_try.rb
42
42
 
43
43
  ## Writing Tests
44
44
 
45
- Tryouts use a comment-based syntax for expecations:
45
+ Tryouts use a comment-based syntax for expectations:
46
46
 
47
47
  ```ruby
48
48
  # Setup code runs before all tests
@@ -98,9 +98,10 @@ Each test file is made up of three sections:
98
98
  | `#=:>` | Must match result type | `#=:> String` | result, _ |
99
99
  | `#=~>` | Must match regex pattern | `#=~> /^[^@]+@[^@]+\.[^@]+$/` | result, _ |
100
100
  | `#=%>` | Must complete within time | `#=%> 2000 # in milliseconds` | result, _ |
101
+ | `#=*>` | Must be non-nil | `#=*> result` | result, _ |
101
102
  | `#=1>` | Match content in STDOUT | `#=1> "You have great success"` | result, _ |
102
103
  | `#=2>` | Match content in STDERR | `#=2> /[a-zA-Z0-9]+-?[0-9]{1,5}` | result, _ |
103
- | `#=<>` | Fails on purpose | `#==<> result.include?(4)` | result, _ |
104
+ | `#=<>` | Fails on purpose | `#=<> result.include?(4)` | result, _ |
104
105
 
105
106
 
106
107
  ### Using other test runners
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/agent.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'token_budget'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/base.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'output_manager'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/compact.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/factory.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative '../tty_detector'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/live_status_manager.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'test_run_state'
4
6
  require_relative 'tty_status_display'
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/output_manager.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'live_status_manager'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/quiet.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/test_run_state.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/token_budget.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/tty_status_display.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require 'tty-cursor'
4
6
  require 'tty-screen'
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters/verbose.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/formatters.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'formatters/base'
4
6
  require_relative 'formatters/compact'
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/line_spec_parser.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/modes/generate.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/modes/inspect.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -13,14 +15,24 @@ class Tryouts
13
15
 
14
16
  def handle
15
17
  @output_manager.raw("Inspecting: #{@file}")
16
- @output_manager.separator(:heavy)
18
+ @output_manager.raw('=' * 60)
17
19
  @output_manager.raw("Found #{@testrun.total_tests} test cases")
18
20
  @output_manager.raw("Setup code: #{@testrun.setup.empty? ? 'None' : 'Present'}")
19
21
  @output_manager.raw("Teardown code: #{@testrun.teardown.empty? ? 'None' : 'Present'}")
20
22
  @output_manager.raw('')
21
23
 
22
- @testrun.test_cases.each_with_index do |tc, i|
23
- @output_manager.raw("Test #{i + 1}: #{tc.description}")
24
+ test_number = 0
25
+ @testrun.test_cases.each do |tc|
26
+ if tc.is_a?(Tryouts::OrphanBlock)
27
+ @output_manager.raw("Orphan code block (no description, no expectations)")
28
+ @output_manager.raw(" Code lines: #{tc.code.lines.count}")
29
+ @output_manager.raw(" Range: #{tc.line_range}")
30
+ @output_manager.raw('')
31
+ next
32
+ end
33
+
34
+ test_number += 1
35
+ @output_manager.raw("Test #{test_number}: #{tc.description}")
24
36
  @output_manager.raw(" Code lines: #{tc.code.lines.count}")
25
37
  @output_manager.raw(" Expectations: #{tc.expectations.size}")
26
38
  @output_manager.raw(" Range: #{tc.line_range}")
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/opts.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  class CLI
@@ -161,7 +163,6 @@ class Tryouts
161
163
 
162
164
  opts.separator "\nParser Options:"
163
165
  opts.on('--enhanced-parser', 'Use enhanced parser with inhouse comment extraction (default)') { options[:parser] = :enhanced }
164
- opts.on('--legacy-parser', 'Use legacy prism parser') { options[:parser] = :prism }
165
166
 
166
167
  opts.separator "\nInspection Options:"
167
168
  opts.on('-i', '--inspect', 'Inspect file structure without running tests') { options[:inspect] = true }
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli/tty_detector.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require 'tty-screen'
4
6
 
data/lib/tryouts/cli.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/cli.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require 'optparse'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/console.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require 'pathname'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/base.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  module ExpectationEvaluators
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/boolean.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/exception.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/expectation_result.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  module ExpectationEvaluators
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/false.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/intentional_failure.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
  require_relative 'regular'
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/non_nil.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/output.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/performance_time.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/regex_match.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/registry.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'expectation_result'
4
6
  require_relative 'base'
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/regular.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/result_type.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/expectation_evaluators/true.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'base'
4
6
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/failure_collector.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative 'console'
4
6
 
@@ -1,6 +1,7 @@
1
1
  # lib/tryouts/file_processor.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
- require_relative 'parsers/legacy_parser'
4
5
  require_relative 'parsers/enhanced_parser'
5
6
  require_relative 'test_executor'
6
7
  require_relative 'cli/modes/inspect'
@@ -9,7 +10,7 @@ require_relative 'cli/modes/generate'
9
10
  class Tryouts
10
11
  class FileProcessor
11
12
  # Supported parser types for validation and documentation
12
- PARSER_TYPES = [:enhanced, :prism].freeze
13
+ PARSER_TYPES = [:enhanced].freeze
13
14
  def initialize(file:, options:, output_manager:, translator:, global_tally:)
14
15
  @file = file
15
16
  @options = options
@@ -52,8 +53,6 @@ class Tryouts
52
53
  case parser_type
53
54
  when :enhanced
54
55
  EnhancedParser.new(file, options)
55
- when :prism
56
- LegacyParser.new(file, options)
57
56
  end
58
57
  end
59
58
 
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/parser_warning.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  class Tryouts
4
6
  # Data structure for parser warnings
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/parsers/base_parser.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require 'prism'
4
6
 
@@ -11,8 +13,7 @@ class Tryouts
11
13
  #
12
14
  # BaseParser establishes the foundation for parsing tryout files by handling
13
15
  # file loading, Prism integration, and providing shared parsing infrastructure.
14
- # All concrete parser implementations (EnhancedParser, LegacyParser) inherit
15
- # from this class.
16
+ # All concrete parser implementations (EnhancedParser) inherit from this class.
16
17
  #
17
18
  # @abstract Subclass and implement {#parse} to create a concrete parser
18
19
  # @example Implementing a custom parser
@@ -75,7 +76,6 @@ class Tryouts
75
76
  # 4. Provide a unique `parser_type` identifier
76
77
  #
77
78
  # @see EnhancedParser For Prism-based comment extraction
78
- # @see LegacyParser For line-by-line parsing approach
79
79
  # @see SharedMethods For common parsing utilities
80
80
  # @since 3.0.0
81
81
  class BaseParser
@@ -1,4 +1,6 @@
1
1
  # lib/tryouts/parsers/enhanced_parser.rb
2
+ #
3
+ # frozen_string_literal: true
2
4
 
3
5
  require_relative '../test_case'
4
6
  require_relative 'base_parser'
@@ -31,7 +33,7 @@ class Tryouts
31
33
  # @!attribute [r] parser_type
32
34
  # @return [Symbol] Returns :enhanced to identify parser type
33
35
  #
34
- # ## Key Benefits over LegacyParser
36
+ # ## Key Benefits
35
37
  #
36
38
  # ### 1. HEREDOC Safety
37
39
  # - Uses Prism's `parse_comments()` to extract only actual Ruby comments
@@ -56,7 +58,6 @@ class Tryouts
56
58
  # Uses Ruby 3.4+ pattern matching (`case/in`) for token classification,
57
59
  # providing clean, modern syntax for expectation type detection.
58
60
  #
59
- # @see LegacyParser For simpler regex-based parsing (legacy compatibility)
60
61
  # @see BaseParser For shared parsing functionality
61
62
  # @since 3.2.0
62
63
  class EnhancedParser < Tryouts::Parsers::BaseParser
@@ -72,6 +73,12 @@ class Tryouts
72
73
  def parse
73
74
  return handle_syntax_errors if @prism_result.failure?
74
75
 
76
+ # Line ranges of multi-line statements, computed once from the whole-file
77
+ # parse. A column-0 comment strictly inside one of these spans (e.g. a
78
+ # #=>-shaped line inside an unclosed array literal) cannot be a real
79
+ # block boundary or expectation, no matter what it looks like lexically.
80
+ @multiline_statement_ranges = multiline_statement_ranges
81
+
75
82
  # Use inhouse comment extraction instead of line-by-line regex parsing
76
83
  # This automatically excludes HEREDOC content!
77
84
  tokens = tokenize_content_with_inhouse_extraction
@@ -104,22 +111,41 @@ class Tryouts
104
111
  comments = Prism.parse_comments(@source)
105
112
  comment_by_line = comments.group_by { |comment| comment.location.start_line }
106
113
 
114
+ # A =begin/=end block comment is one Prism comment node spanning multiple
115
+ # lines, but comment_by_line only keys its start line. Its interior lines
116
+ # must be skipped entirely: re-emitting them as :code duplicates them, and
117
+ # running the marker regex cascade against the raw multi-line slice lets an
118
+ # interior #=>-shaped line match via ^/$ line anchors.
119
+ multiline_comment_spans = comments.filter_map do |comment|
120
+ loc = comment.location
121
+ ((loc.start_line + 1)..loc.end_line) if loc.end_line > loc.start_line
122
+ end
123
+
107
124
  # Process each line, handling multiple comments per line
108
125
  @lines.each_with_index do |line, index|
109
126
  line_number = index + 1
110
127
 
128
+ next if multiline_comment_spans.any? { |span| span.cover?(line_number) }
129
+
111
130
  if (comments_for_line = comment_by_line[line_number]) && !comments_for_line.empty?
112
131
  emitted_code = false
113
132
  comments_for_line.sort_by! { |c| c.location.start_column }
114
133
  comments_for_line.each do |comment|
115
134
  comment_content = comment.slice.strip
116
- if comment.location.start_column > 0
135
+ if comment.location.end_line > comment.location.start_line
136
+ # Whole =begin/=end block: one plain comment token for the span
137
+ tokens << { type: :comment, content: comment_content, line: index }
138
+ elsif comment.location.start_column > 0
117
139
  unless emitted_code
118
140
  tokens << { type: :code, content: line, line: index, ast: parse_ruby_line(line) }
119
141
  emitted_code = true
120
142
  end
121
143
  # Inline comment (after code) - treat as regular comment, not expectation
122
144
  tokens << { type: :comment, content: comment_content.sub(/^#\s*/, ''), line: line_number - 1 }
145
+ elsif strictly_inside_multiline_statement?(index)
146
+ # Column-0 comment inside a multi-line statement (unclosed
147
+ # array/hash/call/...) - force plain :comment regardless of shape
148
+ tokens << { type: :comment, content: comment_content.sub(/^#\s*/, ''), line: line_number - 1 }
123
149
  else
124
150
  tokens << classify_comment_inhousely(comment_content, line_number)
125
151
  end
@@ -140,6 +166,34 @@ class Tryouts
140
166
  tokens
141
167
  end
142
168
 
169
+ # Collect 0-based, inclusive line ranges for every AST node that spans more
170
+ # than one physical line, walking the existing whole-file @prism_result.
171
+ # Built once per parse; no second Prism.parse call.
172
+ def multiline_statement_ranges
173
+ ranges = []
174
+ root = @prism_result.value
175
+ return ranges if root.nil?
176
+
177
+ visit = lambda do |node|
178
+ next if node.nil?
179
+
180
+ loc = node.location
181
+ ranges << ((loc.start_line - 1)..(loc.end_line - 1)) if loc.start_line != loc.end_line
182
+ node.compact_child_nodes.each { |child| visit.call(child) }
183
+ end
184
+
185
+ root.statements.body.each { |stmt| visit.call(stmt) }
186
+ ranges
187
+ end
188
+
189
+ # True if the 0-based line index falls STRICTLY inside a multi-line
190
+ # statement span. A comment on the same line as the opening or closing
191
+ # delimiter is still eligible to be a real boundary; one on a line fully
192
+ # swallowed by the statement is not.
193
+ def strictly_inside_multiline_statement?(line_idx)
194
+ @multiline_statement_ranges.any? { |range| line_idx > range.first && line_idx < range.last }
195
+ end
196
+
143
197
  # Classify comment content into specific token types using pattern matching
144
198
  #
145
199
  # Takes a raw comment string and determines what type of tryout token it