parlour 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.parlour +5 -0
- data/CHANGELOG.md +10 -0
- data/README.md +28 -2
- data/exe/parlour +68 -2
- data/lib/parlour/detached_rbi_generator.rb +1 -6
- data/lib/parlour/plugin.rb +1 -1
- data/lib/parlour/rbi_generator/constant.rb +11 -2
- data/lib/parlour/rbi_generator/namespace.rb +29 -6
- data/lib/parlour/rbi_generator/parameter.rb +4 -4
- data/lib/parlour/type_loader.rb +25 -12
- data/lib/parlour/type_parser.rb +22 -17
- data/lib/parlour/version.rb +1 -1
- data/rbi/parlour.rbi +893 -0
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f37a6dd2dffd0b59594b4c0ed664cdd27c4ea5bb02d1ca0f944ddff2d6ccda83
         | 
| 4 | 
            +
              data.tar.gz: 38b776b79c349f48e672fbb81534d4ab1b751af13ecdab9e60d3f08562f03332
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 8da56118b8e784707a054ae7dbdddda63dade826ec19d87a06f468229e8e53ef1669f7b05c4c5be6cc9e75377846e729748b0f31d3400768041079050fb72776
         | 
| 7 | 
            +
              data.tar.gz: c7a39a7a91aee7298fbdf3e5d7ebdebc278001317cb365bc7f3970d62fa49c2d9e3f5d7e1eb4c70a386ef0964f14bde2647871ab8c0b6a3a5adad8c774bc08f5
         | 
    
        data/.parlour
    ADDED
    
    
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file. | |
| 3 3 |  | 
| 4 4 | 
             
            The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
         | 
| 5 5 |  | 
| 6 | 
            +
            ## [4.0.0] - 2020-05-23
         | 
| 7 | 
            +
            ### Added
         | 
| 8 | 
            +
            - Parlour now defaults to loading the current project when running its command
         | 
| 9 | 
            +
              line tool, allowing it to be used as a "`sig` extractor" when run without
         | 
| 10 | 
            +
              plugins! **Breaking if you invoke Parlour from its command line tool** - to
         | 
| 11 | 
            +
              revert to the old behaviour of having nothing loaded into the root namespace
         | 
| 12 | 
            +
              initially, add `parser: false` to your `.parlour` file.
         | 
| 13 | 
            +
            - Generating constants in an eigenclass context (`class << self`) is now
         | 
| 14 | 
            +
              supported.
         | 
| 15 | 
            +
             | 
| 6 16 | 
             
            ## [3.0.0] - 2020-05-15
         | 
| 7 17 | 
             
            ### Added
         | 
| 8 18 | 
             
            - `T::Struct` classes can now be generated and parsed.
         | 
    
        data/README.md
    CHANGED
    
    | @@ -13,7 +13,7 @@ key parts: | |
| 13 13 | 
             
                RBIs for the same codebase. These are combined automatically as much as
         | 
| 14 14 | 
             
                possible, but any other conflicts can be resolved manually through prompts.
         | 
| 15 15 |  | 
| 16 | 
            -
              - The parser, which can read an RBI and convert it back into a tree of | 
| 16 | 
            +
              - The parser, which can read an RBI and convert it back into a tree of
         | 
| 17 17 | 
             
                generator objects.
         | 
| 18 18 |  | 
| 19 19 | 
             
            ## Why should I use this?
         | 
| @@ -26,7 +26,10 @@ key parts: | |
| 26 26 | 
             
                RBI output file.
         | 
| 27 27 |  | 
| 28 28 | 
             
              - You can **effortlessly build tools which need to access types within an RBI**;
         | 
| 29 | 
            -
                no need to write your own parser! | 
| 29 | 
            +
                no need to write your own parser!
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              - You can **generate RBI to ship with your gem** for consuming projects to use
         | 
| 32 | 
            +
                ([see "RBIs within gems" in Sorbet's docs](https://sorbet.org/docs/rbi#rbis-within-gems)).
         | 
| 30 33 |  | 
| 31 34 | 
             
            Please [**read the wiki**](https://github.com/AaronC81/parlour/wiki) to get
         | 
| 32 35 | 
             
            started!
         | 
| @@ -174,6 +177,29 @@ Parlour::TypeLoader.load_project('root/of/the/project') | |
| 174 177 | 
             
            The structure of the returned object trees is identical to those you would
         | 
| 175 178 | 
             
            create when generating an RBI, built of instances of `RbiObject` subclasses.
         | 
| 176 179 |  | 
| 180 | 
            +
            ## Generating RBI for a Gem
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            Include `parlour` as a development_dependency in your `.gemspec`:
         | 
| 183 | 
            +
             | 
| 184 | 
            +
            ```ruby
         | 
| 185 | 
            +
            spec.add_development_dependency 'parlour'
         | 
| 186 | 
            +
            ```
         | 
| 187 | 
            +
             | 
| 188 | 
            +
            Run Parlour from the command line:
         | 
| 189 | 
            +
             | 
| 190 | 
            +
            ```ruby
         | 
| 191 | 
            +
            bundle exec parlour
         | 
| 192 | 
            +
            ```
         | 
| 193 | 
            +
             | 
| 194 | 
            +
            Parlour is configured to use sane defaults assuming a standard gem structure
         | 
| 195 | 
            +
            to generate an RBI that Sorbet will automatically find when your gem is included
         | 
| 196 | 
            +
            as a dependency. If you require more advanced configuration you can add a
         | 
| 197 | 
            +
            `.parlour` YAML file in the root of your project (see this project's `.parlour`
         | 
| 198 | 
            +
            file as an example).
         | 
| 199 | 
            +
             | 
| 200 | 
            +
            To disable the parsing step entire and just run plugins you can set `parser: false`
         | 
| 201 | 
            +
            in your `.parlour` file.
         | 
| 202 | 
            +
             | 
| 177 203 | 
             
            ## Parlour Plugins
         | 
| 178 204 |  | 
| 179 205 | 
             
            _Have you written an awesome Parlour plugin? Please submit a PR to add it to this list!_
         | 
    
        data/exe/parlour
    CHANGED
    
    | @@ -16,15 +16,42 @@ command :run do |c| | |
| 16 16 | 
             
              c.description = 'Generates an RBI file from your .parlour file'
         | 
| 17 17 |  | 
| 18 18 | 
             
              c.action do |args, options|
         | 
| 19 | 
            -
                 | 
| 19 | 
            +
                working_dir = Dir.pwd
         | 
| 20 | 
            +
                config_filename = File.join(working_dir, '.parlour')
         | 
| 20 21 |  | 
| 21 | 
            -
                 | 
| 22 | 
            +
                if File.exists?(config_filename)
         | 
| 23 | 
            +
                  configuration = keys_to_symbols(YAML.load_file(config_filename))
         | 
| 24 | 
            +
                else
         | 
| 25 | 
            +
                  configuration = {}
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                # Output default
         | 
| 29 | 
            +
                configuration[:output_file] ||= "rbi/#{File.basename(working_dir)}.rbi"
         | 
| 22 30 |  | 
| 23 31 | 
             
                # Style defaults
         | 
| 24 32 | 
             
                configuration[:style] ||= {}
         | 
| 25 33 | 
             
                configuration[:style][:tab_size] ||= 2
         | 
| 26 34 | 
             
                configuration[:style][:break_params] ||= 4
         | 
| 27 35 |  | 
| 36 | 
            +
                # Parser defaults, set explicitly to false to not run parser
         | 
| 37 | 
            +
                if configuration[:parser] != false
         | 
| 38 | 
            +
                  configuration[:parser] ||= {}
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  # Input/Output defaults
         | 
| 41 | 
            +
                  configuration[:parser][:root] ||= '.'
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  # Included/Excluded path defaults
         | 
| 44 | 
            +
                  configuration[:parser][:included_paths] ||= ['lib']
         | 
| 45 | 
            +
                  configuration[:parser][:excluded_paths] ||= ['sorbet', 'spec']
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                  # Defaults can be overridden but we always want to exclude the output file
         | 
| 48 | 
            +
                  configuration[:parser][:excluded_paths] << configuration[:output_file]
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                # Included/Excluded module defaults
         | 
| 52 | 
            +
                configuration[:included_modules] ||= []
         | 
| 53 | 
            +
                configuration[:excluded_modules] ||= []
         | 
| 54 | 
            +
             | 
| 28 55 | 
             
                # Require defaults
         | 
| 29 56 | 
             
                configuration[:requires] ||= []
         | 
| 30 57 | 
             
                configuration[:relative_requires] ||= []
         | 
| @@ -53,6 +80,15 @@ command :run do |c| | |
| 53 80 | 
             
                  break_params: configuration[:style][:break_params],
         | 
| 54 81 | 
             
                  tab_size: configuration[:style][:tab_size]
         | 
| 55 82 | 
             
                )
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                if configuration[:parser]
         | 
| 85 | 
            +
                  Parlour::TypeLoader.load_project(
         | 
| 86 | 
            +
                    configuration[:parser][:root],
         | 
| 87 | 
            +
                    inclusions: configuration[:parser][:included_paths],
         | 
| 88 | 
            +
                    exclusions: configuration[:parser][:excluded_paths],
         | 
| 89 | 
            +
                    generator: gen,
         | 
| 90 | 
            +
                  )
         | 
| 91 | 
            +
                end
         | 
| 56 92 | 
             
                Parlour::Plugin.run_plugins(plugin_instances, gen)
         | 
| 57 93 |  | 
| 58 94 | 
             
                # Run a pass of the conflict resolver
         | 
| @@ -74,6 +110,14 @@ command :run do |c| | |
| 74 110 | 
             
                  choice == 0 ? nil : candidates[choice - 1]
         | 
| 75 111 | 
             
                end
         | 
| 76 112 |  | 
| 113 | 
            +
                if !configuration[:included_modules].empty? || !configuration[:excluded_modules].empty?
         | 
| 114 | 
            +
                  remove_unwanted_modules(
         | 
| 115 | 
            +
                    gen.root,
         | 
| 116 | 
            +
                    included_modules: configuration[:included_modules],
         | 
| 117 | 
            +
                    excluded_modules: configuration[:excluded_modules],
         | 
| 118 | 
            +
                  )
         | 
| 119 | 
            +
                end
         | 
| 120 | 
            +
             | 
| 77 121 | 
             
                # Figure out strictness levels
         | 
| 78 122 | 
             
                requested_strictness_levels = plugin_instances.map do |plugin|
         | 
| 79 123 | 
             
                  s = plugin.strictness&.to_s
         | 
| @@ -98,6 +142,7 @@ command :run do |c| | |
| 98 142 | 
             
                end
         | 
| 99 143 |  | 
| 100 144 | 
             
                # Write the final RBI
         | 
| 145 | 
            +
                FileUtils.mkdir_p(File.dirname(configuration[:output_file]))
         | 
| 101 146 | 
             
                File.write(configuration[:output_file], gen.rbi(strictness))
         | 
| 102 147 | 
             
              end
         | 
| 103 148 | 
             
            end
         | 
| @@ -122,3 +167,24 @@ def keys_to_symbols(hash) | |
| 122 167 | 
             
                ]
         | 
| 123 168 | 
             
              end.to_h
         | 
| 124 169 | 
             
            end
         | 
| 170 | 
            +
             | 
| 171 | 
            +
            def remove_unwanted_modules(root, included_modules:, excluded_modules:, prefix: nil)
         | 
| 172 | 
            +
              root.children.select! do |child|
         | 
| 173 | 
            +
                module_name = "#{prefix}#{child.name}"
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                if child.respond_to?(:children)
         | 
| 176 | 
            +
                  remove_unwanted_modules(
         | 
| 177 | 
            +
                    child,
         | 
| 178 | 
            +
                    included_modules: included_modules,
         | 
| 179 | 
            +
                    excluded_modules: excluded_modules,
         | 
| 180 | 
            +
                    prefix: "#{module_name}::",
         | 
| 181 | 
            +
                  )
         | 
| 182 | 
            +
                  has_included_children = !child.children.empty?
         | 
| 183 | 
            +
                end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                included = included_modules.empty? ? true : included_modules.any? { |m| module_name.start_with?(m) }
         | 
| 186 | 
            +
                excluded = excluded_modules.empty? ? false : excluded_modules.any? { |m| module_name.start_with?(m) }
         | 
| 187 | 
            +
             | 
| 188 | 
            +
                (included || has_included_children) && !excluded
         | 
| 189 | 
            +
              end
         | 
| 190 | 
            +
            end
         | 
| @@ -6,17 +6,12 @@ module Parlour | |
| 6 6 | 
             
                def detached!
         | 
| 7 7 | 
             
                  raise "cannot call methods on a detached RBI generator"
         | 
| 8 8 | 
             
                end
         | 
| 9 | 
            -
             | 
| 9 | 
            +
             | 
| 10 10 | 
             
                sig { override.returns(Options) }
         | 
| 11 11 | 
             
                def options
         | 
| 12 12 | 
             
                  detached!
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 | 
            -
                sig { override.returns(Namespace) }
         | 
| 16 | 
            -
                def root
         | 
| 17 | 
            -
                  detached!
         | 
| 18 | 
            -
                end
         | 
| 19 | 
            -
             | 
| 20 15 | 
             
                sig { override.returns(T.nilable(Plugin)) }
         | 
| 21 16 | 
             
                def current_plugin
         | 
| 22 17 | 
             
                  nil
         | 
    
        data/lib/parlour/plugin.rb
    CHANGED
    
    
| @@ -8,6 +8,7 @@ module Parlour | |
| 8 8 | 
             
                      generator: RbiGenerator,
         | 
| 9 9 | 
             
                      name: String,
         | 
| 10 10 | 
             
                      value: String,
         | 
| 11 | 
            +
                      eigen_constant: T::Boolean,
         | 
| 11 12 | 
             
                      block: T.nilable(T.proc.params(x: Constant).void)
         | 
| 12 13 | 
             
                    ).void
         | 
| 13 14 | 
             
                  end
         | 
| @@ -15,9 +16,12 @@ module Parlour | |
| 15 16 | 
             
                  #
         | 
| 16 17 | 
             
                  # @param name [String] The name of the constant.
         | 
| 17 18 | 
             
                  # @param value [String] The value of the constant, as a Ruby code string.
         | 
| 18 | 
            -
                   | 
| 19 | 
            +
                  # @param eigen_constant [Boolean] Whether this constant is defined on the
         | 
| 20 | 
            +
                  #   eigenclass of the current namespace.
         | 
| 21 | 
            +
                  def initialize(generator, name: '', value: '', eigen_constant: false, &block)
         | 
| 19 22 | 
             
                    super(generator, name)
         | 
| 20 23 | 
             
                    @value = value
         | 
| 24 | 
            +
                    @eigen_constant = eigen_constant
         | 
| 21 25 | 
             
                    yield_self(&block) if block
         | 
| 22 26 | 
             
                  end
         | 
| 23 27 |  | 
| @@ -25,6 +29,10 @@ module Parlour | |
| 25 29 | 
             
                  sig { returns(String) }
         | 
| 26 30 | 
             
                  attr_reader :value
         | 
| 27 31 |  | 
| 32 | 
            +
                  # @return [Boolean] Whether this constant is defined on the eigenclass
         | 
