Skip to content

Updating to UBI9.5 and Ruby 3.3.7 #1873

Closed
@stephen-ritter

Description

@stephen-ritter

Due to security reasons I was attempting to update to UBI9.5, however I hit some issues. I hit an OpenSSL issue when I ran the line gem update --system 3.3.14:

OpenSSL is not available. Install OpenSSL and rebuild Ruby or use non-HTTPS sources (Gem::Exception)

To fix this I updated Ruby to 3.3.7, however I was faced with another issue in that the unit tests started to fail. Specifically the tests in ruby_lex_utils_spec.rb were failing as it appears that the class RubyLex has been refactored heavily:
https://msp-greg.github.io/ruby_3_3/irb/IRB/RubyLex.html
https://msp-greg.github.io/ruby_3_2/irb/RubyLex.html
I did some work to fix some of the tests by switching from using RubyLex to Prism. I have been stuck on the function each_lexed_segment as Prism for the most part has been a drop in replacement however in the implementation of this function it is a bit trickier. I am attaching the code that I have updated just to give it as an example, and it may be helpful in a future update.

It should be noted that Prism does not emit the on_sp event, so you will not be able to recreate your code with the spaces in it, thus some of the tests will need to be updated to account for this lack of spacing.
ruby/prism#722

# encoding: ascii-8bit

# Copyright 2022 Ball Aerospace & Technologies Corp.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
# under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; version 3 with
# attribution addendums as found in the LICENSE.txt
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# Modified by OpenC3, Inc.
# All changes Copyright 2022, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.

require 'prism'

class RubyLexUtils
  # Regular expression to detect blank lines
  BLANK_LINE_REGEX  = /^\s*$/
  # Regular expression to detect lines containing only 'else'
  LONELY_ELSE_REGEX = /^\s*else\s*$/

  KEY_KEYWORDS = [
    'class'.freeze,
    'module'.freeze,
    'def'.freeze,
    'undef'.freeze,
    'begin'.freeze,
    'rescue'.freeze,
    'ensure'.freeze,
    'end'.freeze,
    'if'.freeze,
    'unless'.freeze,
    'then'.freeze,
    'elsif'.freeze,
    'else'.freeze,
    'case'.freeze,
    'when'.freeze,
    'while'.freeze,
    'until'.freeze,
    'for'.freeze,
    'break'.freeze,
    'next'.freeze,
    'redo'.freeze,
    'retry'.freeze,
    'in'.freeze,
    'do'.freeze,
    'return'.freeze,
    'alias'.freeze
  ]

  # @param text [String]
  # @return [Boolean] Whether the text contains the 'begin' keyword
  def contains_begin?(text)
    lex = Prism.lex(text)
    tokens = lex.value
    tokens.each do |token|
      token_object = token[0]
      if token_object.type == :KEYWORD_BEGIN
        return true
      end
    end
    return false
  end

  # @param text [String]
  # @return [Boolean] Whether the text contains the 'end' keyword
  def contains_end?(text)
    lex = Prism.lex(text)
    tokens = lex.value
    tokens.each do |token|
      token_object = token[0]
      if token_object.type == :KEYWORD_END
        return true
      end
    end
    return false
  end

  # @param text [String]
  # @return [Boolean] Whether the text contains a Ruby keyword
  def contains_keyword?(text)
    lex = Prism.lex(text)
    tokens = lex.value
    tokens.each do |token|
      token_object = token[0]
      state_bits = token[1]
      if token_object.type.start_with?("KEYWORD")
        if KEY_KEYWORDS.include?(token_object.value)
          return true
        end
      elsif token_object.type == :BRACE_LEFT and state_bits != (Ripper::EXPR_BEG | Ripper::EXPR_LABEL)
        return true
      end
    end
    return false
  end

  # @param text [String]
  # @return [Boolean] Whether the text contains a keyword which starts a block.
  #   i.e. 'do', '{', or 'begin'
  def contains_block_beginning?(text)
    lex = Prism.lex(text)
    tokens = lex.value
    tokens.each do |token|
      token_object = token[0]
      if token_object.type == :KEYWORD_BEGIN || token_object.type == :KEYWORD_DO || token_object.type == :BRACE_LEFT
        return true
      end
    end
    return false
  end

  def continue_block?(text)
    lex = Prism.lex(text)
    tokens = lex.value
    index = tokens.length - 1
    while index > 0
      token_object = tokens[index][0]
      return true if token_object.type == :KEYWORD_DO
      index -= 1
    end
    return false
  end

  # @param text [String]
  # @param progress_dialog [OpenC3::ProgressDialog] If this is set, the overall
  #   progress will be set as the processing progresses
  # @return [String] The text with all comments removed
  def remove_comments(text, progress_dialog = nil)
    lex = Prism.lex(text)
    tokens = lex.value
    comments_removed = ""
    token_count = 0
    progress = 0.0
    tokens.each do |token|
      token_object = token[0]
      token_count += 1
      if token_object.type != :COMMENT
        comments_removed << token_object.value
      else
        newline_count = token_object.value.count("\n")
        comments_removed << ("\n" * newline_count)
      end
      if progress_dialog and token_count % 10000 == 0
        progress += 0.01
        progress = 0.0 if progress >= 0.99
        progress_dialog.set_overall_progress(progress)
      end
    end
    return comments_removed
  end

Metadata

Metadata

Assignees

No one assigned

    Labels

    maintenanceDependencies or other issues not bugs or features

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions