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:



623
624
625
626
627
628
629
# File 'utils/ast.rb', line 623

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)


718
719
720
721
722
723
724
725
726
727
# File 'utils/ast.rb', line 718

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)


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

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:



632
633
634
# File 'utils/ast.rb', line 632

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:



637
638
639
640
641
642
# File 'utils/ast.rb', line 637

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:



699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
# File 'utils/ast.rb', line 699

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:



677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
# File 'utils/ast.rb', line 677

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)


645
646
647
# File 'utils/ast.rb', line 645

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)


650
651
652
653
654
655
656
657
658
659
# File 'utils/ast.rb', line 650

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)


733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
# File 'utils/ast.rb', line 733

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