| 33 | 
            +
                  #   of the current namespace.
         | 
| 34 | 
            +
                  attr_reader :eigen_constant
         | 
| 35 | 
            +
             | 
| 28 36 | 
             
                  sig { params(other: Object).returns(T::Boolean) }
         | 
| 29 37 | 
             
                  # Returns true if this instance is equal to another extend.
         | 
| 30 38 | 
             
                  #
         | 
| @@ -32,7 +40,8 @@ module Parlour | |
| 32 40 | 
             
                  #   subclass of it), this will always return false.
         | 
| 33 41 | 
             
                  # @return [Boolean]
         | 
| 34 42 | 
             
                  def ==(other)
         | 
| 35 | 
            -
                    Constant === other && name == other.name && value == other.value
         | 
| 43 | 
            +
                    Constant === other && name == other.name && value == other.value \
         | 
| 44 | 
            +
                      && eigen_constant == other.eigen_constant
         | 
| 36 45 | 
             
                  end
         | 
| 37 46 |  | 
| 38 47 | 
             
                  sig do
         | 
| @@ -527,7 +527,7 @@ module Parlour | |
| 527 527 | 
             
                    returned_includables
         | 
| 528 528 | 
             
                  end
         | 
| 529 529 |  | 
| 530 | 
            -
                  sig { params(name: String, value: String, block: T.nilable(T.proc.params(x: Constant).void)).returns(Constant) }
         | 
| 530 | 
            +
                  sig { params(name: String, value: String, eigen_constant: T::Boolean, block: T.nilable(T.proc.params(x: Constant).void)).returns(Constant) }
         | 
| 531 531 | 
             
                  # Adds a new constant definition to this namespace.
         | 
| 532 532 | 
             
                  #
         | 
| 533 533 | 
             
                  # @example Add an +Elem+ constant to the class.
         | 
| @@ -535,13 +535,16 @@ module Parlour | |
| 535 535 | 
             
                  #
         | 
| 536 536 | 
             
                  # @param name [String] The name of the constant.
         | 
