Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ jobs:
- name: RBS Inline
run: bundle exec rake rbs_inline

# - name: Sorbet
# run: bundle exec srb tc
- name: Sorbet
run: bundle exec srb tc

- name: Run C tests
run: ./run_herb_tests
Expand Down
6 changes: 3 additions & 3 deletions lib/herb/ast/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
module Herb
module AST
module Helpers
#: (Herb::AST::Node) -> bool
#: (Herb::AST::Node?) -> bool
def erb_outputs?(node)
return false unless node.is_a?(Herb::AST::ERBContentNode)

opening = node.tag_opening&.value
opening&.include?("=") && !opening&.start_with?("<%#")
opening = node.tag_opening&.value || ""
opening.include?("=") && !opening.start_with?("<%#")
end

#: (String) -> bool
Expand Down
20 changes: 14 additions & 6 deletions lib/herb/ast/node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@
# typed: true

module Herb
#: type serialized_node = {
#| type: String,
#| location: serialized_location?,
#| errors: Array[serialized_error]
#| }
module AST
class Node
attr_reader :type #: String
attr_reader :location #: Location
attr_reader :errors #: Array[Herb::Errors::Error]

#: (String, Location, Array[Herb::Errors::Error]) -> void
#: String
attr_reader :type
#: Location
attr_reader :location
#: Array[Herb::Errors::Error]
attr_reader :errors

#: (String, Location, ?Array[Herb::Errors::Error]) -> void
def initialize(type, location, errors = [])
@type = type
@location = location
Expand All @@ -19,7 +27,7 @@ def initialize(type, location, errors = [])
def to_hash
{
type: type,
location: location&.to_hash,
location: location.to_hash,
errors: errors.map(&:to_hash),
}
end
Expand Down
1 change: 1 addition & 0 deletions lib/herb/engine.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true
# typed: false

require "json"
require "time"
Expand Down
4 changes: 2 additions & 2 deletions lib/herb/engine/debug_visitor.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true
# typed: false

module Herb
class Engine
Expand Down Expand Up @@ -30,6 +31,7 @@ def initialize(file_path: nil, project_path: nil)
@in_html_comment = false
@in_html_doctype = false
@erb_nodes_to_wrap = [] #: Array[Herb::AST::ERBContentNode]
@top_level_elements = [] #: Array[Herb::AST::HTMLElementNode]
end

def visit_document_node(node)
Expand Down Expand Up @@ -142,8 +144,6 @@ def replace_erb_nodes_recursive(node)
end

def find_top_level_elements(document_node)
@top_level_elements = [] #: Array[Herb::AST::HTMLElementNode]

document_node.children.each do |child|
@top_level_elements << child if child.is_a?(Herb::AST::HTMLElementNode)
end
Expand Down
4 changes: 3 additions & 1 deletion lib/herb/lex_result.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# frozen_string_literal: true
# typed: true

module Herb
class LexResult < Result
attr_reader :value #: TokenList
#: TokenList
attr_reader :value

#: (Array[Herb::Token], String, Array[Herb::Warnings::Warning], Array[Herb::Errors::Error]) -> void
def initialize(value, source, warnings, errors)
Expand Down
16 changes: 11 additions & 5 deletions lib/herb/location.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@
# typed: true

module Herb
#: type serialized_location = {
#| start: serialized_position,
#| end: serialized_position
#| }
class Location
attr_reader :start #: Position
attr_reader :end #: Position
#: Position
attr_reader :start
#: Position
attr_reader :end

#: (Position, Position) -> void
def initialize(start_position, end_position)
Expand All @@ -28,9 +34,9 @@ def self.[](start_line, start_column, end_line, end_column)
#: () -> serialized_location
def to_hash
{
start: start,
end: self.end,
} #: Herb::serialized_location
start: start.to_hash,
end: self.end.to_hash,
}
end

#: (?untyped) -> String
Expand Down
4 changes: 3 additions & 1 deletion lib/herb/parse_result.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# frozen_string_literal: true
# typed: true

require "json"

module Herb
class ParseResult < Result
attr_reader :value #: Herb::AST::DocumentNode
#: Herb::AST::DocumentNode
attr_reader :value

#: (Herb::AST::DocumentNode, String, Array[Herb::Warnings::Warning], Array[Herb::Errors::Error]) -> void
def initialize(value, source, warnings, errors)
Expand Down
7 changes: 5 additions & 2 deletions lib/herb/position.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
# typed: true

module Herb
#: type serialized_position = { line: Integer, column: Integer }
class Position
attr_reader :line #: Integer
attr_reader :column #: Integer
#: Integer
attr_reader :line
#: Integer
attr_reader :column

#: (Integer, Integer) -> void
def initialize(line, column)
Expand Down
7 changes: 5 additions & 2 deletions lib/herb/range.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
# typed: true

module Herb
#: type serialized_range = [Integer, Integer]
class Range
attr_reader :from #: Integer
attr_reader :to #: Integer
#: Integer
attr_reader :from
#: Integer
attr_reader :to

#: (Integer, Integer) -> void
def initialize(from, to)
Expand Down
9 changes: 6 additions & 3 deletions lib/herb/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

module Herb
class Result
attr_reader :source #: String
attr_reader :warnings #: Array[Herb::Warnings::Warning]
attr_reader :errors #: Array[Herb::Errors::Error]
#: String
attr_reader :source
#: Array[Herb::Warnings::Warning]
attr_reader :warnings
#: Array[Herb::Errors::Error]
attr_reader :errors

