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:



581
582
583
584
585
586
587
# File 'utils/ast.rb', line 581

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)


676
677
678
679
680
681
682
683
684
685
# File 'utils/ast.rb', line 676

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)


620
621
622
623
624
625
# File 'utils/ast.rb', line 620

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

#processString

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:



590
591
592
# File 'utils/ast.rb', line 590

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:



595
596
597
598
599
600
# File 'utils/ast.rb', line 595

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:



657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
# File 'utils/ast.rb', line 657

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:



635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
# File 'utils/ast.rb', line 635

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)


603
604
605
# File 'utils/ast.rb', line 603

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)


608
609
610
611
612
613
614
615
616
617
# File 'utils/ast.rb', line 608

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)


691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
# File 'utils/ast.rb', line 691

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