| 537 537 | 
             
                  # @param value [String] The value of the constant, as a Ruby code string.
         | 
| 538 | 
            +
                  # @param eigen_constant [Boolean] Whether this constant is defined on the
         | 
| 539 | 
            +
                  #   eigenclass of the current namespace.
         | 
| 538 540 | 
             
                  # @param block A block which the new instance yields itself to.
         | 
| 539 541 | 
             
                  # @return [RbiGenerator::Constant]
         | 
| 540 | 
            -
                  def create_constant(name, value:, &block)
         | 
| 542 | 
            +
                  def create_constant(name, value:, eigen_constant: false, &block)
         | 
| 541 543 | 
             
                    new_constant = RbiGenerator::Constant.new(
         | 
| 542 544 | 
             
                      generator,
         | 
| 543 545 | 
             
                      name: name,
         | 
| 544 546 | 
             
                      value: value,
         | 
| 547 | 
            +
                      eigen_constant: eigen_constant,
         | 
| 545 548 | 
             
                      &block
         | 
| 546 549 | 
             
                    )
         | 
| 547 550 | 
             
                    move_next_comments(new_constant)
         | 
| @@ -631,14 +634,19 @@ module Parlour | |
| 631 634 |  | 
| 632 635 | 
             
                    result += [options.indented(indent_level, 'final!'), ''] if final
         | 
| 633 636 |  | 
| 634 | 
            -
                     | 
| 637 | 
            +
                    # Split away the eigen constants; these need to be put in a
         | 
| 638 | 
            +
                    # "class << self" block later
         | 
| 639 | 
            +
                    eigen_constants, non_eigen_constants = constants.partition(&:eigen_constant)
         | 
| 640 | 
            +
                    eigen_constants.sort_by!(&:name) if options.sort_namespaces
         | 
| 641 | 
            +
             | 
| 642 | 
            +
                    if includes.any? || extends.any? || non_eigen_constants.any?
         | 
| 635 643 | 
             
                      result += (options.sort_namespaces ? includes.sort_by(&:name) : includes)
         | 
| 636 644 | 
             
                        .flat_map { |x| x.generate_rbi(indent_level, options) }
         | 
| 637 645 | 
             
                        .reject { |x| x.strip == '' }
         | 
| 638 646 | 
             
                      result += (options.sort_namespaces ? extends.sort_by(&:name) : extends)
         | 
| 639 647 | 
             
                        .flat_map { |x| x.generate_rbi(indent_level, options) }
         | 
| 640 648 | 
             
                        .reject { |x| x.strip == '' }
         | 
