Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 1 addition & 4 deletions .rubocop-https---www-goodcop-style-base-yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# yaml-language-server: $schema=https://www.rubyschema.org/rubocop.json
---
AllCops:
DisabledByDefault: true
Expand Down Expand Up @@ -821,10 +822,6 @@ Style/QuotedSymbols:
Enabled: true
EnforcedStyle: same_as_string_literals

Style/RaiseArgs:
Enabled: true
EnforcedStyle: compact

Style/RandomWithOffset:
Enabled: true

Expand Down
13 changes: 13 additions & 0 deletions lib/phlex/compiler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require "prism"

module Phlex::Compiler
def self.compile(component)
path, line = Object.const_source_location(component.name)
return unless File.exist?(path)
source = File.read(path)
tree = Prism.parse(source).value
Compilation.new(component, path, line, source, tree).compile
end
end
34 changes: 34 additions & 0 deletions lib/phlex/compiler/class_compiler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

class Phlex::Compiler::ClassCompiler < Prism::Visitor
def initialize(compiler)
@compiler = compiler
end

def compile(node)
visit_all(node.child_nodes)
end

def visit_def_node(node)
return if node.name == :initialize

compiled_source = Phlex::Compiler::MethodCompiler.new(@compiler.component).compile(node)

if compiled_source
puts compiled_source
@compiler.redefine_method(compiled_source, node.location.start_line)
end
end

def visit_class_node(node)
nil
end

def visit_module_node(node)
nil
end

def visit_block_node(node)
nil
end
end
24 changes: 24 additions & 0 deletions lib/phlex/compiler/compilation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Phlex::Compiler
class Compilation
def initialize(component, path, line, source, tree)
@component = component
@path = path
@line = line
@source = source
@tree = tree
freeze
end

attr_reader :component, :line, :source, :path

def compile
FileCompiler.new(self).compile(@tree)
end

def redefine_method(source, line)
@component.class_eval("# frozen_string_literal: true\n#{source}", @path, line - 1)
end
end
end
29 changes: 29 additions & 0 deletions lib/phlex/compiler/file_compiler.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# frozen_string_literal: true

class Phlex::Compiler::FileCompiler < Prism::Visitor
def initialize(compiler)
@compiler = compiler
end

def compile(node)
visit(node)
end

def visit_class_node(node)
if @compiler.line == node.location.start_line
Phlex::Compiler::ClassCompiler.new(@compiler).compile(node)
end
end

# def visit_module_node(node)
# super
# end

def visit_def_node(node)
nil
end

def visit_block_node(node)
nil
end
end
136 changes: 136 additions & 0 deletions lib/phlex/compiler/formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# frozen_string_literal: true

module Phlex::Compiler
class Formatter < VerbatimFormatter
def initialize
super
@new_line_character = "\n"
@indentation_character = "\t"
@level = 0
end

def visit(node)
case node
when nil
nil
when Array
visit_array(node)
when Proc
node.call(self)
else
super
end
end

def visit_array(nodes)
nodes.each do |node|
case node
when Array
indent { visit_array(node) }
else
visit(node)
end
end
end

def format(node)
@buffer.clear
visit(node)
[@buffer.join, @source_map]
end

def visit_each(nodes)
i, len = 0, nodes.length
if block_given?
while i < len
node = nodes[i]
i += 1
if node
visit node
yield unless i == len
end
end
else
while i < len
visit nodes[i]
i += 1
end
end
end

def space
push " "
end

def statement
ensure_new_line
yield
end

def ensure_new_line
new_line unless on_new_line?
end

def on_new_line?
@new_line_at == @buffer.length
end

def new_line
push "#{@new_line_character}#{@indentation_character * @level}"
@new_line_at = @buffer.length
end

def indent
original_level = @level
@level += 1
ensure_new_line
yield
@level = original_level
end

def visit_block_node(node)
emit node.opening_loc
indent do
visit node.body
end
new_line
emit node.closing_loc
end

def visit_call_node(node)
visit node.receiver
emit node.call_operator_loc
emit node.message_loc
if node.opening_loc
emit node.opening_loc
else
space
end
visit node.arguments
emit node.closing_loc
space
visit node.block
end

def visit_def_node(node)
emit node.def_keyword_loc
space
push node.name

if node.parameters
push "("
visit node.parameters
push ")"
end

indent { visit node.body }

new_line
emit node.end_keyword_loc
end

def visit_statements_node(node)
visit_each(node.compact_child_nodes) { ensure_new_line }
end
end
end
Loading