Class: Y2R::AST::YCP::Node

Inherits:
OpenStruct
  • Object
show all
Defined in:
lib/y2r/ast/ycp.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.transfers_comments(*names) ⇒ Object



647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
# File 'lib/y2r/ast/ycp.rb', line 647

def transfers_comments(*names)
  names.each do |name|
    name_without_comments = :"#{name}_without_comments"
    name_with_comments    = :"#{name}_with_comments"

    define_method name_with_comments do |context|
      whitespace = context.whitespace
      if context.whitespace != Comments::Whitespace::DROP_ALL
        context = context.with_whitespace(Comments::Whitespace::DROP_ALL)
      end

      node = send(name_without_comments, context)
      if node
        if comment_before
          processed_comment_before = Comments.process_comment_before(
            self,
            comment_before,
            :whitespace => whitespace
          )
          if processed_comment_before
            node.comment_before = processed_comment_before
          end
        end

        if comment_after
          processed_comment_after = Comments.process_comment_after(
            self,
            comment_after,
            :whitespace => whitespace
          )
          if processed_comment_after
            node.comment_after = processed_comment_after
          end
        end
      end
      node
    end

    alias_method name_without_comments, name
    alias_method name, name_with_comments
  end
end

Instance Method Details

#always_returns?Boolean

In Ruby, methods return value of last expresion if no return statement is encountered. To match YaST’s behavior in this case (returning nil), we need to append nil at the end, unless we are sure some statement in the method always causes early return. These early returns are detected using this method.



712
713
714
# File 'lib/y2r/ast/ycp.rb', line 712

def always_returns?
  false
end

#compile_as_copy_if_needed(context) ⇒ Object



716
717
718
# File 'lib/y2r/ast/ycp.rb', line 716

def compile_as_copy_if_needed(context)
  compile(context)
end

#compile_statements(statements, context) ⇒ Object



720
721
722
723
724
725
726
# File 'lib/y2r/ast/ycp.rb', line 720

def compile_statements(statements, context)
  if statements
    statements.compile(context)
  else
    Ruby::Statements.new(:statements => [])
  end
end

#compile_statements_inside_block(statements, context) ⇒ Object



728
729
730
731
732
# File 'lib/y2r/ast/ycp.rb', line 728

def compile_statements_inside_block(statements, context)
  context.inside self do |inner_context|
    compile_statements(statements, inner_context)
  end
end

#compile_statements_with_whitespace(statements, context) ⇒ Object



751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
# File 'lib/y2r/ast/ycp.rb', line 751

def compile_statements_with_whitespace(statements, context)
  # There is a duplicate import removal logic in ycpc, but it doesn't
  # work for auto-iports such as UI. As a result, we need to do the
  # deduplication again ourselves.
  statements = remove_duplicate_imports(statements)

  case statements.size
    when 0
      []

    when 1
      statement_context = context.with_whitespace(Comments::Whitespace.new(
        :drop_before_above => true,
        :drop_after_below  => true
      ))

      [statements.first.compile(statement_context)]
    else
      first_context  = context.with_whitespace(Comments::Whitespace.new(
        :drop_before_above => true
      ))
      middle_context = context.with_whitespace(Comments::Whitespace::KEEP_ALL)
      last_context   = context.with_whitespace(Comments::Whitespace.new(
        :drop_after_below => true
      ))

      [statements.first.compile(first_context)] +
        statements[1..-2].map { |s| s.compile(middle_context) } +
        [statements.last.compile(last_context)]
    end
end

#creates_local_scope?Boolean



691
692
693
# File 'lib/y2r/ast/ycp.rb', line 691

def creates_local_scope?
  false
end

#needs_copy?Boolean



703
704
705
# File 'lib/y2r/ast/ycp.rb', line 703

def needs_copy?
  false
end

#never_nil?Boolean

‘Ops` exists because YCP does not have exceptions and nil propagates to operation results. If we use a Ruby operator where the YaST program can produce `nil`, we would crash with an exception. If we know that `nil` cannot be there, we ca use a plain ruby operator.



699
700
701
# File 'lib/y2r/ast/ycp.rb', line 699

def never_nil?
  false
end

#optimize_last_statement(statements, klass) ⇒ Object



783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
# File 'lib/y2r/ast/ycp.rb', line 783

def optimize_last_statement(statements, klass)
  if !statements.empty?
    last = statements.last

    last_optimized = if last.is_a?(klass)
      value = last.value || Ruby::Literal.new(:value => nil)

      # We can't optimize the |return| or |next| away if they have
      # comments and we can't move them to the value because it has its
      # own comments. (We don't want to mess with concatenating.)
      can_optimize = true
      can_optimize = false if last.comment_before && value.comment_before
      can_optimize = false if last.comment_after  && value.comment_after

      if can_optimize
        value.comment_before = last.comment_before if last.comment_before
        value.comment_after  = last.comment_after  if last.comment_after
        value
      else
        last
      end
    else
      last
    end

    statements[0..-2] + [last_optimized]
  else
    []
  end
end

#optimize_next(statements) ⇒ Object



818
819
820
# File 'lib/y2r/ast/ycp.rb', line 818

def optimize_next(statements)
  optimize_last_statement(statements, Ruby::Next)
end

#optimize_return(statements) ⇒ Object



814
815
816
# File 'lib/y2r/ast/ycp.rb', line 814

def optimize_return(statements)
  optimize_last_statement(statements, Ruby::Return)
end

#remove_duplicate_imports(statements) ⇒ Object



734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
# File 'lib/y2r/ast/ycp.rb', line 734

def remove_duplicate_imports(statements)
  seen_imports = []

  statements.select do |statement|
    if statement.is_a?(Import)
      if seen_imports.include?(statement.name)
        false
      else
        seen_imports << statement.name
        true
      end
    else
      true
    end
  end
end