| 641 | 
            -
                      result += (options.sort_namespaces ?  | 
| 649 | 
            +
                      result += (options.sort_namespaces ? non_eigen_constants.sort_by(&:name) : non_eigen_constants)
         | 
| 642 650 | 
             
                        .flat_map { |x| x.generate_rbi(indent_level, options) }
         | 
| 643 651 | 
             
                        .reject { |x| x.strip == '' }
         | 
| 644 652 | 
             
                      result << ""
         | 
| @@ -658,14 +666,29 @@ module Parlour | |
| 658 666 | 
             
                      child.is_a?(Attribute) && child.class_attribute
         | 
| 659 667 | 
             
                    end
         | 
| 660 668 |  | 
| 661 | 
            -
                     | 
| 662 | 
            -
             | 
| 669 | 
            +
                    # Handle the "class << self block"
         | 
| 670 | 
            +
                    result << options.indented(indent_level, 'class << self') \
         | 
| 671 | 
            +
                      if class_attributes.any? || eigen_constants.any?
         | 
| 672 | 
            +
             | 
| 673 | 
            +
                    if eigen_constants.any?
         | 
| 674 | 
            +
                      first, *rest = eigen_constants
         | 
| 675 | 
            +
                      result += T.must(first).generate_rbi(indent_level + 1, options) + T.must(rest)
         | 
| 676 | 
            +
                        .map { |obj| obj.generate_rbi(indent_level + 1, options) }
         | 
| 677 | 
            +
                        .map { |lines| [""] + lines }
         | 
| 678 | 
            +
                        .flatten
         | 
| 679 | 
            +
                    end
         | 
| 680 | 
            +
             | 
| 681 | 
            +
                    result << '' if eigen_constants.any? && class_attributes.any?
         | 
| 663 682 |  | 
| 683 | 
            +
                    if class_attributes.any?
         | 
| 664 684 | 
             
                      first, *rest = class_attributes
         | 
| 665 685 | 
             
                      result += T.must(first).generate_rbi(indent_level + 1, options) + T.must(rest)
         | 
| 666 686 | 
             
                        .map { |obj| obj.generate_rbi(indent_level + 1, options) }
         | 
| 667 687 | 
             
                        .map { |lines| [""] + lines }
         | 
| 668 688 | 
             
                        .flatten
         | 
| 689 | 
            +
                    end
         | 
| 690 | 
            +
             | 
| 691 | 
            +
                    if class_attributes.any? || eigen_constants.any?
         | 
| 669 692 | 
             
                      result << options.indented(indent_level, 'end')
         | 
| 670 693 | 
             
                      result << ''
         | 
| 671 694 | 
             
                    end
         | 
| @@ -42,7 +42,7 @@ module Parlour | |
| 42 42 |  | 
| 43 43 | 
             
                    @kind = :keyword if kind == :normal && name.end_with?(':')
         | 
| 44 44 |  | 
| 45 | 
            -
                    @type = type
         | 
| 45 | 
            +
                    @type = type || 'T.untyped'
         | 
| 46 46 | 
             
                    @default = default
         | 
| 47 47 | 
             
                  end
         | 
| 48 48 |  | 
| @@ -80,10 +80,10 @@ module Parlour | |
| 80 80 | 
             
                    T.must(name[prefix.length..-1])
         | 
| 81 81 | 
             
                  end
         | 
| 82 82 |  | 
| 83 | 
            -
                  sig { returns( | 
| 83 | 
            +
                  sig { returns(String) }
         | 
| 84 84 | 
             
                  # A Sorbet string of this parameter's type, such as +"String"+ or
         | 
| 85 85 | 
             
                  # +"T.untyped"+.
         | 
| 86 | 
            -
                  # @return [String | 
| 86 | 
            +
                  # @return [String]
         | 
| 87 87 | 
             
                  attr_reader :type
         | 
| 88 88 |  | 
| 89 89 | 
             
                  sig { returns(T.nilable(String)) }
         | 
| @@ -118,7 +118,7 @@ module Parlour | |
| 118 118 | 
             
                  #
         | 
| 119 119 | 
             
                  # @return [String]
         | 
| 120 120 | 
             
                  def to_sig_param
         | 
| 121 | 
            -
                    "#{name_without_kind}: #{type | 
| 121 | 
            +
                    "#{name_without_kind}: #{type}"
         | 
| 122 122 | 
             
                  end#
         | 
| 123 123 |  | 
| 124 124 | 
             
                  # A mapping of {kind} values to the characteristic prefixes each kind has.
         | 
    
        data/lib/parlour/type_loader.rb
    CHANGED
    
    | @@ -10,27 +10,34 @@ module Parlour | |
| 10 10 | 
             
                # TODO: make this into a class which stores configuration and passes it to
         | 
| 11 11 | 
             
                # all typeparsers
         | 
| 12 12 |  | 
| 13 | 
            -
                sig { params(source: String, filename: T.nilable(String)).returns(RbiGenerator::Namespace) }
         | 
| 13 | 
            +
                sig { params(source: String, filename: T.nilable(String), generator: T.nilable(RbiGenerator)).returns(RbiGenerator::Namespace) }
         | 
| 14 14 | 
             
                # Converts Ruby source code into a tree of objects.
         | 
| 15 15 | 
             
                #
         | 
| 16 16 | 
             
                # @param [String] source The Ruby source code.
         | 
| 17 17 | 
             
                # @param [String, nil] filename The filename to use when parsing this code.
         | 
| 18 18 | 
             
                #   This may be used in error messages, but is optional.
         | 
| 19 19 | 
             
                # @return [RbiGenerator::Namespace] The root of the object tree.
         | 
| 20 | 
            -
                def self.load_source(source, filename = nil)
         | 
| 21 | 
            -
                  TypeParser.from_source(filename || '(source)', source).parse_all
         | 
| 20 | 
            +
                def self.load_source(source, filename = nil, generator: nil)
         | 
| 21 | 
            +
                  TypeParser.from_source(filename || '(source)', source, generator: generator).parse_all
         | 
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 | 
            -
                sig { params(filename: String).returns(RbiGenerator::Namespace) }
         | 
| 24 | 
            +
                sig { params(filename: String, generator: T.nilable(RbiGenerator)).returns(RbiGenerator::Namespace) }
         | 
| 25 25 | 
             
                # Converts Ruby source code into a tree of objects from a file.
         | 
| 26 26 | 
             
                #
         | 
| 27 27 | 
             
                # @param [String] filename The name of the file to load code from.
         | 
| 28 28 | 
             
                # @return [RbiGenerator::Namespace] The root of the object tree.
         | 
| 29 | 
            -
                def self.load_file(filename)
         | 
| 30 | 
            -
                  load_source(File.read(filename), filename)
         | 
| 29 | 
            +
                def self.load_file(filename, generator: nil)
         | 
| 30 | 
            +
                  load_source(File.read(filename), filename, generator: generator)
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                sig do
         | 
| 34 | 
            +
                  params(
         | 
| 35 | 
            +
                    root: String,
         | 
| 36 | 
            +
                    inclusions: T::Array[String],
         | 
| 37 | 
            +
                    exclusions: T::Array[String],
         | 
| 38 | 
            +
                    generator: T.nilable(RbiGenerator),
         | 
| 39 | 
            +
                  ).returns(RbiGenerator::Namespace)
         | 
| 31 40 | 
             
                end
         | 
| 32 | 
            -
              
         | 
| 33 | 
            -
                sig { params(root: String, exclusions: T::Array[String]).returns(RbiGenerator::Namespace) }
         | 
| 34 41 | 
             
                # Loads an entire Sorbet project using Sorbet's file table, obeying any
         | 
| 35 42 | 
             
                # "typed: ignore" sigils, into a tree of objects.
         | 
| 36 43 | 
             
                #
         | 
| @@ -39,12 +46,15 @@ module Parlour | |
| 39 46 | 
             
                #
         | 
| 40 47 | 
             
                # @param [String] root The root of the project; where the "sorbet" directory
         | 
| 41 48 | 
             
                #   and "Gemfile" are located.
         | 
| 49 | 
            +
                # @param [Array<String>] inclusions A list of files to include when loading
         | 
| 50 | 
            +
                #   the project, relative to the given root.
         | 
| 42 51 | 
             
                # @param [Array<String>] exclusions A list of files to exclude when loading
         | 
| 43 52 | 
             
                #   the project, relative to the given root.
         | 
| 44 53 | 
             
                # @return [RbiGenerator::Namespace] The root of the object tree.
         | 
| 45 | 
            -
                def self.load_project(root, exclusions: [])
         | 
| 54 | 
            +
                def self.load_project(root, inclusions: ['.'], exclusions: [], generator: nil)
         | 
| 55 | 
            +
                  expanded_inclusions = inclusions.map { |i| File.expand_path(i, root) }
         | 
| 46 56 | 
             
                  expanded_exclusions = exclusions.map { |e| File.expand_path(e, root) }
         | 
| 47 | 
            -
             | 
| 57 | 
            +
             | 
| 48 58 | 
             
                  stdin, stdout, stderr, wait_thr = T.unsafe(Open3).popen3(
         | 
| 49 59 | 
             
                    'bundle exec srb tc -p file-table-json',
         | 
| 50 60 | 
             
                    chdir: root
         | 
| @@ -63,14 +73,17 @@ module Parlour | |
| 63 73 | 
             
                    path = File.expand_path(rel_path, root)
         | 
| 64 74 |  | 
| 65 75 | 
             
                    # Skip this file if it was excluded
         | 
| 66 | 
            -
                    next if  | 
| 76 | 
            +
                    next if !expanded_inclusions.any? { |i| path.start_with?(i) } \
         | 
| 77 | 
            +
                      || expanded_exclusions.any? { |e| path.start_with?(e) }
         | 
| 67 78 |  | 
| 68 79 | 
             
                    # There are some entries which are URLs to stdlib
         | 
| 69 80 | 
             
                    next unless File.exist?(path)
         | 
| 70 81 |  | 
| 71 | 
            -
                    namespaces << load_file(path)
         | 
| 82 | 
            +
                    namespaces << load_file(path, generator: generator)
         | 
| 72 83 | 
             
                  end
         | 
| 73 84 |  | 
| 85 | 
            +
                  namespaces.uniq!
         | 
| 86 | 
            +
             | 
| 74 87 | 
             
                  raise 'project is empty' if namespaces.empty?
         | 
| 75 88 |  | 
| 76 89 | 
             
                  first_namespace, *other_namespaces = namespaces
         |