#: (String, Array[Herb::Warnings::Warning], Array[Herb::Errors::Error]) -> void
def initialize(source, warnings, errors)
Expand Down
24 changes: 17 additions & 7 deletions lib/herb/token.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@
# typed: true

module Herb
#: type serialized_token = {
#| value: String,
#| range: serialized_range?,
#| location: serialized_location?,
#| type: String
#| }
class Token
attr_reader :value #: String
attr_reader :range #: Range
attr_reader :location #: Location
attr_reader :type #: String
#: String
attr_reader :value
#: Range?
attr_reader :range
#: Location?
attr_reader :location
#: String
attr_reader :type

#: (String, Range, Location, String) -> void
def initialize(value, range, location, type)
Expand All @@ -23,7 +33,7 @@ def to_hash
range: range&.to_a,
location: location&.to_hash,
type: type,
} #: Herb::serialized_token
}
end

#: (?untyped) -> String
Expand All @@ -33,7 +43,7 @@ def to_json(state = nil)

#: () -> String
def tree_inspect
%("#{value.force_encoding("utf-8")}" #{location.tree_inspect})
%("#{value.force_encoding("utf-8")}" #{location&.tree_inspect})
end

#: () -> String
Expand All @@ -47,7 +57,7 @@ def value_inspect

#: () -> String
def inspect
%(#<Herb::Token type="#{type}" value=#{value_inspect} range=#{range.tree_inspect} start=#{location.start.tree_inspect} end=#{location.end.tree_inspect}>)
%(#<Herb::Token type="#{type}" value=#{value_inspect} range=#{range&.tree_inspect} start=#{location&.start&.tree_inspect} end=#{location&.end&.tree_inspect}>)
end
end
end
14 changes: 11 additions & 3 deletions lib/herb/warnings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,18 @@

module Herb
module Warnings
#: type serialized_warning = {
#| type: String,
#| location: serialized_location?,
#| message: String
#| }
class Warning
attr_reader :type #: String
attr_reader :location #: Location
attr_reader :message #: String
#: String
attr_reader :type
#: Location?
attr_reader :location
#: String
attr_reader :message

#: (String, Location, String) -> void
def initialize(type, location, message)
Expand Down
2 changes: 1 addition & 1 deletion sig/herb/ast/helpers.rbs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions sig/herb/token.rbs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions sorbet/config
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
lib/
--ignore=/tmp/
--ignore=/vendor/bundle
--enable-experimental-rbs-signatures
--enable-experimental-rbs-assertions
--enable-experimental-rbs-comments
16 changes: 12 additions & 4 deletions templates/lib/herb/ast/nodes.rb.erb
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
module Herb
module AST
<%- nodes.each do |node| -%>
#: type serialized_<%= node.human %> = {
<%- node.fields.each do |field| -%>
<%- is_nilable = !%w[Array[Herb::AST::Node] Array[Herb::AST::ERBWhenNode] Array[Herb::AST::ERBInNode] bool nil].include?(field.ruby_type) -%>
#| <%= field.name %>: <%= field.ruby_type %><%= if is_nilable then "?" end %>,
<%- end -%>
#| }
class <%= node.name -%> < Node
<%- node.fields.each do |field| -%>
attr_reader :<%= field.name %> #: <%= field.ruby_type %>
<%- is_nilable = !%w[Array[Herb::AST::Node] Array[Herb::AST::ERBWhenNode] Array[Herb::AST::ERBInNode] bool nil].include?(field.ruby_type) -%>
#: <%= field.ruby_type %><%= if is_nilable then "?" end %>
attr_reader :<%= field.name %>
<%- end -%>

#: (<%= ["String", "Location", "Array[Herb::Errors::Error]", *node.fields.map(&:ruby_type)].join(", ") %>) -> void
Expand All @@ -24,7 +32,7 @@ module Herb
<%- node.fields.each do |field| -%>
<%= field.name %>: <%= field.name %>,
<%- end -%>
}) #: Herb::serialized_<%= node.human %>
})
end

#: (Visitor) -> void
Expand Down Expand Up @@ -73,7 +81,7 @@ module Herb
output += %(<%= name %>#{<%= field.name %>.inspect}\n)
<%- when Herb::Template::TokenField -%>
output += "<%= name %>"
output += <%= field.name %> ? <%= field.name %>.tree_inspect : "∅"
output += <%= field.name %>&.tree_inspect || "∅"
output += "\n"
<%- when Herb::Template::BooleanField -%>
output += "<%= name %>"
Expand All @@ -95,7 +103,7 @@ module Herb
<%- else -%>
output += "│ └── "
<%- end -%>
output += <%= field.name %>.tree_inspect(indent).gsub(/^/, " " * (indent + 1)).lstrip.gsub(/^/, "<%= prefix %>").delete_prefix("<%= prefix %>")
output += <%= field.name %>&.tree_inspect(indent)&.gsub(/^/, " " * (indent + 1))&.lstrip&.gsub(/^/, "<%= prefix %>")&.delete_prefix("<%= prefix %>") || ""
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kind of annoying, but despite checking for field_name above, Sorbet still considers it could be nil, so we need to add safe navigators on every method. It does seem to work on sig files though. It might be one of the quirks of using Sorbet with rbs

Image

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it might be worth to report this on Sorbet

else
output += "∅\n"
end
Expand Down
Loading
Loading