Skip to content

Expose core RBS definition paths as public API - #1029

Open
HoneyryderChuck wants to merge 1 commit into
Shopify:mainfrom
HoneyryderChuck:expose-core-rbs-definition-paths
Open

Expose core RBS definition paths as public API#1029
HoneyryderChuck wants to merge 1 commit into
Shopify:mainfrom
HoneyryderChuck:expose-core-rbs-definition-paths

Conversation

@HoneyryderChuck

Copy link
Copy Markdown
Contributor

Tools that build their own list of paths and index it with index_all instead of index_workspace (RuboCop's AllCops/UseProjectIndex does this, so that its own Include/Exclude configuration governs the index) ended up with a graph that has no definitions for Ruby's core classes. The core definitions come from indexing the rbs gem's core and stdlib signature directories, which only index_workspace did, through the private add_core_rbs_definition_paths.

Add Rubydex::Graph.core_rbs_definition_paths, which returns those paths, so callers can append them to their own list without reaching for a private method. add_core_rbs_definition_paths now delegates to it, keeping a single source of truth as well as the existing semantics: the latest installation of rbs in the system wins, rbs does not have to be part of the bundle and no installation being found is not an error.


@vinistock this is to address what we discussed in #1027; rubocop can't really use graph_workspace as that'd mean indexing the 3rd party gems too; the easiest workaround I got to was to use this method to expose the rbs sigs there, which would be better served as a public API.

Tools that build their own list of paths and index it with `index_all` instead
of `index_workspace` (RuboCop's `AllCops/UseProjectIndex` does this, so that its
own `Include`/`Exclude` configuration governs the index) ended up with a graph
that has no definitions for Ruby's core classes. The core definitions come from
indexing the `rbs` gem's `core` and `stdlib` signature directories, which only
`index_workspace` did, through the private `add_core_rbs_definition_paths`.

Add `Rubydex::Graph.core_rbs_definition_paths`, which returns those paths, so
callers can append them to their own list without reaching for a private
method. `add_core_rbs_definition_paths` now delegates to it, keeping a single
source of truth as well as the existing semantics: the latest installation of
`rbs` in the system wins, `rbs` does not have to be part of the bundle and no
installation being found is not an error.

Fixes Shopify#1027

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@vinistock vinistock left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution. Exposing this method is not a problem, but I want to call attention that performing the analysis in an incomplete graph can have unexpected results and this is not going to fix the problem 100%.

Constants in Ruby are global and can be influenced by any code included in the application, which includes dependencies.

Consider this example:

# rbs definition
class Object; end

# some_gem
class UsefulParentClass
  class Object; end
end

# your code
class MyImplementation < UsefulParentClass
  # This Object reference points to UsefulParentClass::Object and not Object.
  # By not including the full context of the application into the analysis, constants
  # may resolve differently and you might be inaccurate results.
  Object

  # Note that inaccuracies in constant resolution can easily propagate. For example:
  #
  # This class inherits from UsefulParentClass::Object and not Object. By incorrectly
  # understanding its parent class, we resolve every constant reference inside of this
  # namespace against the wrong ancestor chain, which produces more inaccuracies in the
  # analysis.
  class SomeOtherThing < Object
  end
end

Exposing the method you're proposing would make the analysis less incomplete by including the core definitions, but it will still be incomplete and subject to more inaccuracies if you don't take dependencies into account.

This is why in the Rubydex linter included in this gem, we filter diagnostics from dependencies only at the end during presentation and never exclude anything from the analysis as it may impact the understanding of the code.

@HoneyryderChuck

Copy link
Copy Markdown
Contributor Author

@vinistock I understand. When it comes to rubocop though, it really depends on how they'd like the integration to go forward. indexing the 3rd party gems is an opt-in,in which case graph_workspace could be employed. But what you're implying leads me to question whether that opt-in should even be a thing. Perhaps something to take to rubocop team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants