Class: Utils::AST::CaskAST Private

Inherits:
Object show all
Includes:
Utils::AST
Defined in:
utils/ast.rb

Overview

This class is part of a private API. This class may only be used in the Homebrew/brew repository. Third parties should avoid using this class if possible, as it may be removed or changed without warning.

Helper class for editing casks.

Constant Summary

Constants included from Utils::AST

BlockNode, DefNode, Node, ProcessedSource, SendNode, TreeRewriter

Instance Method Summary collapse

Methods included from Utils::AST

body_children, call_node_match?, component_match?, literal_value, process_source, ruby_literal, stanza_text

Methods included from Kernel

#which, #with_env

Constructor Details

#initialize(cask_contents) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:



633
634
635
636
637
638
639
# File 'utils/ast.rb', line 633

def initialize(cask_contents)
  @cask_contents = cask_contents
  processed_source, cask_block = process_cask
  @processed_source = T.let(processed_source, ProcessedSource)
  @cask_block = T.let(cask_block, BlockNode)
  @tree_rewriter = T.let(TreeRewriter.new(processed_source.buffer), TreeRewriter)
end

Instance Method Details

#depends_on_macos? ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:

  • (Boolean)


728
729
730
731
732
733
734
735
736
737
# File 'utils/ast.rb', line 728

def depends_on_macos?
  stanzas(:depends_on).any? do |stanza_node|
    stanza_node.arguments.any? do |argument|
      literal_value(argument) == :macos ||
        (argument.hash_type? && T.cast(argument, RuboCop::AST::HashNode).pairs.any? do |pair|
          literal_value(pair.key) == :macos
        end)
    end
  end
end

#first_stanza_value(name, within: nil) ⇒ T.untyped

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (T.untyped)


672
673
674
675
676
677
# File 'utils/ast.rb', line 672

def first_stanza_value(name, within: nil)
  stanza_node = stanzas(name, within:).first
  return if stanza_node.blank?

  literal_value(stanza_node.first_argument)
end

#process ⇒ String

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Returns:



642
643
644
# File 'utils/ast.rb', line 642

def process
  tree_rewriter.process
end

#replace_first_stanza_value(name, value) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method returns an undefined value.

Parameters:



647
648
649
650
651
652
# File 'utils/ast.rb', line 647

def replace_first_stanza_value(name, value)
  stanza_node = stanzas(name).first
  raise "Could not find '#{name}' stanza!" if stanza_node.blank?

  replace_stanza_argument(stanza_node, value)
end

#replace_root_stanza_with_arch_blocks(name, old_value) ⇒ void

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

This method returns an undefined value.

Parameters:



709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
# File 'utils/ast.rb', line 709

def replace_root_stanza_with_arch_blocks(name, old_value)
  stanza_node = top_level_stanzas(name).find do |node|
    literal_value(node.first_argument) == old_value
  end
  return if stanza_node.blank?

  indent = " " * stanza_node.source_range.column
  replacement = <<~EOS
    #{indent}on_arm do
    #{indent}  #{name} #{ruby_literal(old_value)}
    #{indent}end
    #{indent}on_intel do
    #{indent}  #{name} #{ruby_literal(old_value)}
    #{indent}end
  EOS
  tree_rewriter.replace(whole_line_range(stanza_node.source_range), replacement)
end

#replace_stanza_value(name, old_value, new_value, within: nil) ⇒ Integer

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:



687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
# File 'utils/ast.rb', line 687

def replace_stanza_value(name, old_value, new_value, within: nil)
  replacement_count = T.let(0, Integer)
  stanzas(name, within:).each do |stanza_node|
    if literal_value(stanza_node.first_argument) == old_value
      replace_stanza_argument(stanza_node, new_value)
      replacement_count += 1
    end

    stanza_node.arguments.grep(RuboCop::AST::HashNode).each do |hash_node|
      hash_node.pairs.each do |pair|
        next if literal_value(pair.value) != old_value

        tree_rewriter.replace(pair.value.source_range, ruby_literal(new_value))
        replacement_count += 1
      end
    end
  end

  replacement_count
end

#stanza?(name, within: nil) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean)


655
656
657
# File 'utils/ast.rb', line 655

def stanza?(name, within: nil)
  stanzas(name, within:).present?
end

#stanza_anywhere?(name, within:) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Parameters:

Returns:

  • (Boolean)


660
661
662
663
664
665
666
667
668
669
# File 'utils/ast.rb', line 660

def stanza_anywhere?(name, within:)
  cask_block.each_node(:block).any? do |node|
    block_node = T.cast(node, BlockNode)
    next false if block_node.method_name != within || block_node.receiver.present?

    block_node.each_node(:send).any? do |send_node|
      send_node.method_name == name && send_node.receiver.nil? && send_node.first_argument.present?
    end
  end
end

#update_depends_on_macos_minimum!(version) ⇒ Boolean

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.

Sets the minimum macOS version of the depends_on macos: stanza, adding the stanza when it is missing. Returns false when the minimum version cannot be expressed, e.g. an exact version list or a maximum.

Parameters:

Returns:

  • (Boolean)


743
744
745
746
747
748
749
750
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
# File 'utils/ast.rb', line 743

def update_depends_on_macos_minimum!(version)
  if (macos_pair = top_level_depends_on_macos_pair)
    return false unless minimum_macos_value?(macos_pair.value)

    tree_rewriter.replace(macos_pair.value.source_range, ruby_literal(version))
    return true
  end

  # A second stanza alongside a bare `depends_on :macos` would be flagged
  # as redundant by `Homebrew/OSDependsOn`.
  if (bare_argument = top_level_bare_depends_on_macos_argument)
    tree_rewriter.replace(bare_argument.source_range, "macos: #{ruby_literal(version)}")
    return true
  end

  return false if depends_on_macos?

  new_stanza = "depends_on macos: #{ruby_literal(version)}"

  if (existing_stanza = top_level_stanzas(:depends_on).last)
    indent = " " * existing_stanza.source_range.column
    tree_rewriter.insert_after(whole_line_range(existing_stanza.source_range), "#{indent}#{new_stanza}\n")
    return true
  end

  successor = stanza_successor(:depends_on)
  return false if successor.nil?

  indent = " " * successor.source_range.column
  line_range = whole_line_range(successor.source_range)
  separator = "\n" unless cask_contents[0...line_range.begin_pos].to_s.match?(/(\n\n|do\n)\z/)
  tree_rewriter.insert_before(line_range, "#{separator}#{indent}#{new_stanza}\n\n")
  true
end