From 6acfa0c54a806da203daf30765c7a99a67066f16 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 30 Aug 2025 09:06:14 -0400 Subject: [PATCH 01/81] RuboCop todo file stability To avoid merge conflicts and contributors having to deal with non-intuitive RuboCop todo changes: * Lock down development versions of RuboCop and plugins so that unrelated PRs aren't affected by newly implemented RuboCop rules. * Exclude rule entirely if more than 5 files violate it today, so that PRs are less likely to cause todo file changes unless they are specifically targeted at cleanup. * Clarify guidance on RuboCop todo file in CI error message. * Fix to hopefully ensure guidance always appears in CI error message. --- .github/workflows/linting.yml | 6 +- .rubocop.yml | 1 - .rubocop_todo.yml | 1588 ++------------------------------- solargraph.gemspec | 13 +- 4 files changed, 98 insertions(+), 1510 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 8abbf51ef..aa22ce22c 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -115,11 +115,13 @@ jobs: - name: Run RuboCop against todo file continue-on-error: true run: | - bundle exec rubocop --auto-gen-config --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp + cmd="bundle exec rubocop --auto-gen-config --exclude-limit=5 --no-offense-counts --no-auto-gen-timestampxb*com" + ${cmd:?} + set +e if [ -n "$(git status --porcelain)" ] then git status --porcelain git diff -u . - >&2 echo "Please fix deltas if bad or run 'bundle exec rubocop --auto-gen-config --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp' and push up changes if good" + >&2 echo "Please address any new issues, then run '${cmd:?}' and push up any improvements" exit 1 fi diff --git a/.rubocop.yml b/.rubocop.yml index a73324db2..c7643c3c6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -34,7 +34,6 @@ Metrics/ParameterLists: Max: 7 CountKeywordArgs: false - # we tend to use @@ and the risk doesn't seem high Style/ClassVars: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index f3f0069f3..bf6b2272a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,5 +1,5 @@ # This configuration was generated by -# `rubocop --auto-gen-config --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` +# `rubocop --auto-gen-config --exclude-limit 5 --no-offense-counts --no-auto-gen-timestamp` # using RuboCop version 1.79.2. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. @@ -83,23 +83,7 @@ Layout/CommentIndentation: # This cop supports safe autocorrection (--autocorrect). Layout/ElseAlignment: - Exclude: - - 'lib/solargraph.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/diagnostics/rubocop.rb' - - 'lib/solargraph/language_server/message/extended/check_gem_version.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/block_node.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/namespace.rb' - - 'lib/solargraph/rbs_map.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker/rules.rb' - - 'lib/solargraph/yard_map/mapper.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines. @@ -111,18 +95,7 @@ Layout/EmptyLineBetweenDefs: # This cop supports safe autocorrection (--autocorrect). Layout/EmptyLines: - Exclude: - - 'lib/solargraph/bench.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/language_server/message/extended/check_gem_version.rb' - - 'lib/solargraph/language_server/message/initialize.rb' - - 'lib/solargraph/pin/delegated_method.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'spec/complex_type_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/pin/symbol_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. @@ -142,23 +115,7 @@ Layout/EmptyLinesAroundModuleBody: # Configuration parameters: EnforcedStyleAlignWith, Severity. # SupportedStylesAlignWith: keyword, variable, start_of_line Layout/EndAlignment: - Exclude: - - 'lib/solargraph.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/diagnostics/rubocop.rb' - - 'lib/solargraph/language_server/message/extended/check_gem_version.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/block_node.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/namespace.rb' - - 'lib/solargraph/rbs_map.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker/rules.rb' - - 'lib/solargraph/yard_map/mapper.rb' + Enabled: false # Configuration parameters: EnforcedStyle. # SupportedStyles: native, lf, crlf @@ -172,13 +129,7 @@ Layout/EndOfLine: # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. Layout/ExtraSpacing: - Exclude: - - 'lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb' - - 'lib/solargraph/pin/closure.rb' - - 'lib/solargraph/pin/local_variable.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/type_checker.rb' - - 'spec/spec_helper.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, IndentationWidth. @@ -203,22 +154,7 @@ Layout/FirstArrayElementIndentation: # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: special_inside_parentheses, consistent, align_braces Layout/FirstHashElementIndentation: - Exclude: - - 'lib/solargraph/language_server/message/extended/check_gem_version.rb' - - 'lib/solargraph/language_server/message/extended/document_gems.rb' - - 'lib/solargraph/language_server/message/text_document/completion.rb' - - 'lib/solargraph/language_server/message/text_document/rename.rb' - - 'lib/solargraph/language_server/message/text_document/signature_help.rb' - - 'lib/solargraph/pin/base_variable.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/initialize_spec.rb' - - 'spec/language_server/message/text_document/definition_spec.rb' - - 'spec/language_server/message/text_document/formatting_spec.rb' - - 'spec/language_server/message/text_document/hover_spec.rb' - - 'spec/language_server/message/text_document/rename_spec.rb' - - 'spec/language_server/message/text_document/type_definition_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. @@ -239,27 +175,7 @@ Layout/HeredocIndentation: # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: Width, AllowedPatterns. Layout/IndentationWidth: - Exclude: - - 'lib/solargraph.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/diagnostics/rubocop.rb' - - 'lib/solargraph/language_server/message/extended/check_gem_version.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/block_node.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/namespace.rb' - - 'lib/solargraph/rbs_map.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' - - 'lib/solargraph/type_checker/rules.rb' - - 'lib/solargraph/yard_map/mapper.rb' - - 'spec/api_map/config_spec.rb' - - 'spec/shell_spec.rb' - - 'spec/source_map/mapper_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment, AllowRBSInlineAnnotation, AllowSteepAnnotation. @@ -289,14 +205,7 @@ Layout/MultilineMethodCallBraceLayout: # Configuration parameters: EnforcedStyle, IndentationWidth. # SupportedStyles: aligned, indented, indented_relative_to_receiver Layout/MultilineMethodCallIndentation: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/diagnostics/type_check.rb' - - 'lib/solargraph/language_server/message/completion_item/resolve.rb' - - 'lib/solargraph/language_server/message/text_document/hover.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/pin/search.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, IndentationWidth. @@ -316,13 +225,7 @@ Layout/SpaceAfterComma: # Configuration parameters: EnforcedStyle. # SupportedStyles: space, no_space Layout/SpaceAroundEqualsInParameterDefault: - Exclude: - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/base_variable.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/closure.rb' - - 'lib/solargraph/pin/local_variable.rb' - - 'lib/solargraph/pin/parameter.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Layout/SpaceAroundKeyword: @@ -334,56 +237,14 @@ Layout/SpaceAroundKeyword: # SupportedStylesForExponentOperator: space, no_space # SupportedStylesForRationalLiterals: space, no_space Layout/SpaceAroundOperators: - Exclude: - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/pin/local_variable.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/change.rb' - - 'lib/solargraph/source/cursor.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/workspace/config.rb' - - 'spec/library_spec.rb' - - 'spec/yard_map/mapper_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. # SupportedStyles: space, no_space # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceBeforeBlockBraces: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/diagnostics/rubocop.rb' - - 'lib/solargraph/diagnostics/update_errors.rb' - - 'lib/solargraph/language_server/host.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/and_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/if_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/chain/class_variable.rb' - - 'lib/solargraph/source/chain/constant.rb' - - 'lib/solargraph/source/chain/global_variable.rb' - - 'lib/solargraph/source/chain/instance_variable.rb' - - 'lib/solargraph/source/chain/variable.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/workspace/config.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/library_spec.rb' - - 'spec/pin/constant_spec.rb' - - 'spec/pin/instance_variable_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Layout/SpaceBeforeComma: @@ -395,28 +256,7 @@ Layout/SpaceBeforeComma: # SupportedStyles: space, no_space # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceInsideBlockBraces: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/diagnostics/update_errors.rb' - - 'lib/solargraph/language_server/host.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/and_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/if_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/chain/class_variable.rb' - - 'lib/solargraph/source/chain/global_variable.rb' - - 'lib/solargraph/source/chain/instance_variable.rb' - - 'lib/solargraph/source/chain/variable.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/library_spec.rb' - - 'spec/pin/constant_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. @@ -455,13 +295,7 @@ Lint/AmbiguousBlockAssociation: # This cop supports safe autocorrection (--autocorrect). Lint/AmbiguousOperator: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/language_server/message/workspace/did_change_watched_files.rb' - - 'lib/solargraph/parser/parser_gem/class_methods.rb' - - 'lib/solargraph/pin/constant.rb' - - 'lib/solargraph/pin/method.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Lint/AmbiguousOperatorPrecedence: @@ -472,15 +306,7 @@ Lint/AmbiguousOperatorPrecedence: # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: RequireParenthesesForMethodChains. Lint/AmbiguousRange: - Exclude: - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/change.rb' - - 'lib/solargraph/source/cursor.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'spec/library_spec.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowSafeAssignment. @@ -514,14 +340,7 @@ Lint/DuplicateBranch: - 'lib/solargraph/rbs_map/conversions.rb' Lint/DuplicateMethods: - Exclude: - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/location.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/signature.rb' - - 'lib/solargraph/rbs_map.rb' - - 'lib/solargraph/rbs_map/core_map.rb' - - 'lib/solargraph/source/chain/link.rb' + Enabled: false # Configuration parameters: AllowComments, AllowEmptyLambdas. Lint/EmptyBlock: @@ -530,13 +349,7 @@ Lint/EmptyBlock: # Configuration parameters: AllowComments. Lint/EmptyClass: - Exclude: - - 'spec/fixtures/rubocop-validation-error/app.rb' - - 'spec/fixtures/workspace-with-gemfile/lib/other.rb' - - 'spec/fixtures/workspace/lib/other.rb' - - 'spec/fixtures/workspace/lib/something.rb' - - 'spec/fixtures/workspace_folders/folder1/app.rb' - - 'spec/fixtures/workspace_folders/folder2/app.rb' + Enabled: false # Configuration parameters: AllowComments. Lint/EmptyFile: @@ -635,31 +448,7 @@ Lint/UnusedBlockArgument: # Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions. # NotImplementedExceptions: NotImplementedError Lint/UnusedMethodArgument: - Exclude: - - 'lib/solargraph.rb' - - 'lib/solargraph/complex_type/type_methods.rb' - - 'lib/solargraph/convention/base.rb' - - 'lib/solargraph/diagnostics/base.rb' - - 'lib/solargraph/diagnostics/update_errors.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/pin/namespace.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/chain.rb' - - 'lib/solargraph/source/chain/block_symbol.rb' - - 'lib/solargraph/source/chain/block_variable.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/chain/class_variable.rb' - - 'lib/solargraph/source/chain/constant.rb' - - 'lib/solargraph/source/chain/global_variable.rb' - - 'lib/solargraph/source/chain/hash.rb' - - 'lib/solargraph/source/chain/head.rb' - - 'lib/solargraph/source/chain/instance_variable.rb' - - 'lib/solargraph/source/chain/link.rb' - - 'lib/solargraph/source/chain/literal.rb' - - 'lib/solargraph/source/chain/variable.rb' - - 'lib/solargraph/source/chain/z_super.rb' - - 'spec/doc_map_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AutoCorrect, ContextCreatingMethods, MethodCreatingMethods. @@ -670,30 +459,7 @@ Lint/UselessAccessModifier: # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AutoCorrect. Lint/UselessAssignment: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/language_server/message/extended/check_gem_version.rb' - - 'lib/solargraph/language_server/message/extended/document_gems.rb' - - 'lib/solargraph/language_server/message/text_document/completion.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' - - 'spec/fixtures/long_squiggly_heredoc.rb' - - 'spec/fixtures/rubocop-unused-variable-error/app.rb' - - 'spec/fixtures/unicode.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/library_spec.rb' - - 'spec/pin/namespace_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source_map/mapper_spec.rb' + Enabled: false Lint/UselessConstantScoping: Exclude: @@ -707,43 +473,16 @@ Lint/UselessMethodDefinition: # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max. Metrics/AbcSize: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/source_to_yard.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/language_server/host.rb' - - 'lib/solargraph/language_server/message/initialize.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false -# Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. +# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns, inherit_mode. # AllowedMethods: refine Metrics/BlockLength: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/source_to_yard.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/convention/struct_definition.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/type_checker.rb' + Max: 54 -# Configuration parameters: CountBlocks, CountModifierForms, Max. +# Configuration parameters: CountBlocks, CountModifierForms. Metrics/BlockNesting: - Exclude: - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/type_checker.rb' + Max: 5 # Configuration parameters: CountComments, Max, CountAsOne. Metrics/ClassLength: @@ -755,33 +494,15 @@ Metrics/ClassLength: # Configuration parameters: AllowedMethods, AllowedPatterns, Max. Metrics/CyclomaticComplexity: - Exclude: - - 'lib/solargraph/api_map/source_to_yard.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false # Configuration parameters: CountComments, Max, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/convention/struct_definition.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source_map/mapper.rb' + Enabled: false -# Configuration parameters: CountComments, Max, CountAsOne. +# Configuration parameters: CountComments, CountAsOne. Metrics/ModuleLength: - Exclude: - - 'lib/solargraph/complex_type/type_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/pin_cache.rb' + Max: 169 # Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters. Metrics/ParameterLists: @@ -794,13 +515,7 @@ Metrics/ParameterLists: # Configuration parameters: AllowedMethods, AllowedPatterns, Max. Metrics/PerceivedComplexity: - Exclude: - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false Naming/AccessorMethodName: Exclude: @@ -823,41 +538,18 @@ Naming/HeredocDelimiterNaming: # Configuration parameters: EnforcedStyleForLeadingUnderscores. # SupportedStylesForLeadingUnderscores: disallowed, required, optional Naming/MemoizedInstanceVariableName: - Exclude: - - 'lib/solargraph/complex_type/type_methods.rb' - - 'lib/solargraph/convention/gemfile.rb' - - 'lib/solargraph/convention/gemspec.rb' - - 'lib/solargraph/convention/rakefile.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/rbs_map.rb' - - 'lib/solargraph/workspace.rb' + Enabled: false # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to Naming/MethodParameterName: - Exclude: - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/range.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/yard_map/mapper/to_method.rb' - - 'lib/solargraph/yard_map/to_method.rb' + Enabled: false # Configuration parameters: Mode, AllowedMethods, AllowedPatterns, AllowBangMethods, WaywardPredicates. # AllowedMethods: call # WaywardPredicates: nonzero? Naming/PredicateMethod: - Exclude: - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/convention/data_definition.rb' - - 'lib/solargraph/convention/struct_definition.rb' - - 'lib/solargraph/language_server/progress.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/node_processor/base.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/local_variable.rb' - - 'lib/solargraph/workspace.rb' + Enabled: false # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs. # NamePrefix: is_, has_, have_, does_ @@ -912,16 +604,7 @@ RSpec/BeforeAfterAll: # Configuration parameters: Prefixes, AllowedPatterns. # Prefixes: when, with, without RSpec/ContextWording: - Exclude: - - 'spec/complex_type_spec.rb' - - 'spec/library_spec.rb' - - 'spec/pin/method_spec.rb' - - 'spec/pin/parameter_spec.rb' - - 'spec/pin/symbol_spec.rb' - - 'spec/type_checker/levels/normal_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/type_checker/levels/strong_spec.rb' - - 'spec/type_checker/levels/typed_spec.rb' + Enabled: false # Configuration parameters: IgnoredMetadata. RSpec/DescribeClass: @@ -938,81 +621,11 @@ RSpec/DescribeClass: # Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants. # SupportedStyles: described_class, explicit RSpec/DescribedClass: - Exclude: - - 'spec/api_map/cache_spec.rb' - - 'spec/api_map/source_to_yard_spec.rb' - - 'spec/api_map/store_spec.rb' - - 'spec/api_map_spec.rb' - - 'spec/diagnostics/base_spec.rb' - - 'spec/diagnostics/require_not_found_spec.rb' - - 'spec/diagnostics/rubocop_helpers_spec.rb' - - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/diagnostics/type_check_spec.rb' - - 'spec/diagnostics/update_errors_spec.rb' - - 'spec/diagnostics_spec.rb' - - 'spec/doc_map_spec.rb' - - 'spec/gem_pins_spec.rb' - - 'spec/language_server/host/diagnoser_spec.rb' - - 'spec/language_server/host/dispatch_spec.rb' - - 'spec/language_server/host/message_worker_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/message/initialize_spec.rb' - - 'spec/language_server/message/text_document/definition_spec.rb' - - 'spec/language_server/message/text_document/formatting_spec.rb' - - 'spec/language_server/message/text_document/hover_spec.rb' - - 'spec/language_server/message/text_document/rename_spec.rb' - - 'spec/language_server/message/text_document/type_definition_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' - - 'spec/language_server/message_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/language_server/transport/data_reader_spec.rb' - - 'spec/language_server/uri_helpers_spec.rb' - - 'spec/library_spec.rb' - - 'spec/logging_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/parser/node_processor_spec.rb' - - 'spec/parser_spec.rb' - - 'spec/pin/base_spec.rb' - - 'spec/pin/delegated_method_spec.rb' - - 'spec/pin/instance_variable_spec.rb' - - 'spec/pin/keyword_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/pin/method_spec.rb' - - 'spec/pin/namespace_spec.rb' - - 'spec/pin/parameter_spec.rb' - - 'spec/pin/search_spec.rb' - - 'spec/pin/symbol_spec.rb' - - 'spec/position_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/rbs_map/stdlib_map_spec.rb' - - 'spec/rbs_map_spec.rb' - - 'spec/source/chain/class_variable_spec.rb' - - 'spec/source/chain/global_variable_spec.rb' - - 'spec/source/chain/head_spec.rb' - - 'spec/source/chain/instance_variable_spec.rb' - - 'spec/source/chain/z_super_spec.rb' - - 'spec/source/change_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source/updater_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' - - 'spec/type_checker/checks_spec.rb' - - 'spec/type_checker/levels/normal_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/type_checker/rules_spec.rb' - - 'spec/type_checker_spec.rb' - - 'spec/workspace/config_spec.rb' - - 'spec/workspace_spec.rb' - - 'spec/yard_map/mapper/to_method_spec.rb' - - 'spec/yard_map/mapper_spec.rb' - -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AutoCorrect. -RSpec/EmptyExampleGroup: + Enabled: false + +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: AutoCorrect. +RSpec/EmptyExampleGroup: Exclude: - 'spec/convention_spec.rb' @@ -1023,33 +636,7 @@ RSpec/EmptyLineAfterFinalLet: # Configuration parameters: Max, CountAsOne. RSpec/ExampleLength: - Exclude: - - 'spec/api_map_spec.rb' - - 'spec/complex_type_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/initialize_spec.rb' - - 'spec/language_server/message/text_document/definition_spec.rb' - - 'spec/language_server/message/text_document/hover_spec.rb' - - 'spec/language_server/message/text_document/rename_spec.rb' - - 'spec/language_server/message/text_document/type_definition_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/library_spec.rb' - - 'spec/parser/flow_sensitive_typing_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/parser/node_processor_spec.rb' - - 'spec/pin/base_variable_spec.rb' - - 'spec/pin/delegated_method_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/pin/parameter_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/type_checker_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: CustomTransform, IgnoredWords, DisallowedExamples. @@ -1077,15 +664,7 @@ RSpec/ExpectActual: # Configuration parameters: EnforcedStyle. # SupportedStyles: implicit, each, example RSpec/HookArgument: - Exclude: - - 'spec/api_map/config_spec.rb' - - 'spec/diagnostics/require_not_found_spec.rb' - - 'spec/language_server/host/dispatch_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/workspace/config_spec.rb' - - 'spec/workspace_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: . @@ -1095,13 +674,7 @@ RSpec/ImplicitExpect: # Configuration parameters: AssignmentOnly. RSpec/InstanceVariable: - Exclude: - - 'spec/api_map/config_spec.rb' - - 'spec/api_map_spec.rb' - - 'spec/diagnostics/require_not_found_spec.rb' - - 'spec/language_server/host/dispatch_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/protocol_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). RSpec/LeadingSubject: @@ -1127,89 +700,17 @@ RSpec/MissingExampleGroupArgument: Exclude: - 'spec/diagnostics/rubocop_helpers_spec.rb' -# Configuration parameters: Max. RSpec/MultipleExpectations: - Exclude: - - 'spec/api_map/cache_spec.rb' - - 'spec/api_map/config_spec.rb' - - 'spec/api_map/source_to_yard_spec.rb' - - 'spec/api_map/store_spec.rb' - - 'spec/api_map_spec.rb' - - 'spec/complex_type_spec.rb' - - 'spec/convention/struct_definition_spec.rb' - - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/diagnostics/type_check_spec.rb' - - 'spec/diagnostics/update_errors_spec.rb' - - 'spec/diagnostics_spec.rb' - - 'spec/doc_map_spec.rb' - - 'spec/gem_pins_spec.rb' - - 'spec/language_server/host/message_worker_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/initialize_spec.rb' - - 'spec/language_server/message/text_document/rename_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/language_server/transport/adapter_spec.rb' - - 'spec/language_server/transport/data_reader_spec.rb' - - 'spec/library_spec.rb' - - 'spec/parser/flow_sensitive_typing_spec.rb' - - 'spec/parser/node_chainer_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/parser/node_processor_spec.rb' - - 'spec/pin/base_spec.rb' - - 'spec/pin/base_variable_spec.rb' - - 'spec/pin/constant_spec.rb' - - 'spec/pin/instance_variable_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/pin/method_spec.rb' - - 'spec/pin/namespace_spec.rb' - - 'spec/pin/parameter_spec.rb' - - 'spec/position_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/rbs_map/stdlib_map_spec.rb' - - 'spec/rbs_map_spec.rb' - - 'spec/shell_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source/chain/class_variable_spec.rb' - - 'spec/source/chain/global_variable_spec.rb' - - 'spec/source/chain/head_spec.rb' - - 'spec/source/chain/instance_variable_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source/cursor_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map/node_processor_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' - - 'spec/type_checker/checks_spec.rb' - - 'spec/type_checker/levels/normal_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/type_checker/levels/strong_spec.rb' - - 'spec/type_checker/levels/typed_spec.rb' - - 'spec/type_checker/rules_spec.rb' - - 'spec/workspace/config_spec.rb' - - 'spec/workspace_spec.rb' - - 'spec/yard_map/mapper/to_method_spec.rb' - - 'spec/yard_map/mapper_spec.rb' + Max: 14 -# Configuration parameters: Max, AllowedGroups. +# Configuration parameters: AllowedGroups. RSpec/NestedGroups: - Exclude: - - 'spec/complex_type_spec.rb' + Max: 4 # Configuration parameters: AllowedPatterns. # AllowedPatterns: ^expect_, ^assert_ RSpec/NoExpectationExample: - Exclude: - - 'spec/language_server/protocol_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/pin/block_spec.rb' - - 'spec/pin/method_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/type_checker/checks_spec.rb' - - 'spec/type_checker/levels/typed_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. @@ -1220,18 +721,7 @@ RSpec/NotToNot: - 'spec/rbs_map/core_map_spec.rb' RSpec/PendingWithoutReason: - Exclude: - - 'spec/api_map_spec.rb' - - 'spec/complex_type_spec.rb' - - 'spec/parser/node_chainer_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/yard_map/mapper/to_method_spec.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: Strict, EnforcedStyle, AllowedExplicitMatchers. @@ -1251,16 +741,7 @@ RSpec/RemoveConst: - 'spec/diagnostics/rubocop_helpers_spec.rb' RSpec/RepeatedDescription: - Exclude: - - 'spec/api_map_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/type_checker/levels/normal_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' + Enabled: false RSpec/RepeatedExample: Exclude: @@ -1279,99 +760,7 @@ RSpec/ScatteredLet: # Configuration parameters: Include, CustomTransform, IgnoreMethods, IgnoreMetadata. # Include: **/*_spec.rb RSpec/SpecFilePathFormat: - Exclude: - - '**/spec/routing/**/*' - - 'spec/api_map/cache_spec.rb' - - 'spec/api_map/config_spec.rb' - - 'spec/api_map/source_to_yard_spec.rb' - - 'spec/api_map/store_spec.rb' - - 'spec/api_map_spec.rb' - - 'spec/convention/activesupport_concern_spec.rb' - - 'spec/convention/struct_definition_spec.rb' - - 'spec/convention_spec.rb' - - 'spec/diagnostics/base_spec.rb' - - 'spec/diagnostics/require_not_found_spec.rb' - - 'spec/diagnostics/rubocop_helpers_spec.rb' - - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/diagnostics/type_check_spec.rb' - - 'spec/diagnostics/update_errors_spec.rb' - - 'spec/diagnostics_spec.rb' - - 'spec/doc_map_spec.rb' - - 'spec/gem_pins_spec.rb' - - 'spec/language_server/host/diagnoser_spec.rb' - - 'spec/language_server/host/dispatch_spec.rb' - - 'spec/language_server/host/message_worker_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/message/initialize_spec.rb' - - 'spec/language_server/message/text_document/definition_spec.rb' - - 'spec/language_server/message/text_document/formatting_spec.rb' - - 'spec/language_server/message/text_document/hover_spec.rb' - - 'spec/language_server/message/text_document/rename_spec.rb' - - 'spec/language_server/message/text_document/type_definition_spec.rb' - - 'spec/language_server/message/workspace/did_change_configuration_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' - - 'spec/language_server/message_spec.rb' - - 'spec/language_server/transport/adapter_spec.rb' - - 'spec/language_server/transport/data_reader_spec.rb' - - 'spec/language_server/uri_helpers_spec.rb' - - 'spec/library_spec.rb' - - 'spec/logging_spec.rb' - - 'spec/parser/flow_sensitive_typing_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/parser/node_processor_spec.rb' - - 'spec/parser_spec.rb' - - 'spec/pin/base_spec.rb' - - 'spec/pin/base_variable_spec.rb' - - 'spec/pin/block_spec.rb' - - 'spec/pin/constant_spec.rb' - - 'spec/pin/delegated_method_spec.rb' - - 'spec/pin/documenting_spec.rb' - - 'spec/pin/instance_variable_spec.rb' - - 'spec/pin/keyword_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/pin/method_spec.rb' - - 'spec/pin/namespace_spec.rb' - - 'spec/pin/parameter_spec.rb' - - 'spec/pin/search_spec.rb' - - 'spec/pin/symbol_spec.rb' - - 'spec/position_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/rbs_map/stdlib_map_spec.rb' - - 'spec/rbs_map_spec.rb' - - 'spec/shell_spec.rb' - - 'spec/source/chain/array_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source/chain/class_variable_spec.rb' - - 'spec/source/chain/constant_spec.rb' - - 'spec/source/chain/global_variable_spec.rb' - - 'spec/source/chain/head_spec.rb' - - 'spec/source/chain/instance_variable_spec.rb' - - 'spec/source/chain/link_spec.rb' - - 'spec/source/chain/literal_spec.rb' - - 'spec/source/chain/z_super_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source/change_spec.rb' - - 'spec/source/cursor_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source/updater_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' - - 'spec/type_checker/checks_spec.rb' - - 'spec/type_checker/levels/normal_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/type_checker/levels/strong_spec.rb' - - 'spec/type_checker/levels/typed_spec.rb' - - 'spec/type_checker/rules_spec.rb' - - 'spec/type_checker_spec.rb' - - 'spec/workspace/config_spec.rb' - - 'spec/workspace_spec.rb' - - 'spec/yard_map/mapper/to_method_spec.rb' - - 'spec/yard_map/mapper_spec.rb' + Enabled: false RSpec/StubbedMock: Exclude: @@ -1379,20 +768,7 @@ RSpec/StubbedMock: # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. RSpec/VerifiedDoubles: - Exclude: - - 'spec/complex_type_spec.rb' - - 'spec/language_server/host/diagnoser_spec.rb' - - 'spec/language_server/host/message_worker_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/message/text_document/formatting_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/source/chain/class_variable_spec.rb' - - 'spec/source/cursor_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/workspace_spec.rb' + Enabled: false Security/MarshalLoad: Exclude: @@ -1402,20 +778,7 @@ Security/MarshalLoad: # Configuration parameters: EnforcedStyle, AllowModifiersOnSymbols, AllowModifiersOnAttrs, AllowModifiersOnAliasMethod. # SupportedStyles: inline, group Style/AccessModifierDeclarations: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/location.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/position.rb' - - 'lib/solargraph/range.rb' - - 'lib/solargraph/source/chain.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/chain/hash.rb' - - 'lib/solargraph/source/chain/if.rb' - - 'lib/solargraph/source/chain/link.rb' - - 'lib/solargraph/source/chain/literal.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. @@ -1431,21 +794,7 @@ Style/AccessorGrouping: # Configuration parameters: EnforcedStyle. # SupportedStyles: always, conditionals Style/AndOr: - Exclude: - - 'lib/solargraph/api_map/source_to_yard.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/language_server/message/base.rb' - - 'lib/solargraph/page.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/position.rb' - - 'lib/solargraph/source/change.rb' - - 'lib/solargraph/source/cursor.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source/updater.rb' - - 'lib/solargraph/workspace.rb' - - 'lib/solargraph/yard_map/mapper.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowOnlyRestArgument, UseAnonymousForwarding, RedundantRestArgumentNames, RedundantKeywordRestArgumentNames, RedundantBlockArgumentNames. @@ -1464,44 +813,12 @@ Style/ArgumentsForwarding: # FunctionalMethods: let, let!, subject, watch # AllowedMethods: lambda, proc, it Style/BlockDelimiters: - Exclude: - - 'lib/solargraph/api_map/source_to_yard.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/language_server/host.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/language_server/transport/adapter_spec.rb' - - 'spec/language_server/transport/data_reader_spec.rb' - - 'spec/library_spec.rb' - - 'spec/parser/node_processor_spec.rb' - - 'spec/pin/documenting_spec.rb' - - 'spec/position_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_spec.rb' - - 'spec/type_checker_spec.rb' - - 'spec/workspace_spec.rb' - - 'spec/yard_map/mapper/to_method_spec.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: MinBranchesCount. Style/CaseLikeIf: - Exclude: - - 'lib/solargraph/language_server/message/workspace/did_change_watched_files.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/yard_map/mapper.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules. @@ -1509,18 +826,7 @@ Style/CaseLikeIf: # SupportedStylesForClasses: ~, nested, compact # SupportedStylesForModules: ~, nested, compact Style/ClassAndModuleChildren: - Exclude: - - 'lib/solargraph/language_server/message/text_document/definition.rb' - - 'lib/solargraph/language_server/message/text_document/document_highlight.rb' - - 'lib/solargraph/language_server/message/text_document/document_symbol.rb' - - 'lib/solargraph/language_server/message/text_document/prepare_rename.rb' - - 'lib/solargraph/language_server/message/text_document/references.rb' - - 'lib/solargraph/language_server/message/text_document/rename.rb' - - 'lib/solargraph/language_server/message/text_document/type_definition.rb' - - 'lib/solargraph/language_server/message/workspace/did_change_configuration.rb' - - 'lib/solargraph/language_server/message/workspace/did_change_watched_files.rb' - - 'lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb' - - 'lib/solargraph/language_server/message/workspace/workspace_symbol.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowedMethods, AllowedPatterns. @@ -1556,150 +862,13 @@ Style/ConcatArrayLiterals: # SupportedStyles: assign_to_condition, assign_inside_condition Style/ConditionalAssignment: Exclude: + - 'lib/solargraph/api_map/source_to_yard.rb' - 'lib/solargraph/parser/parser_gem/node_processors/defs_node.rb' - 'lib/solargraph/source/chain/call.rb' # Configuration parameters: AllowedConstants. Style/Documentation: - Exclude: - - 'spec/**/*' - - 'test/**/*' - - 'lib/solargraph/api_map/cache.rb' - - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/api_map/source_to_yard.rb' - - 'lib/solargraph/convention/data_definition.rb' - - 'lib/solargraph/convention/gemfile.rb' - - 'lib/solargraph/convention/gemspec.rb' - - 'lib/solargraph/convention/rakefile.rb' - - 'lib/solargraph/convention/struct_definition.rb' - - 'lib/solargraph/converters/dd.rb' - - 'lib/solargraph/converters/dl.rb' - - 'lib/solargraph/converters/dt.rb' - - 'lib/solargraph/diagnostics/update_errors.rb' - - 'lib/solargraph/language_server/message/base.rb' - - 'lib/solargraph/language_server/message/cancel_request.rb' - - 'lib/solargraph/language_server/message/client.rb' - - 'lib/solargraph/language_server/message/client/register_capability.rb' - - 'lib/solargraph/language_server/message/completion_item.rb' - - 'lib/solargraph/language_server/message/exit_notification.rb' - - 'lib/solargraph/language_server/message/extended/document.rb' - - 'lib/solargraph/language_server/message/extended/search.rb' - - 'lib/solargraph/language_server/message/initialize.rb' - - 'lib/solargraph/language_server/message/initialized.rb' - - 'lib/solargraph/language_server/message/method_not_found.rb' - - 'lib/solargraph/language_server/message/method_not_implemented.rb' - - 'lib/solargraph/language_server/message/shutdown.rb' - - 'lib/solargraph/language_server/message/text_document.rb' - - 'lib/solargraph/language_server/message/text_document/base.rb' - - 'lib/solargraph/language_server/message/text_document/code_action.rb' - - 'lib/solargraph/language_server/message/text_document/completion.rb' - - 'lib/solargraph/language_server/message/text_document/definition.rb' - - 'lib/solargraph/language_server/message/text_document/did_change.rb' - - 'lib/solargraph/language_server/message/text_document/did_close.rb' - - 'lib/solargraph/language_server/message/text_document/did_open.rb' - - 'lib/solargraph/language_server/message/text_document/did_save.rb' - - 'lib/solargraph/language_server/message/text_document/document_highlight.rb' - - 'lib/solargraph/language_server/message/text_document/document_symbol.rb' - - 'lib/solargraph/language_server/message/text_document/folding_range.rb' - - 'lib/solargraph/language_server/message/text_document/formatting.rb' - - 'lib/solargraph/language_server/message/text_document/hover.rb' - - 'lib/solargraph/language_server/message/text_document/on_type_formatting.rb' - - 'lib/solargraph/language_server/message/text_document/prepare_rename.rb' - - 'lib/solargraph/language_server/message/text_document/references.rb' - - 'lib/solargraph/language_server/message/text_document/rename.rb' - - 'lib/solargraph/language_server/message/text_document/signature_help.rb' - - 'lib/solargraph/language_server/message/text_document/type_definition.rb' - - 'lib/solargraph/language_server/message/workspace.rb' - - 'lib/solargraph/language_server/message/workspace/did_change_configuration.rb' - - 'lib/solargraph/language_server/message/workspace/did_change_watched_files.rb' - - 'lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb' - - 'lib/solargraph/language_server/message/workspace/workspace_symbol.rb' - - 'lib/solargraph/language_server/request.rb' - - 'lib/solargraph/language_server/transport/data_reader.rb' - - 'lib/solargraph/logging.rb' - - 'lib/solargraph/page.rb' - - 'lib/solargraph/parser.rb' - - 'lib/solargraph/parser/comment_ripper.rb' - - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/parser/node_methods.rb' - - 'lib/solargraph/parser/node_processor/base.rb' - - 'lib/solargraph/parser/parser_gem.rb' - - 'lib/solargraph/parser/parser_gem/class_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/alias_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/and_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/args_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/begin_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/block_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/casgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/cvasgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/def_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/defs_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/gvasgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/if_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/namespace_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/sym_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/until_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/while_node.rb' - - 'lib/solargraph/parser/snippet.rb' - - 'lib/solargraph/pin/base_variable.rb' - - 'lib/solargraph/pin/block.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/closure.rb' - - 'lib/solargraph/pin/common.rb' - - 'lib/solargraph/pin/constant.rb' - - 'lib/solargraph/pin/instance_variable.rb' - - 'lib/solargraph/pin/keyword.rb' - - 'lib/solargraph/pin/local_variable.rb' - - 'lib/solargraph/pin/namespace.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/pin/proxy_type.rb' - - 'lib/solargraph/pin/reference.rb' - - 'lib/solargraph/pin/reference/override.rb' - - 'lib/solargraph/pin/reference/require.rb' - - 'lib/solargraph/pin/search.rb' - - 'lib/solargraph/pin/signature.rb' - - 'lib/solargraph/pin/singleton.rb' - - 'lib/solargraph/pin/symbol.rb' - - 'lib/solargraph/pin/until.rb' - - 'lib/solargraph/pin/while.rb' - - 'lib/solargraph/pin_cache.rb' - - 'lib/solargraph/rbs_map.rb' - - 'lib/solargraph/server_methods.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source/chain/array.rb' - - 'lib/solargraph/source/chain/block_symbol.rb' - - 'lib/solargraph/source/chain/block_variable.rb' - - 'lib/solargraph/source/chain/class_variable.rb' - - 'lib/solargraph/source/chain/constant.rb' - - 'lib/solargraph/source/chain/global_variable.rb' - - 'lib/solargraph/source/chain/hash.rb' - - 'lib/solargraph/source/chain/if.rb' - - 'lib/solargraph/source/chain/instance_variable.rb' - - 'lib/solargraph/source/chain/link.rb' - - 'lib/solargraph/source/chain/literal.rb' - - 'lib/solargraph/source/chain/or.rb' - - 'lib/solargraph/source/chain/q_call.rb' - - 'lib/solargraph/source/chain/variable.rb' - - 'lib/solargraph/source/chain/z_super.rb' - - 'lib/solargraph/source/encoding_fixes.rb' - - 'lib/solargraph/source_map/data.rb' - - 'lib/solargraph/yard_map/cache.rb' - - 'lib/solargraph/yard_map/helpers.rb' - - 'lib/solargraph/yard_map/mapper.rb' - - 'lib/solargraph/yard_map/mapper/to_constant.rb' - - 'lib/solargraph/yard_map/mapper/to_method.rb' - - 'lib/solargraph/yard_map/mapper/to_namespace.rb' - - 'lib/solargraph/yard_map/to_method.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/EmptyLambdaParameter: @@ -1750,136 +919,7 @@ Style/FloatDivision: # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never Style/FrozenStringLiteralComment: - Exclude: - - '**/*.arb' - - 'Gemfile' - - 'Rakefile' - - 'bin/solargraph' - - 'lib/solargraph/converters/dd.rb' - - 'lib/solargraph/converters/dl.rb' - - 'lib/solargraph/converters/dt.rb' - - 'lib/solargraph/converters/misc.rb' - - 'lib/solargraph/parser.rb' - - 'lib/solargraph/parser/comment_ripper.rb' - - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/parser/node_methods.rb' - - 'lib/solargraph/parser/parser_gem.rb' - - 'lib/solargraph/parser/snippet.rb' - - 'lib/solargraph/pin/breakable.rb' - - 'lib/solargraph/pin/signature.rb' - - 'lib/solargraph/pin_cache.rb' - - 'lib/solargraph/source/chain/array.rb' - - 'lib/solargraph/source/chain/q_call.rb' - - 'lib/solargraph/yard_map/helpers.rb' - - 'solargraph.gemspec' - - 'spec/api_map/cache_spec.rb' - - 'spec/api_map/config_spec.rb' - - 'spec/api_map/source_to_yard_spec.rb' - - 'spec/api_map_spec.rb' - - 'spec/complex_type_spec.rb' - - 'spec/convention/struct_definition_spec.rb' - - 'spec/convention_spec.rb' - - 'spec/diagnostics/base_spec.rb' - - 'spec/diagnostics/require_not_found_spec.rb' - - 'spec/diagnostics/rubocop_helpers_spec.rb' - - 'spec/diagnostics/type_check_spec.rb' - - 'spec/diagnostics/update_errors_spec.rb' - - 'spec/diagnostics_spec.rb' - - 'spec/fixtures/formattable.rb' - - 'spec/fixtures/long_squiggly_heredoc.rb' - - 'spec/fixtures/rdoc-lib/Gemfile' - - 'spec/fixtures/rdoc-lib/lib/example.rb' - - 'spec/fixtures/rdoc-lib/rdoc-lib.gemspec' - - 'spec/fixtures/rubocop-custom-version/specifications/rubocop-0.0.0.gemspec' - - 'spec/fixtures/rubocop-validation-error/app.rb' - - 'spec/fixtures/unicode.rb' - - 'spec/fixtures/workspace-with-gemfile/Gemfile' - - 'spec/fixtures/workspace-with-gemfile/app.rb' - - 'spec/fixtures/workspace-with-gemfile/lib/other.rb' - - 'spec/fixtures/workspace-with-gemfile/lib/thing.rb' - - 'spec/fixtures/workspace/app.rb' - - 'spec/fixtures/workspace/lib/other.rb' - - 'spec/fixtures/workspace/lib/something.rb' - - 'spec/fixtures/workspace/lib/thing.rb' - - 'spec/fixtures/workspace_folders/folder1/app.rb' - - 'spec/fixtures/workspace_folders/folder2/app.rb' - - 'spec/fixtures/yard_map/attr.rb' - - 'spec/language_server/host/diagnoser_spec.rb' - - 'spec/language_server/host/dispatch_spec.rb' - - 'spec/language_server/host/message_worker_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/message/initialize_spec.rb' - - 'spec/language_server/message/text_document/definition_spec.rb' - - 'spec/language_server/message/text_document/formatting_spec.rb' - - 'spec/language_server/message/text_document/hover_spec.rb' - - 'spec/language_server/message/text_document/type_definition_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' - - 'spec/language_server/message_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/language_server/transport/adapter_spec.rb' - - 'spec/language_server/transport/data_reader_spec.rb' - - 'spec/language_server/uri_helpers_spec.rb' - - 'spec/library_spec.rb' - - 'spec/logging_spec.rb' - - 'spec/parser/node_chainer_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/parser/node_processor_spec.rb' - - 'spec/parser_spec.rb' - - 'spec/pin/base_spec.rb' - - 'spec/pin/base_variable_spec.rb' - - 'spec/pin/block_spec.rb' - - 'spec/pin/class_variable_spec.rb' - - 'spec/pin/constant_spec.rb' - - 'spec/pin/delegated_method_spec.rb' - - 'spec/pin/documenting_spec.rb' - - 'spec/pin/instance_variable_spec.rb' - - 'spec/pin/keyword_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/pin/method_spec.rb' - - 'spec/pin/namespace_spec.rb' - - 'spec/pin/parameter_spec.rb' - - 'spec/pin/search_spec.rb' - - 'spec/pin/symbol_spec.rb' - - 'spec/position_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/rbs_map/stdlib_map_spec.rb' - - 'spec/rbs_map_spec.rb' - - 'spec/shell_spec.rb' - - 'spec/source/chain/array_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source/chain/class_variable_spec.rb' - - 'spec/source/chain/constant_spec.rb' - - 'spec/source/chain/global_variable_spec.rb' - - 'spec/source/chain/head_spec.rb' - - 'spec/source/chain/instance_variable_spec.rb' - - 'spec/source/chain/link_spec.rb' - - 'spec/source/chain/literal_spec.rb' - - 'spec/source/chain/z_super_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source/change_spec.rb' - - 'spec/source/cursor_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source/updater_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map/node_processor_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' - - 'spec/spec_helper.rb' - - 'spec/type_checker/checks_spec.rb' - - 'spec/type_checker/levels/normal_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/type_checker/levels/strong_spec.rb' - - 'spec/type_checker/levels/typed_spec.rb' - - 'spec/type_checker/rules_spec.rb' - - 'spec/type_checker_spec.rb' - - 'spec/workspace/config_spec.rb' - - 'spec/workspace_spec.rb' - - 'spec/yard_map/mapper/to_method_spec.rb' - - 'spec/yard_map/mapper_spec.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). Style/GlobalStdStream: @@ -1892,15 +932,7 @@ Style/GlobalStdStream: # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. Style/GuardClause: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin_cache.rb' - - 'lib/solargraph/range.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/workspace.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowSplatArgument. @@ -1935,52 +967,11 @@ Style/IdenticalConditionalBranches: # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowIfModifier. Style/IfInsideElse: - Exclude: - - 'lib/solargraph/complex_type/type_methods.rb' - - 'lib/solargraph/language_server/transport/data_reader.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/language_server/message/completion_item/resolve.rb' - - 'lib/solargraph/language_server/message/initialize.rb' - - 'lib/solargraph/language_server/message/text_document/completion.rb' - - 'lib/solargraph/language_server/message/text_document/hover.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/class_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/common.rb' - - 'lib/solargraph/pin/constant.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/range.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/source/chain.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/change.rb' - - 'lib/solargraph/source/cursor.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' - - 'lib/solargraph/workspace.rb' - - 'lib/solargraph/workspace/config.rb' - - 'lib/solargraph/yard_map/helpers.rb' - - 'lib/solargraph/yard_map/mapper/to_method.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. @@ -2010,69 +1001,8 @@ Style/MapToSet: # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: require_parentheses, require_no_parentheses, require_no_parentheses_except_multiline -Style/MethodDefParentheses: - Exclude: - - 'lib/solargraph.rb' - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/type_methods.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/convention.rb' - - 'lib/solargraph/convention/data_definition.rb' - - 'lib/solargraph/convention/data_definition/data_assignment_node.rb' - - 'lib/solargraph/convention/data_definition/data_definition_node.rb' - - 'lib/solargraph/convention/struct_definition.rb' - - 'lib/solargraph/convention/struct_definition/struct_assignment_node.rb' - - 'lib/solargraph/convention/struct_definition/struct_definition_node.rb' - - 'lib/solargraph/diagnostics/rubocop_helpers.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/equality.rb' - - 'lib/solargraph/gem_pins.rb' - - 'lib/solargraph/language_server/host/message_worker.rb' - - 'lib/solargraph/language_server/host/sources.rb' - - 'lib/solargraph/language_server/message/text_document/formatting.rb' - - 'lib/solargraph/location.rb' - - 'lib/solargraph/parser/comment_ripper.rb' - - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/parser/node_methods.rb' - - 'lib/solargraph/parser/node_processor/base.rb' - - 'lib/solargraph/parser/parser_gem/flawed_builder.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/args_node.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/base_variable.rb' - - 'lib/solargraph/pin/block.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/closure.rb' - - 'lib/solargraph/pin/delegated_method.rb' - - 'lib/solargraph/pin/local_variable.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/pin_cache.rb' - - 'lib/solargraph/position.rb' - - 'lib/solargraph/range.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/chain/constant.rb' - - 'lib/solargraph/source_map.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' - - 'lib/solargraph/type_checker/checks.rb' - - 'lib/solargraph/yard_map/helpers.rb' - - 'lib/solargraph/yardoc.rb' - - 'spec/doc_map_spec.rb' - - 'spec/fixtures/rdoc-lib/lib/example.rb' - - 'spec/source_map_spec.rb' - - 'spec/spec_helper.rb' - - 'spec/type_checker/levels/normal_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/type_checker/levels/strong_spec.rb' - - 'spec/type_checker/levels/typed_spec.rb' +Style/MethodDefParentheses: + Enabled: false Style/MultilineBlockChain: Exclude: @@ -2091,29 +1021,13 @@ Style/MultilineTernaryOperator: # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowMethodComparison, ComparisonsThreshold. Style/MultipleComparison: - Exclude: - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/type_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: literals, strict Style/MutableConstant: - Exclude: - - 'lib/solargraph/diagnostics/rubocop.rb' - - 'lib/solargraph/logging.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/rbs_map/core_fills.rb' - - 'lib/solargraph/yard_map/mapper/to_method.rb' - - 'spec/complex_type_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. @@ -2148,34 +1062,15 @@ Style/Next: - 'lib/solargraph/type_checker/checks.rb' # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: MinDigits, Strict, AllowedNumbers, AllowedPatterns. +# Configuration parameters: Strict, AllowedNumbers, AllowedPatterns. Style/NumericLiterals: - Exclude: - - 'lib/solargraph/language_server/error_codes.rb' - - 'spec/language_server/protocol_spec.rb' + MinDigits: 6 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns. # SupportedStyles: predicate, comparison Style/NumericPredicate: - Exclude: - - 'spec/**/*' - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/type_methods.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/language_server/message/extended/check_gem_version.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/comment_ripper.rb' - - 'lib/solargraph/pin/delegated_method.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source/chain/array.rb' - - 'lib/solargraph/source/change.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/workspace.rb' + Enabled: false Style/OpenStructUse: Exclude: @@ -2184,14 +1079,7 @@ Style/OpenStructUse: # Configuration parameters: AllowedMethods. # AllowedMethods: respond_to_missing? Style/OptionalBooleanParameter: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/language_server/message/text_document/completion.rb' - - 'lib/solargraph/source/chain.rb' - - 'lib/solargraph/source/chain/hash.rb' - - 'lib/solargraph/source/chain/z_super.rb' - - 'lib/solargraph/source/change.rb' - - 'lib/solargraph/source/updater.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowSafeAssignment, AllowInMultilineConditions. @@ -2254,14 +1142,7 @@ Style/RedundantInterpolation: # This cop supports safe autocorrection (--autocorrect). Style/RedundantParentheses: - Exclude: - - 'lib/solargraph/diagnostics/type_check.rb' - - 'lib/solargraph/language_server/message/initialize.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/RedundantRegexpArgument: @@ -2274,13 +1155,7 @@ Style/RedundantRegexpArgument: # This cop supports safe autocorrection (--autocorrect). Style/RedundantRegexpEscape: - Exclude: - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/diagnostics/rubocop.rb' - - 'lib/solargraph/language_server/uri_helpers.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowMultipleReturnValues. @@ -2294,15 +1169,7 @@ Style/RedundantReturn: # This cop supports safe autocorrection (--autocorrect). Style/RedundantSelf: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/equality.rb' - - 'lib/solargraph/location.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/signature.rb' - - 'lib/solargraph/source/chain.rb' - - 'lib/solargraph/source/chain/link.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, AllowInnerSlashes. @@ -2323,19 +1190,7 @@ Style/RescueStandardError: # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength. # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: - Exclude: - - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/language_server/message/completion_item/resolve.rb' - - 'lib/solargraph/language_server/request.rb' - - 'lib/solargraph/language_server/transport/data_reader.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/conversions.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin_cache.rb' - - 'lib/solargraph/range.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false # Configuration parameters: Max. Style/SafeNavigationChainLength: @@ -2344,36 +1199,12 @@ Style/SafeNavigationChainLength: # This cop supports unsafe autocorrection (--autocorrect-all). Style/SlicingWithRange: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/convention/data_definition/data_definition_node.rb' - - 'lib/solargraph/convention/struct_definition/struct_definition_node.rb' - - 'lib/solargraph/diagnostics/rubocop_helpers.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/namespace.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/chain/constant.rb' - - 'lib/solargraph/source/change.rb' - - 'lib/solargraph/source/cursor.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker/checks.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowModifier. Style/SoleNestedConditional: - Exclude: - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/StderrPuts: @@ -2384,114 +1215,13 @@ Style/StderrPuts: # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: Mode. Style/StringConcatenation: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/closure.rb' - - 'lib/solargraph/pin/local_variable.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/namespace.rb' - - 'solargraph.gemspec' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes Style/StringLiterals: - Exclude: - - 'Gemfile' - - 'Rakefile' - - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/convention/struct_definition.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/language_server/host.rb' - - 'lib/solargraph/language_server/message/extended/document_gems.rb' - - 'lib/solargraph/language_server/message/extended/download_core.rb' - - 'lib/solargraph/language_server/message/initialize.rb' - - 'lib/solargraph/language_server/message/text_document/completion.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/parser_gem/class_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/conversions.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/server_methods.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/workspace.rb' - - 'lib/solargraph/yard_map/mapper/to_method.rb' - - 'lib/solargraph/yard_tags.rb' - - 'solargraph.gemspec' - - 'spec/api_map/cache_spec.rb' - - 'spec/api_map/config_spec.rb' - - 'spec/api_map/source_to_yard_spec.rb' - - 'spec/complex_type_spec.rb' - - 'spec/convention/struct_definition_spec.rb' - - 'spec/diagnostics/base_spec.rb' - - 'spec/diagnostics/require_not_found_spec.rb' - - 'spec/diagnostics/rubocop_helpers_spec.rb' - - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/diagnostics/type_check_spec.rb' - - 'spec/diagnostics/update_errors_spec.rb' - - 'spec/diagnostics_spec.rb' - - 'spec/fixtures/rdoc-lib/rdoc-lib.gemspec' - - 'spec/language_server/host/diagnoser_spec.rb' - - 'spec/language_server/host/dispatch_spec.rb' - - 'spec/language_server/host/message_worker_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/message/initialize_spec.rb' - - 'spec/language_server/message/text_document/rename_spec.rb' - - 'spec/language_server/message_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/language_server/transport/adapter_spec.rb' - - 'spec/language_server/transport/data_reader_spec.rb' - - 'spec/library_spec.rb' - - 'spec/logging_spec.rb' - - 'spec/parser/node_chainer_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/parser_spec.rb' - - 'spec/pin/base_spec.rb' - - 'spec/pin/base_variable_spec.rb' - - 'spec/pin/constant_spec.rb' - - 'spec/pin/instance_variable_spec.rb' - - 'spec/pin/keyword_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/pin/namespace_spec.rb' - - 'spec/pin/symbol_spec.rb' - - 'spec/position_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/rbs_map/stdlib_map_spec.rb' - - 'spec/shell_spec.rb' - - 'spec/source/chain/array_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source/chain/class_variable_spec.rb' - - 'spec/source/chain/constant_spec.rb' - - 'spec/source/chain/global_variable_spec.rb' - - 'spec/source/chain/head_spec.rb' - - 'spec/source/chain/instance_variable_spec.rb' - - 'spec/source/chain/link_spec.rb' - - 'spec/source/chain/literal_spec.rb' - - 'spec/source/chain/z_super_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source/change_spec.rb' - - 'spec/source/cursor_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source/updater_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/workspace/config_spec.rb' - - 'spec/workspace_spec.rb' - - 'spec/yard_map/mapper/to_method_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/SuperArguments: @@ -2505,35 +1235,13 @@ Style/SuperArguments: # Configuration parameters: EnforcedStyle, MinSize. # SupportedStyles: percent, brackets Style/SymbolArray: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/block_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/chain/literal.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/source_map/mapper_spec.rb' + Enabled: false # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowMethodsWithArguments, AllowedMethods, AllowedPatterns, AllowComments. # AllowedMethods: define_method Style/SymbolProc: - Exclude: - - 'lib/solargraph/gem_pins.rb' - - 'lib/solargraph/language_server/message/text_document/hover.rb' - - 'lib/solargraph/language_server/message/text_document/signature_help.rb' - - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/closure.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, AllowSafeAssignment. @@ -2546,19 +1254,7 @@ Style/TernaryParentheses: # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInArguments: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/parser/node_processor.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/block_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/def_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/defs_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/until_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/while_node.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/yard_map/mapper/to_method.rb' - - 'lib/solargraph/yard_map/mapper/to_namespace.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. @@ -2572,13 +1268,7 @@ Style/TrailingCommaInArrayLiteral: # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma Style/TrailingCommaInHashLiteral: - Exclude: - - 'lib/solargraph/pin/base_variable.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/closure.rb' - - 'lib/solargraph/pin/local_variable.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/rbs_map/conversions.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: ExactNameMatch, AllowPredicates, AllowDSLWriters, IgnoreClassMethods, AllowedMethods. @@ -2597,20 +1287,7 @@ Style/WhileUntilModifier: # Configuration parameters: EnforcedStyle, MinSize, WordRegex. # SupportedStyles: percent, brackets Style/WordArray: - Exclude: - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/diagnostics/type_check.rb' - - 'lib/solargraph/language_server/message/text_document/formatting.rb' - - 'spec/doc_map_spec.rb' - - 'spec/parser/node_chainer_spec.rb' - - 'spec/pin/method_spec.rb' - - 'spec/source/cursor_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). Style/YAMLFileRead: @@ -2619,13 +1296,7 @@ Style/YAMLFileRead: # This cop supports unsafe autocorrection (--autocorrect-all). Style/ZeroLengthPredicate: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/language_server/host.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/source/chain/array.rb' - - 'spec/language_server/protocol_spec.rb' + Enabled: false # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. @@ -2638,33 +1309,7 @@ YARD/CollectionType: # Configuration parameters: EnforcedStylePrototypeName. # SupportedStylesPrototypeName: before, after YARD/MismatchName: - Exclude: - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/gem_pins.rb' - - 'lib/solargraph/language_server/host.rb' - - 'lib/solargraph/language_server/host/dispatch.rb' - - 'lib/solargraph/language_server/request.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/region.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/base_variable.rb' - - 'lib/solargraph/pin/block.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/closure.rb' - - 'lib/solargraph/pin/delegated_method.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/namespace.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/pin/proxy_type.rb' - - 'lib/solargraph/pin/reference.rb' - - 'lib/solargraph/pin/symbol.rb' - - 'lib/solargraph/pin/until.rb' - - 'lib/solargraph/pin/while.rb' - - 'lib/solargraph/pin_cache.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/chain/z_super.rb' - - 'lib/solargraph/type_checker.rb' + Enabled: false YARD/TagTypeSyntax: Exclude: @@ -2673,72 +1318,7 @@ YARD/TagTypeSyntax: - 'lib/solargraph/type_checker.rb' # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. +# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. # URISchemes: http, https Layout/LineLength: - Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/source_to_yard.rb' - - 'lib/solargraph/api_map/store.rb' - - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/convention/data_definition.rb' - - 'lib/solargraph/doc_map.rb' - - 'lib/solargraph/gem_pins.rb' - - 'lib/solargraph/language_server/host.rb' - - 'lib/solargraph/language_server/message/extended/check_gem_version.rb' - - 'lib/solargraph/language_server/message/extended/download_core.rb' - - 'lib/solargraph/language_server/message/initialize.rb' - - 'lib/solargraph/language_server/message/text_document/completion.rb' - - 'lib/solargraph/language_server/message/text_document/definition.rb' - - 'lib/solargraph/language_server/message/text_document/document_highlight.rb' - - 'lib/solargraph/language_server/message/text_document/prepare_rename.rb' - - 'lib/solargraph/language_server/message/text_document/references.rb' - - 'lib/solargraph/language_server/message/text_document/rename.rb' - - 'lib/solargraph/language_server/message/workspace/did_change_watched_files.rb' - - 'lib/solargraph/library.rb' - - 'lib/solargraph/parser/comment_ripper.rb' - - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/and_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/if_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb' - - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin/base.rb' - - 'lib/solargraph/pin/callable.rb' - - 'lib/solargraph/pin/common.rb' - - 'lib/solargraph/pin/documenting.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/rbs_map/conversions.rb' - - 'lib/solargraph/rbs_map/core_fills.rb' - - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source.rb' - - 'lib/solargraph/source/chain.rb' - - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/chain/if.rb' - - 'lib/solargraph/source/chain/instance_variable.rb' - - 'lib/solargraph/source/chain/variable.rb' - - 'lib/solargraph/source/cursor.rb' - - 'lib/solargraph/source/encoding_fixes.rb' - - 'lib/solargraph/source/source_chainer.rb' - - 'lib/solargraph/source_map.rb' - - 'lib/solargraph/source_map/clip.rb' - - 'lib/solargraph/source_map/mapper.rb' - - 'lib/solargraph/type_checker.rb' - - 'lib/solargraph/workspace.rb' - - 'lib/solargraph/workspace/config.rb' - - 'lib/solargraph/yard_map/mapper/to_method.rb' - - 'spec/api_map_spec.rb' - - 'spec/complex_type_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/message/text_document/definition_spec.rb' - - 'spec/language_server/protocol_spec.rb' - - 'spec/pin/parameter_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/workspace_spec.rb' + Max: 244 diff --git a/solargraph.gemspec b/solargraph.gemspec index e6bb9394a..7610bb8ea 100755 --- a/solargraph.gemspec +++ b/solargraph.gemspec @@ -48,9 +48,16 @@ Gem::Specification.new do |s| s.add_development_dependency 'public_suffix', '~> 3.1' s.add_development_dependency 'rake', '~> 13.2' s.add_development_dependency 'rspec', '~> 3.5' - s.add_development_dependency 'rubocop-rake', '~> 0.7' - s.add_development_dependency 'rubocop-rspec', '~> 3.6' - s.add_development_dependency 'rubocop-yard', '~> 1.0' + # + # very specific development-time RuboCop version patterns for CI + # stability - feel free to update in an isolated PR + # + # even more specific on RuboCop itself, which is written into _todo + # file. + s.add_development_dependency 'rubocop', '~> 1.79.2.0' + s.add_development_dependency 'rubocop-rake', '~> 0.7.1' + s.add_development_dependency 'rubocop-rspec', '~> 3.6.0' + s.add_development_dependency 'rubocop-yard', '~> 1.0.0' s.add_development_dependency 'simplecov', '~> 0.21' s.add_development_dependency 'simplecov-lcov', '~> 0.8' s.add_development_dependency 'undercover', '~> 0.7' From 61260f346883de89c8dd9c61b205e88f59ae3a8b Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 30 Aug 2025 10:18:50 -0400 Subject: [PATCH 02/81] Fix merge issue --- .github/workflows/linting.yml | 2 +- .rubocop_todo.yml | 25 +++++++++---------------- lib/solargraph/api_map.rb | 2 -- spec/api_map_spec.rb | 3 --- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index aa22ce22c..b4ef26bfe 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -115,7 +115,7 @@ jobs: - name: Run RuboCop against todo file continue-on-error: true run: | - cmd="bundle exec rubocop --auto-gen-config --exclude-limit=5 --no-offense-counts --no-auto-gen-timestampxb*com" + cmd="bundle exec rubocop --auto-gen-config --exclude-limit=5 --no-offense-counts --no-auto-gen-timestamp" ${cmd:?} set +e if [ -n "$(git status --porcelain)" ] diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7641198af..0ed335f34 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,5 +1,5 @@ # This configuration was generated by -# `rubocop --auto-gen-config --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` +# `rubocop --auto-gen-config --exclude-limit 5 --no-offense-counts --no-auto-gen-timestamp` # using RuboCop version 1.80.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. @@ -121,7 +121,13 @@ Layout/EndOfLine: # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment. - Enabled: false +Layout/ExtraSpacing: + Exclude: + - 'lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb' + - 'lib/solargraph/pin/closure.rb' + - 'lib/solargraph/rbs_map/conversions.rb' + - 'lib/solargraph/type_checker.rb' + - 'spec/spec_helper.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, IndentationWidth. @@ -604,9 +610,9 @@ RSpec/DescribeClass: - '**/spec/routing/**/*' - '**/spec/system/**/*' - '**/spec/views/**/*' + - 'spec/api_map_method_spec.rb' - 'spec/complex_type_spec.rb' - 'spec/source_map/node_processor_spec.rb' - - 'spec/api_map_method_spec.rb' # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants. @@ -633,7 +639,6 @@ RSpec/ExampleLength: # DisallowedExamples: works RSpec/ExampleWording: Exclude: - - 'spec/convention/struct_definition_spec.rb' - 'spec/pin/base_spec.rb' - 'spec/pin/method_spec.rb' @@ -1114,12 +1119,6 @@ Style/RedundantFreeze: - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/source_map/mapper.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowComments. -Style/RedundantInitialize: - Exclude: - - 'lib/solargraph/rbs_map/core_map.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). Style/RedundantInterpolation: Exclude: @@ -1140,12 +1139,6 @@ Style/RedundantRegexpArgument: - 'spec/diagnostics/rubocop_spec.rb' - 'spec/language_server/host_spec.rb' -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantRegexpCharacterClass: - Exclude: - - 'lib/solargraph/source/cursor.rb' - - 'lib/solargraph/source/source_chainer.rb' - # This cop supports safe autocorrection (--autocorrect). Style/RedundantRegexpEscape: Enabled: false diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index f58633a0c..ee35dc497 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -753,7 +753,6 @@ def store # @param skip [Set] # @param no_core [Boolean] Skip core classes if true # @return [Array] - # rubocop:disable Metrics/CyclomaticComplexity def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false rooted_type = ComplexType.parse(rooted_tag).force_rooted fqns = rooted_type.namespace @@ -827,7 +826,6 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false end result end - # rubocop:enable Metrics/CyclomaticComplexity # @param fqns [String] # @param visibility [Array] diff --git a/spec/api_map_spec.rb b/spec/api_map_spec.rb index a612b428e..85e62d507 100755 --- a/spec/api_map_spec.rb +++ b/spec/api_map_spec.rb @@ -1,7 +1,6 @@ require 'tmpdir' describe Solargraph::ApiMap do - # rubocop:disable RSpec/InstanceVariable before :all do @api_map = Solargraph::ApiMap.new end @@ -873,6 +872,4 @@ def c clip = api_map.clip_at('test.rb', [18, 4]) expect(clip.infer.to_s).to eq('Integer') end - - # rubocop:enable RSpec/InstanceVariable end From f63248177198c73cb9474367bdcdd0adce9f0936 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 3 Sep 2025 18:17:14 -0400 Subject: [PATCH 03/81] Centralize all pin-caching logic in PinCache --- .github/workflows/rspec.yml | 4 + .rubocop.yml | 3 + .rubocop_todo.yml | 166 +----- lib/solargraph/api_map.rb | 99 ++-- lib/solargraph/doc_map.rb | 360 ++++--------- lib/solargraph/gem_pins.rb | 13 +- lib/solargraph/library.rb | 41 +- .../parser/parser_gem/class_methods.rb | 3 + lib/solargraph/pin_cache.rb | 508 ++++++++++++++++-- lib/solargraph/rbs_map.rb | 91 +++- lib/solargraph/rbs_map/core_map.rb | 43 +- lib/solargraph/rbs_map/stdlib_map.rb | 25 +- lib/solargraph/shell.rb | 9 +- lib/solargraph/workspace.rb | 88 ++- lib/solargraph/yardoc.rb | 79 ++- spec/doc_map_spec.rb | 149 +++-- spec/gem_pins_spec.rb | 53 +- spec/language_server/host/diagnoser_spec.rb | 3 +- .../host/message_worker_spec.rb | 2 +- spec/library_spec.rb | 312 +++++++---- spec/pin_cache_spec.rb | 197 +++++++ spec/rbs_map_spec.rb | 13 +- spec/shell_spec.rb | 117 +++- spec/spec_helper.rb | 30 +- spec/type_checker/levels/normal_spec.rb | 6 +- spec/yard_map/mapper_spec.rb | 49 +- spec/yardoc_spec.rb | 111 ++++ 27 files changed, 1742 insertions(+), 832 deletions(-) create mode 100644 spec/pin_cache_spec.rb create mode 100644 spec/yardoc_spec.rb diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index ecc3d9771..7b2255b0e 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -48,6 +48,8 @@ jobs: run: | bundle install bundle update rbs # use latest available for this Ruby version + - name: Install types + run: bundle exec rbs collection update - name: Run tests run: bundle exec rake spec undercover: @@ -65,6 +67,8 @@ jobs: bundler-cache: false - name: Install gems run: bundle install + - name: Install types + run: bundle exec rbs collection update - name: Run tests run: bundle exec rake spec - name: Check PR coverage diff --git a/.rubocop.yml b/.rubocop.yml index a73324db2..c17a56410 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -21,6 +21,9 @@ AllCops: - "vendor/**/.*" TargetRubyVersion: 3.0 +RSpec/SpecFilePathFormat: + Enabled: false + Style/MethodDefParentheses: EnforcedStyle: require_no_parentheses diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index b8d123824..f474d025b 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.80.0. +# using RuboCop version 1.80.2. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -64,7 +64,6 @@ Layout/BlockAlignment: Layout/ClosingHeredocIndentation: Exclude: - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowForAlignment. @@ -225,7 +224,6 @@ Layout/HashAlignment: Layout/HeredocIndentation: Exclude: - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' - 'spec/yard_map/mapper/to_method_spec.rb' # This cop supports safe autocorrection (--autocorrect). @@ -241,7 +239,6 @@ Layout/IndentationWidth: - 'lib/solargraph/parser/parser_gem/node_processors/block_node.rb' - 'lib/solargraph/pin/method.rb' - 'lib/solargraph/pin/namespace.rb' - - 'lib/solargraph/rbs_map.rb' - 'lib/solargraph/shell.rb' - 'lib/solargraph/source/chain/call.rb' - 'lib/solargraph/source_map/clip.rb' @@ -295,7 +292,6 @@ Layout/MultilineMethodCallIndentation: # SupportedStyles: aligned, indented Layout/MultilineOperationIndentation: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/language_server/host/dispatch.rb' - 'lib/solargraph/source.rb' @@ -336,7 +332,6 @@ Layout/SpaceAroundOperators: - 'lib/solargraph/source_map/clip.rb' - 'lib/solargraph/workspace/config.rb' - 'spec/library_spec.rb' - - 'spec/yard_map/mapper_spec.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. @@ -511,7 +506,6 @@ Lint/DuplicateMethods: - 'lib/solargraph/pin/base.rb' - 'lib/solargraph/pin/signature.rb' - 'lib/solargraph/rbs_map.rb' - - 'lib/solargraph/rbs_map/core_map.rb' - 'lib/solargraph/source/chain/link.rb' # Configuration parameters: AllowComments, AllowEmptyLambdas. @@ -632,7 +626,6 @@ Lint/UnusedMethodArgument: - 'lib/solargraph/convention/base.rb' - 'lib/solargraph/diagnostics/base.rb' - 'lib/solargraph/diagnostics/update_errors.rb' - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/pin/namespace.rb' - 'lib/solargraph/rbs_map/conversions.rb' - 'lib/solargraph/source.rb' @@ -652,12 +645,6 @@ Lint/UnusedMethodArgument: - 'lib/solargraph/source/chain/z_super.rb' - 'spec/doc_map_spec.rb' -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods. -Lint/UselessAccessModifier: - Exclude: - - 'lib/solargraph/api_map.rb' - # This cop supports safe autocorrection (--autocorrect). Lint/UselessAssignment: Exclude: @@ -700,7 +687,6 @@ Metrics/AbcSize: - 'lib/solargraph/api_map.rb' - 'lib/solargraph/api_map/source_to_yard.rb' - 'lib/solargraph/complex_type.rb' - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/language_server/host.rb' - 'lib/solargraph/language_server/message/initialize.rb' - 'lib/solargraph/library.rb' @@ -770,7 +756,6 @@ Metrics/ModuleLength: Exclude: - 'lib/solargraph/complex_type/type_methods.rb' - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/pin_cache.rb' # Configuration parameters: Max, CountKeywordArgs, MaxOptionalParameters. Metrics/ParameterLists: @@ -817,7 +802,6 @@ Naming/MemoizedInstanceVariableName: - 'lib/solargraph/convention/gemfile.rb' - 'lib/solargraph/convention/gemspec.rb' - 'lib/solargraph/convention/rakefile.rb' - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/rbs_map.rb' - 'lib/solargraph/workspace.rb' @@ -871,7 +855,6 @@ Naming/VariableName: RSpec/Be: Exclude: - 'spec/rbs_map/stdlib_map_spec.rb' - - 'spec/rbs_map_spec.rb' - 'spec/source/source_chainer_spec.rb' # This cop supports unsafe autocorrection (--autocorrect-all). @@ -894,7 +877,6 @@ RSpec/BeforeAfterAll: - '**/spec/rails_helper.rb' - '**/spec/support/**/*.rb' - 'spec/api_map_spec.rb' - - 'spec/doc_map_spec.rb' - 'spec/language_server/host/dispatch_spec.rb' - 'spec/language_server/protocol_spec.rb' @@ -907,7 +889,6 @@ RSpec/ContextWording: - 'spec/pin/method_spec.rb' - 'spec/pin/parameter_spec.rb' - 'spec/pin/symbol_spec.rb' - - 'spec/type_checker/levels/normal_spec.rb' - 'spec/type_checker/levels/strict_spec.rb' - 'spec/type_checker/levels/strong_spec.rb' - 'spec/type_checker/levels/typed_spec.rb' @@ -920,9 +901,9 @@ RSpec/DescribeClass: - '**/spec/routing/**/*' - '**/spec/system/**/*' - '**/spec/views/**/*' + - 'spec/api_map_method_spec.rb' - 'spec/complex_type_spec.rb' - 'spec/source_map/node_processor_spec.rb' - - 'spec/api_map_method_spec.rb' # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: SkipBlocks, EnforcedStyle, OnlyStaticConstants. @@ -941,7 +922,6 @@ RSpec/DescribedClass: - 'spec/diagnostics/update_errors_spec.rb' - 'spec/diagnostics_spec.rb' - 'spec/doc_map_spec.rb' - - 'spec/gem_pins_spec.rb' - 'spec/language_server/host/diagnoser_spec.rb' - 'spec/language_server/host/dispatch_spec.rb' - 'spec/language_server/host/message_worker_spec.rb' @@ -1045,7 +1025,6 @@ RSpec/ExampleLength: # DisallowedExamples: works RSpec/ExampleWording: Exclude: - - 'spec/convention/struct_definition_spec.rb' - 'spec/pin/base_spec.rb' - 'spec/pin/method_spec.rb' @@ -1086,7 +1065,6 @@ RSpec/ImplicitExpect: RSpec/InstanceVariable: Exclude: - 'spec/api_map/config_spec.rb' - - 'spec/api_map_spec.rb' - 'spec/diagnostics/require_not_found_spec.rb' - 'spec/language_server/host/dispatch_spec.rb' - 'spec/language_server/host_spec.rb' @@ -1106,11 +1084,6 @@ RSpec/LetBeforeExamples: Exclude: - 'spec/complex_type_spec.rb' -# Configuration parameters: . -# SupportedStyles: have_received, receive -RSpec/MessageSpies: - EnforcedStyle: receive - RSpec/MissingExampleGroupArgument: Exclude: - 'spec/diagnostics/rubocop_helpers_spec.rb' @@ -1129,9 +1102,6 @@ RSpec/MultipleExpectations: - 'spec/diagnostics/type_check_spec.rb' - 'spec/diagnostics/update_errors_spec.rb' - 'spec/diagnostics_spec.rb' - - 'spec/doc_map_spec.rb' - - 'spec/gem_pins_spec.rb' - - 'spec/language_server/host/message_worker_spec.rb' - 'spec/language_server/host_spec.rb' - 'spec/language_server/message/completion_item/resolve_spec.rb' - 'spec/language_server/message/initialize_spec.rb' @@ -1157,7 +1127,6 @@ RSpec/MultipleExpectations: - 'spec/rbs_map/core_map_spec.rb' - 'spec/rbs_map/stdlib_map_spec.rb' - 'spec/rbs_map_spec.rb' - - 'spec/shell_spec.rb' - 'spec/source/chain/call_spec.rb' - 'spec/source/chain/class_variable_spec.rb' - 'spec/source/chain/global_variable_spec.rb' @@ -1263,106 +1232,6 @@ RSpec/ScatteredLet: Exclude: - 'spec/complex_type_spec.rb' -# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata. -RSpec/SpecFilePathFormat: - Exclude: - - '**/spec/routing/**/*' - - 'spec/api_map/cache_spec.rb' - - 'spec/api_map/config_spec.rb' - - 'spec/api_map/source_to_yard_spec.rb' - - 'spec/api_map/store_spec.rb' - - 'spec/api_map_spec.rb' - - 'spec/convention/activesupport_concern_spec.rb' - - 'spec/convention/struct_definition_spec.rb' - - 'spec/convention_spec.rb' - - 'spec/diagnostics/base_spec.rb' - - 'spec/diagnostics/require_not_found_spec.rb' - - 'spec/diagnostics/rubocop_helpers_spec.rb' - - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/diagnostics/type_check_spec.rb' - - 'spec/diagnostics/update_errors_spec.rb' - - 'spec/diagnostics_spec.rb' - - 'spec/doc_map_spec.rb' - - 'spec/gem_pins_spec.rb' - - 'spec/language_server/host/diagnoser_spec.rb' - - 'spec/language_server/host/dispatch_spec.rb' - - 'spec/language_server/host/message_worker_spec.rb' - - 'spec/language_server/host_spec.rb' - - 'spec/language_server/message/completion_item/resolve_spec.rb' - - 'spec/language_server/message/extended/check_gem_version_spec.rb' - - 'spec/language_server/message/initialize_spec.rb' - - 'spec/language_server/message/text_document/definition_spec.rb' - - 'spec/language_server/message/text_document/formatting_spec.rb' - - 'spec/language_server/message/text_document/hover_spec.rb' - - 'spec/language_server/message/text_document/rename_spec.rb' - - 'spec/language_server/message/text_document/type_definition_spec.rb' - - 'spec/language_server/message/workspace/did_change_configuration_spec.rb' - - 'spec/language_server/message/workspace/did_change_watched_files_spec.rb' - - 'spec/language_server/message_spec.rb' - - 'spec/language_server/transport/adapter_spec.rb' - - 'spec/language_server/transport/data_reader_spec.rb' - - 'spec/language_server/uri_helpers_spec.rb' - - 'spec/library_spec.rb' - - 'spec/logging_spec.rb' - - 'spec/parser/flow_sensitive_typing_spec.rb' - - 'spec/parser/node_methods_spec.rb' - - 'spec/parser/node_processor_spec.rb' - - 'spec/parser_spec.rb' - - 'spec/pin/base_spec.rb' - - 'spec/pin/base_variable_spec.rb' - - 'spec/pin/block_spec.rb' - - 'spec/pin/constant_spec.rb' - - 'spec/pin/delegated_method_spec.rb' - - 'spec/pin/documenting_spec.rb' - - 'spec/pin/instance_variable_spec.rb' - - 'spec/pin/keyword_spec.rb' - - 'spec/pin/local_variable_spec.rb' - - 'spec/pin/method_spec.rb' - - 'spec/pin/namespace_spec.rb' - - 'spec/pin/parameter_spec.rb' - - 'spec/pin/search_spec.rb' - - 'spec/pin/symbol_spec.rb' - - 'spec/position_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' - - 'spec/rbs_map/core_map_spec.rb' - - 'spec/rbs_map/stdlib_map_spec.rb' - - 'spec/rbs_map_spec.rb' - - 'spec/shell_spec.rb' - - 'spec/source/chain/array_spec.rb' - - 'spec/source/chain/call_spec.rb' - - 'spec/source/chain/class_variable_spec.rb' - - 'spec/source/chain/constant_spec.rb' - - 'spec/source/chain/global_variable_spec.rb' - - 'spec/source/chain/head_spec.rb' - - 'spec/source/chain/instance_variable_spec.rb' - - 'spec/source/chain/link_spec.rb' - - 'spec/source/chain/literal_spec.rb' - - 'spec/source/chain/z_super_spec.rb' - - 'spec/source/chain_spec.rb' - - 'spec/source/change_spec.rb' - - 'spec/source/cursor_spec.rb' - - 'spec/source/source_chainer_spec.rb' - - 'spec/source/updater_spec.rb' - - 'spec/source_map/clip_spec.rb' - - 'spec/source_map/mapper_spec.rb' - - 'spec/source_map_spec.rb' - - 'spec/source_spec.rb' - - 'spec/type_checker/checks_spec.rb' - - 'spec/type_checker/levels/normal_spec.rb' - - 'spec/type_checker/levels/strict_spec.rb' - - 'spec/type_checker/levels/strong_spec.rb' - - 'spec/type_checker/levels/typed_spec.rb' - - 'spec/type_checker/rules_spec.rb' - - 'spec/type_checker_spec.rb' - - 'spec/workspace/config_spec.rb' - - 'spec/workspace_spec.rb' - - 'spec/yard_map/mapper/to_method_spec.rb' - - 'spec/yard_map/mapper_spec.rb' - -RSpec/StubbedMock: - Exclude: - - 'spec/language_server/host/message_worker_spec.rb' - # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. RSpec/VerifiedDoubles: Exclude: @@ -1833,7 +1702,6 @@ Style/FrozenStringLiteralComment: - 'spec/rbs_map/core_map_spec.rb' - 'spec/rbs_map/stdlib_map_spec.rb' - 'spec/rbs_map_spec.rb' - - 'spec/shell_spec.rb' - 'spec/source/chain/array_spec.rb' - 'spec/source/chain/call_spec.rb' - 'spec/source/chain/class_variable_spec.rb' @@ -1882,7 +1750,6 @@ Style/GuardClause: - 'lib/solargraph/api_map.rb' - 'lib/solargraph/library.rb' - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - - 'lib/solargraph/pin_cache.rb' - 'lib/solargraph/range.rb' - 'lib/solargraph/rbs_map/conversions.rb' - 'lib/solargraph/source.rb' @@ -1932,16 +1799,13 @@ Style/IfInsideElse: # This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/api_map/index.rb' - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/language_server/message/completion_item/resolve.rb' - 'lib/solargraph/language_server/message/initialize.rb' - 'lib/solargraph/language_server/message/text_document/completion.rb' - 'lib/solargraph/language_server/message/text_document/hover.rb' - - 'lib/solargraph/library.rb' - 'lib/solargraph/parser/parser_gem/class_methods.rb' - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - 'lib/solargraph/parser/parser_gem/node_methods.rb' @@ -1963,7 +1827,6 @@ Style/IfUnlessModifier: - 'lib/solargraph/source_map/clip.rb' - 'lib/solargraph/source_map/mapper.rb' - 'lib/solargraph/type_checker.rb' - - 'lib/solargraph/workspace.rb' - 'lib/solargraph/workspace/config.rb' - 'lib/solargraph/yard_map/helpers.rb' - 'lib/solargraph/yard_map/mapper/to_method.rb' @@ -2013,7 +1876,6 @@ Style/MethodDefParentheses: - 'lib/solargraph/convention/struct_definition/struct_assignment_node.rb' - 'lib/solargraph/convention/struct_definition/struct_definition_node.rb' - 'lib/solargraph/diagnostics/rubocop_helpers.rb' - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/equality.rb' - 'lib/solargraph/gem_pins.rb' - 'lib/solargraph/language_server/host/message_worker.rb' @@ -2050,7 +1912,6 @@ Style/MethodDefParentheses: - 'lib/solargraph/type_checker.rb' - 'lib/solargraph/type_checker/checks.rb' - 'lib/solargraph/yard_map/helpers.rb' - - 'lib/solargraph/yardoc.rb' - 'spec/doc_map_spec.rb' - 'spec/fixtures/rdoc-lib/lib/example.rb' - 'spec/source_map_spec.rb' @@ -2225,12 +2086,6 @@ Style/RedundantFreeze: - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/source_map/mapper.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -# Configuration parameters: AllowComments. -Style/RedundantInitialize: - Exclude: - - 'lib/solargraph/rbs_map/core_map.rb' - # This cop supports unsafe autocorrection (--autocorrect-all). Style/RedundantInterpolation: Exclude: @@ -2246,6 +2101,7 @@ Style/RedundantParentheses: - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - 'lib/solargraph/pin/method.rb' - 'lib/solargraph/pin/parameter.rb' + - 'lib/solargraph/pin/search.rb' - 'lib/solargraph/source.rb' - 'lib/solargraph/type_checker.rb' @@ -2258,24 +2114,13 @@ Style/RedundantRegexpArgument: - 'spec/diagnostics/rubocop_spec.rb' - 'spec/language_server/host_spec.rb' -# This cop supports safe autocorrection (--autocorrect). -Style/RedundantRegexpCharacterClass: - Exclude: - - 'lib/solargraph/source/cursor.rb' - - 'lib/solargraph/source/source_chainer.rb' - # This cop supports safe autocorrection (--autocorrect). Style/RedundantRegexpEscape: Exclude: - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/diagnostics/rubocop.rb' - 'lib/solargraph/language_server/uri_helpers.rb' - - 'lib/solargraph/parser/parser_gem/node_methods.rb' - - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin/parameter.rb' - 'lib/solargraph/shell.rb' - - 'lib/solargraph/source/change.rb' - - 'lib/solargraph/source/cursor.rb' - 'lib/solargraph/source_map/clip.rb' - 'lib/solargraph/source_map/mapper.rb' @@ -2285,7 +2130,6 @@ Style/RedundantReturn: Exclude: - 'lib/solargraph/api_map.rb' - 'lib/solargraph/complex_type/type_methods.rb' - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/parser/parser_gem/node_methods.rb' - 'lib/solargraph/source/chain/z_super.rb' @@ -2322,7 +2166,6 @@ Style/RescueStandardError: Style/SafeNavigation: Exclude: - 'lib/solargraph/api_map/index.rb' - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/language_server/message/completion_item/resolve.rb' - 'lib/solargraph/language_server/request.rb' - 'lib/solargraph/language_server/transport/data_reader.rb' @@ -2330,7 +2173,6 @@ Style/SafeNavigation: - 'lib/solargraph/pin/base.rb' - 'lib/solargraph/pin/conversions.rb' - 'lib/solargraph/pin/method.rb' - - 'lib/solargraph/pin_cache.rb' - 'lib/solargraph/range.rb' - 'lib/solargraph/type_checker.rb' @@ -2403,7 +2245,6 @@ Style/StringLiterals: - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/complex_type/unique_type.rb' - 'lib/solargraph/convention/struct_definition.rb' - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/language_server/host.rb' - 'lib/solargraph/language_server/message/extended/document_gems.rb' - 'lib/solargraph/language_server/message/extended/download_core.rb' @@ -2638,7 +2479,6 @@ YARD/MismatchName: Exclude: - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/complex_type/unique_type.rb' - - 'lib/solargraph/gem_pins.rb' - 'lib/solargraph/language_server/host.rb' - 'lib/solargraph/language_server/host/dispatch.rb' - 'lib/solargraph/language_server/request.rb' diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index f58633a0c..94b2c7fa0 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -29,6 +29,12 @@ def initialize pins: [] index pins end + # @param out [IO, nil] output stream for logging + # @return [void] + def self.reset_core out: nil + @@core_map = RbsMap::CoreMap.new + end + # # This is a mutable object, which is cached in the Chain class - # if you add any fields which change the results of calls (not @@ -46,6 +52,7 @@ def ==(other) self.eql?(other) end + # @return [Integer] def hash equality_fields.hash end @@ -95,11 +102,12 @@ def catalog bench end unresolved_requires = (bench.external_requires + implicit.requires + bench.workspace.config.required).to_a.compact.uniq recreate_docmap = @unresolved_requires != unresolved_requires || - @doc_map&.uncached_yard_gemspecs&.any? || - @doc_map&.uncached_rbs_collection_gemspecs&.any? || - @doc_map&.rbs_collection_path != bench.workspace.rbs_collection_path + workspace.rbs_collection_path != bench.workspace.rbs_collection_path || + @doc_map.any_uncached? + if recreate_docmap - @doc_map = DocMap.new(unresolved_requires, [], bench.workspace) # @todo Implement gem preferences + @doc_map = DocMap.new(unresolved_requires, [], bench.workspace, out: nil) # @todo Implement gem preferences + @gemspecs = @doc_map.workspace.gemspecs @unresolved_requires = @doc_map.unresolved_requires end @cache.clear if store.update(@@core_map.pins, @doc_map.pins, implicit.pins, iced_pins, live_pins) @@ -114,26 +122,14 @@ def catalog bench [self.class, @source_map_hash, implicit, @doc_map, @unresolved_requires] end - # @return [DocMap] - def doc_map - @doc_map ||= DocMap.new([], []) - end + # @return [DocMap, nil] + attr_reader :doc_map # @return [::Array] def uncached_gemspecs @doc_map&.uncached_gemspecs || [] end - # @return [::Array] - def uncached_rbs_collection_gemspecs - @doc_map.uncached_rbs_collection_gemspecs - end - - # @return [::Array] - def uncached_yard_gemspecs - @doc_map.uncached_yard_gemspecs - end - # @return [Enumerable] def core_pins @@core_map.pins @@ -177,6 +173,7 @@ def clip_at filename, position # Create an ApiMap with a workspace in the specified directory. # # @param directory [String] + # # @return [ApiMap] def self.load directory api_map = new @@ -190,8 +187,8 @@ def self.load directory # @param out [IO, nil] # @return [void] - def cache_all!(out) - @doc_map.cache_all!(out) + def cache_all_for_doc_map! out + @doc_map.cache_doc_map_gems!(out) end # @param gemspec [Gem::Specification] @@ -212,15 +209,16 @@ class << self # # @param directory [String] # @param out [IO] The output stream for messages + # # @return [ApiMap] - def self.load_with_cache directory, out + def self.load_with_cache directory, out = $stderr api_map = load(directory) if api_map.uncached_gemspecs.empty? logger.info { "All gems cached for #{directory}" } return api_map end - api_map.cache_all!(out) + api_map.cache_all_for_doc_map!(out) load(directory) end @@ -236,13 +234,6 @@ def keyword_pins store.pins_by_class(Pin::Keyword) end - # An array of namespace names defined in the ApiMap. - # - # @return [Set] - def namespaces - store.namespaces - end - # True if the namespace exists. # # @param name [String] The namespace to match @@ -326,7 +317,7 @@ def qualify tag, context_tag = '' # @param context_namespace [String] The context namespace in which the # tag was referenced; start from here to resolve the name # @return [String, nil] fully qualified namespace - def qualify_namespace(namespace, context_namespace = '') + def qualify_namespace namespace, context_namespace = '' cached = cache.get_qualified_namespace(namespace, context_namespace) return cached.clone unless cached.nil? result = if namespace.start_with?('::') @@ -356,7 +347,7 @@ def get_includes(fqns) # @param namespace [String] A fully qualified namespace # @param scope [Symbol] :instance or :class # @return [Array] - def get_instance_variable_pins(namespace, scope = :instance) + def get_instance_variable_pins namespace, scope = :instance result = [] used = [namespace] result.concat store.get_instance_variables(namespace, scope) @@ -369,8 +360,10 @@ def get_instance_variable_pins(namespace, scope = :instance) result end - # @sg-ignore Missing @return tag for Solargraph::ApiMap#visible_pins # @see Solargraph::Parser::FlowSensitiveTyping#visible_pins + # @param (see Solargraph::Parser::FlowSensitiveTyping#visible_pins) + # @sg-ignore Missing @return tag for Solargraph::ApiMap#visible_pins + # @return (see Solargraph::Parser::FlowSensitiveTyping#visible_pins) def visible_pins(*args, **kwargs, &blk) Solargraph::Parser::FlowSensitiveTyping.visible_pins(*args, **kwargs, &blk) end @@ -379,7 +372,7 @@ def visible_pins(*args, **kwargs, &blk) # # @param namespace [String] A fully qualified namespace # @return [Enumerable] - def get_class_variable_pins(namespace) + def get_class_variable_pins namespace prefer_non_nil_variables(store.get_class_variables(namespace)) end @@ -533,7 +526,8 @@ def get_complex_type_methods complex_type, context = '', internal = false # @param name [String] Method name to look up # @param scope [Symbol] :instance or :class # @param visibility [Array] :public, :protected, and/or :private - # @param preserve_generics [Boolean] + # @param preserve_generics [Boolean] True to preserve any + # unresolved generic parameters, false to erase them # @return [Array] def get_method_stack rooted_tag, name, scope: :instance, visibility: [:private, :protected, :public], preserve_generics: false rooted_type = ComplexType.parse(rooted_tag) @@ -559,7 +553,7 @@ def get_method_stack rooted_tag, name, scope: :instance, visibility: [:private, # @deprecated Use #get_path_pins instead. # # @param path [String] The path to find - # @return [Enumerable] + # @return [Array] def get_path_suggestions path return [] if path.nil? resolve_method_aliases store.get_path_pins(path) @@ -568,7 +562,7 @@ def get_path_suggestions path # Get an array of pins that match the specified path. # # @param path [String] - # @return [Enumerable] + # @return [Array] def get_path_pins path get_path_suggestions(path) end @@ -658,7 +652,7 @@ def bundled? filename # @param sup [String] The superclass # @param sub [String] The subclass # @return [Boolean] - def super_and_sub?(sup, sub) + def super_and_sub? sup, sub fqsup = qualify(sup) cls = qualify(sub) tested = [] @@ -677,7 +671,7 @@ def super_and_sub?(sup, sub) # @param module_ns [String] The module namespace (no type parameters) # # @return [Boolean] - def type_include?(host_ns, module_ns) + def type_include? host_ns, module_ns store.get_includes(host_ns).map { |inc_tag| ComplexType.parse(inc_tag).name }.include?(module_ns) end @@ -691,10 +685,17 @@ def resolve_method_aliases pins, visibility = [:public, :private, :protected] next nil if resolved.respond_to?(:visibility) && !visibility.include?(resolved.visibility) resolved end.compact - logger.debug { "ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}" } + logger.debug do + "ApiMap#resolve_method_aliases(pins=#{pins.map(&:name)}, visibility=#{visibility}) => #{with_resolved_aliases.map(&:name)}" + end GemPins.combine_method_pins_by_path(with_resolved_aliases) end + # @return [Workspace, nil] + def workspace + @doc_map&.workspace + end + # @param fq_reference_tag [String] A fully qualified whose method should be pulled in # @param namespace_pin [Pin::Base] Namespace pin for the rooted_type # parameter - used to pull generics information @@ -802,7 +803,8 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false end rooted_sc_tag = qualify_superclass(rooted_tag) unless rooted_sc_tag.nil? - result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, no_core) + result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, + visibility, true, skip, no_core) end else logger.info { "ApiMap#inner_get_methods(#{fqns}, #{scope}, #{visibility}, #{deep}, #{skip}) - looking for get_extends() from #{fqns}" } @@ -812,7 +814,8 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false end rooted_sc_tag = qualify_superclass(rooted_tag) unless rooted_sc_tag.nil? - result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, visibility, true, skip, true) + result.concat inner_get_methods_from_reference(rooted_sc_tag, namespace_pin, rooted_type, scope, + visibility, true, skip, true) end unless no_core || fqns.empty? type = get_namespace_type(fqns) @@ -846,9 +849,7 @@ def inner_get_constants fqns, visibility, skip result.concat inner_get_constants(qualify(is, fqns), [:public], skip) end fqsc = qualify_superclass(fqns) - unless %w[Object BasicObject].include?(fqsc) - result.concat inner_get_constants(fqsc, [:public], skip) - end + result.concat inner_get_constants(fqsc, [:public], skip) unless %w[Object BasicObject].include?(fqsc) result end @@ -951,8 +952,6 @@ def prefer_non_nil_variables pins include Logging - private - # @param alias_pin [Pin::MethodAlias] # @return [Pin::Method, nil] def resolve_method_alias(alias_pin) @@ -1027,7 +1026,7 @@ def create_resolved_alias_pin(alias_pin, original) # @param rooted_type [ComplexType] # @param pins [Enumerable] # @return [Array] - def erase_generics(namespace_pin, rooted_type, pins) + def erase_generics namespace_pin, rooted_type, pins return pins unless should_erase_generics_when_done?(namespace_pin, rooted_type) logger.debug("Erasing generics on namespace_pin=#{namespace_pin} / rooted_type=#{rooted_type}") @@ -1038,18 +1037,18 @@ def erase_generics(namespace_pin, rooted_type, pins) # @param namespace_pin [Pin::Namespace] # @param rooted_type [ComplexType] - def should_erase_generics_when_done?(namespace_pin, rooted_type) + def should_erase_generics_when_done? namespace_pin, rooted_type has_generics?(namespace_pin) && !can_resolve_generics?(namespace_pin, rooted_type) end # @param namespace_pin [Pin::Namespace] - def has_generics?(namespace_pin) + def has_generics? namespace_pin namespace_pin && !namespace_pin.generics.empty? end # @param namespace_pin [Pin::Namespace] # @param rooted_type [ComplexType] - def can_resolve_generics?(namespace_pin, rooted_type) + def can_resolve_generics? namespace_pin, rooted_type has_generics?(namespace_pin) && !rooted_type.all_params.empty? end end diff --git a/lib/solargraph/doc_map.rb b/lib/solargraph/doc_map.rb index 5fe5e03f9..880451592 100644 --- a/lib/solargraph/doc_map.rb +++ b/lib/solargraph/doc_map.rb @@ -5,122 +5,86 @@ require 'open3' module Solargraph - # A collection of pins generated from required gems. + # A collection of pins generated from specific 'require' statements + # in code. Multiple can be created per workspace, to represent the + # pins available in different files based on their particular + # 'require' lines. # class DocMap include Logging - # @return [Array] - attr_reader :requires - alias required requires + # @return [Workspace] + attr_reader :workspace # @return [Array] attr_reader :preferences - # @return [Array] - attr_reader :pins - - # @return [Array] - def uncached_gemspecs - uncached_yard_gemspecs.concat(uncached_rbs_collection_gemspecs) - .sort - .uniq { |gemspec| "#{gemspec.name}:#{gemspec.version}" } - end - - # @return [Array] - attr_reader :uncached_yard_gemspecs - - # @return [Array] - attr_reader :uncached_rbs_collection_gemspecs - - # @return [String, nil] - attr_reader :rbs_collection_path - - # @return [String, nil] - attr_reader :rbs_collection_config_path - - # @return [Workspace, nil] - attr_reader :workspace - - # @return [Environ] - attr_reader :environ - # @param requires [Array] # @param preferences [Array] - # @param workspace [Workspace, nil] - def initialize(requires, preferences, workspace = nil) - @requires = requires.compact + # @param workspace [Workspace] + # @param out [IO, nil] output stream for logging + def initialize requires, preferences, workspace, out: $stderr + @provided_requires = requires.compact @preferences = preferences.compact @workspace = workspace - @rbs_collection_path = workspace&.rbs_collection_path - @rbs_collection_config_path = workspace&.rbs_collection_config_path - @environ = Convention.for_global(self) - @requires.concat @environ.requires if @environ - load_serialized_gem_pins - pins.concat @environ.pins + @out = out end - # @param out [IO] - # @return [void] - def cache_all!(out) - # if we log at debug level: - if logger.info? - gem_desc = uncached_gemspecs.map { |gemspec| "#{gemspec.name}:#{gemspec.version}" }.join(', ') - logger.info "Caching pins for gems: #{gem_desc}" unless uncached_gemspecs.empty? - end - logger.debug { "Caching for YARD: #{uncached_yard_gemspecs.map(&:name)}" } - logger.debug { "Caching for RBS collection: #{uncached_rbs_collection_gemspecs.map(&:name)}" } - load_serialized_gem_pins - uncached_gemspecs.each do |gemspec| - cache(gemspec, out: out) + # @return [Array] + def requires + @requires ||= @provided_requires + (workspace.global_environ&.requires || []) + end + alias required requires + + # @return [Array] + def uncached_gemspecs + if @uncached_gemspecs.nil? + @uncached_gemspecs = [] + pins # force lazy-loaded pin lookup end - load_serialized_gem_pins - @uncached_rbs_collection_gemspecs = [] - @uncached_yard_gemspecs = [] + @uncached_gemspecs end - # @param gemspec [Gem::Specification] - # @param out [IO] - # @return [void] - def cache_yard_pins(gemspec, out) - pins = GemPins.build_yard_pins(yard_plugins, gemspec) - PinCache.serialize_yard_gem(gemspec, pins) - logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty? + # @return [Array] + def pins + @pins ||= load_serialized_gem_pins + (workspace.global_environ&.pins || []) end - # @param gemspec [Gem::Specification] - # @param out [IO] # @return [void] - def cache_rbs_collection_pins(gemspec, out) - rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path) - pins = rbs_map.pins - rbs_version_cache_key = rbs_map.cache_key - # cache pins even if result is zero, so we don't retry building pins - pins ||= [] - PinCache.serialize_rbs_collection_gem(gemspec, rbs_version_cache_key, pins) - logger.info { "Cached #{pins.length} RBS collection pins for gem #{gemspec.name} #{gemspec.version} with cache_key #{rbs_version_cache_key.inspect}" unless pins.empty? } + def reset_pins! + @uncached_gemspecs = nil + @pins = nil end - # @param gemspec [Gem::Specification] - # @param rebuild [Boolean] whether to rebuild the pins even if they are cached + # @return [Solargraph::PinCache] + def pin_cache + @pin_cache ||= workspace.fresh_pincache + end + + def any_uncached? + uncached_gemspecs.any? + end + + # Cache all pins needed for the sources in this doc_map # @param out [IO, nil] output stream for logging # @return [void] - def cache(gemspec, rebuild: false, out: nil) - build_yard = uncached_yard_gemspecs.include?(gemspec) || rebuild - build_rbs_collection = uncached_rbs_collection_gemspecs.include?(gemspec) || rebuild - if build_yard || build_rbs_collection - type = [] - type << 'YARD' if build_yard - type << 'RBS collection' if build_rbs_collection - out.puts("Caching #{type.join(' and ')} pins for gem #{gemspec.name}:#{gemspec.version}") if out + def cache_doc_map_gems! out + unless uncached_gemspecs.empty? + logger.info do + gem_desc = uncached_gemspecs.map { |gemspec| "#{gemspec.name}:#{gemspec.version}" }.join(', ') + "Caching pins for gems: #{gem_desc}" + end end - cache_yard_pins(gemspec, out) if build_yard - cache_rbs_collection_pins(gemspec, out) if build_rbs_collection - end - - # @return [Array] - def gemspecs - @gemspecs ||= required_gems_map.values.compact.flatten + time = Benchmark.measure do + uncached_gemspecs.each do |gemspec| + cache(gemspec, out: out) + end + end + milliseconds = (time.real * 1000).round + if (milliseconds > 500) && uncached_gemspecs.any? && out && uncached_gemspecs.any? + out.puts "Built #{uncached_gemspecs.length} gems in #{milliseconds} ms" + end + reset_pins! end # @return [Array] @@ -128,77 +92,81 @@ def unresolved_requires @unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys end - # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version - def self.all_yard_gems_in_memory - @yard_gems_in_memory ||= {} - end - - # @return [Hash{String => Hash{Array(String, String) => Array}}] stored by RBS collection path - def self.all_rbs_collection_gems_in_memory - @rbs_collection_gems_in_memory ||= {} - end - - # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version - def yard_pins_in_memory - self.class.all_yard_gems_in_memory - end - - # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version - def rbs_collection_pins_in_memory - self.class.all_rbs_collection_gems_in_memory[rbs_collection_path] ||= {} - end - - # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version - def self.all_combined_pins_in_memory - @combined_pins_in_memory ||= {} + # @return [Set] + # @param out [IO] + def dependencies out: $stderr + @dependencies ||= + begin + all_deps = gemspecs.flat_map { |spec| fetch_dependencies(spec, out: out) } + existing_gems = gemspecs.map(&:name) + all_deps.reject { |gemspec| existing_gems.include? gemspec.name }.to_set + end end - # @todo this should also include an index by the hash of the RBS collection - # @return [Hash{Array(String, String) => Array}] Indexed by gemspec name and version - def combined_pins_in_memory - self.class.all_combined_pins_in_memory + # Cache gem documentation if needed for this doc_map + # + # @param gemspec [Gem::Specification] + # @param rebuild [Boolean] whether to rebuild the pins even if they are cached + # @param out [IO, nil] output stream for logging + # + # @return [void] + def cache gemspec, rebuild: false, out: nil + pin_cache.cache_gem(gemspec: gemspec, + rebuild: rebuild, + out: out) end - # @return [Array] - def yard_plugins - @environ.yard_plugins - end + private - # @return [Set] - def dependencies - @dependencies ||= (gemspecs.flat_map { |spec| fetch_dependencies(spec) } - gemspecs).to_set + # @return [Array] + def gemspecs + @gemspecs ||= required_gems_map.values.compact.flatten end - private - - # @return [void] - def load_serialized_gem_pins - @pins = [] - @uncached_yard_gemspecs = [] - @uncached_rbs_collection_gemspecs = [] + # @param out [IO, nil] + # @return [Array] + def load_serialized_gem_pins out: @out + serialized_pins = [] with_gemspecs, without_gemspecs = required_gems_map.partition { |_, v| v } - # @sg-ignore Wrong argument type for Hash.[]: arg_0 expected _ToHash), undefined>, received Array)> + # @sg-ignore Need support for RBS duck interfaces like _ToHash # @type [Array] - paths = Hash[without_gemspecs].keys - # @sg-ignore Wrong argument type for Hash.[]: arg_0 expected _ToHash), undefined>, received Array)> + missing_paths = Hash[without_gemspecs].keys + # @sg-ignore Need support for RBS duck interfaces like _ToHash # @type [Array] - gemspecs = Hash[with_gemspecs].values.flatten.compact + dependencies.to_a - - paths.each do |path| - rbs_pins = deserialize_stdlib_rbs_map path + gemspecs = Hash[with_gemspecs].values.flatten.compact + dependencies(out: out).to_a + + missing_paths.each do |path| + # this will load from disk if needed; no need to manage + # uncached_gemspecs to trigger that later + stdlib_name_guess = path.split('/').first + + # try to resolve the stdlib name + deps = workspace.stdlib_dependencies(stdlib_name_guess) || [] + [stdlib_name_guess, *deps].compact.each do |potential_stdlib_name| + rbs_pins = pin_cache.cache_stdlib_rbs_map potential_stdlib_name + serialized_pins.concat rbs_pins if rbs_pins + end end - logger.debug { "DocMap#load_serialized_gem_pins: Combining pins..." } + existing_pin_count = serialized_pins.length time = Benchmark.measure do gemspecs.each do |gemspec| - pins = deserialize_combined_pin_cache gemspec - @pins.concat pins if pins + # only deserializes already-cached gems + gemspec_pins = pin_cache.deserialize_combined_pin_cache gemspec + if gemspec_pins + serialized_pins.concat gemspec_pins + else + uncached_gemspecs << gemspec + end end end - logger.info { "DocMap#load_serialized_gem_pins: Loaded and processed serialized pins together in #{time.real} seconds" } - @uncached_yard_gemspecs.uniq! - @uncached_rbs_collection_gemspecs.uniq! - nil + pins_processed = serialized_pins.length - existing_pin_count + milliseconds = (time.real * 1000).round + if (milliseconds > 500) && out && gemspecs.any? + out.puts "Deserialized #{serialized_pins.length} gem pins from #{PinCache.base_dir} in #{milliseconds} ms" + end + uncached_gemspecs.uniq! { |gemspec| "#{gemspec.name}:#{gemspec.version}" } + serialized_pins end # @return [Hash{String => Array}] @@ -211,102 +179,6 @@ def preference_map @preference_map ||= preferences.to_h { |gemspec| [gemspec.name, gemspec] } end - # @param gemspec [Gem::Specification] - # @return [Array] - def deserialize_yard_pin_cache gemspec - if yard_pins_in_memory.key?([gemspec.name, gemspec.version]) - return yard_pins_in_memory[[gemspec.name, gemspec.version]] - end - - cached = PinCache.deserialize_yard_gem(gemspec) - if cached - logger.info { "Loaded #{cached.length} cached YARD pins from #{gemspec.name}:#{gemspec.version}" } - yard_pins_in_memory[[gemspec.name, gemspec.version]] = cached - cached - else - logger.debug "No YARD pin cache for #{gemspec.name}:#{gemspec.version}" - @uncached_yard_gemspecs.push gemspec - nil - end - end - - # @param gemspec [Gem::Specification] - # @return [void] - def deserialize_combined_pin_cache(gemspec) - unless combined_pins_in_memory[[gemspec.name, gemspec.version]].nil? - return combined_pins_in_memory[[gemspec.name, gemspec.version]] - end - - rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path) - rbs_version_cache_key = rbs_map.cache_key - - cached = PinCache.deserialize_combined_gem(gemspec, rbs_version_cache_key) - if cached - logger.info { "Loaded #{cached.length} cached YARD pins from #{gemspec.name}:#{gemspec.version}" } - combined_pins_in_memory[[gemspec.name, gemspec.version]] = cached - return combined_pins_in_memory[[gemspec.name, gemspec.version]] - end - - rbs_collection_pins = deserialize_rbs_collection_cache gemspec, rbs_version_cache_key - - yard_pins = deserialize_yard_pin_cache gemspec - - if !rbs_collection_pins.nil? && !yard_pins.nil? - logger.debug { "Combining pins for #{gemspec.name}:#{gemspec.version}" } - combined_pins = GemPins.combine(yard_pins, rbs_collection_pins) - PinCache.serialize_combined_gem(gemspec, rbs_version_cache_key, combined_pins) - combined_pins_in_memory[[gemspec.name, gemspec.version]] = combined_pins - logger.info { "Generated #{combined_pins_in_memory[[gemspec.name, gemspec.version]].length} combined pins for #{gemspec.name} #{gemspec.version}" } - return combined_pins - end - - if !yard_pins.nil? - logger.debug { "Using only YARD pins for #{gemspec.name}:#{gemspec.version}" } - combined_pins_in_memory[[gemspec.name, gemspec.version]] = yard_pins - return combined_pins_in_memory[[gemspec.name, gemspec.version]] - elsif !rbs_collection_pins.nil? - logger.debug { "Using only RBS collection pins for #{gemspec.name}:#{gemspec.version}" } - combined_pins_in_memory[[gemspec.name, gemspec.version]] = rbs_collection_pins - return combined_pins_in_memory[[gemspec.name, gemspec.version]] - else - logger.debug { "Pins not yet cached for #{gemspec.name}:#{gemspec.version}" } - return nil - end - end - - # @param path [String] require path that might be in the RBS stdlib collection - # @return [void] - def deserialize_stdlib_rbs_map path - map = RbsMap::StdlibMap.load(path) - if map.resolved? - logger.debug { "Loading stdlib pins for #{path}" } - @pins.concat map.pins - logger.debug { "Loaded #{map.pins.length} stdlib pins for #{path}" } - map.pins - else - # @todo Temporarily ignoring unresolved `require 'set'` - logger.debug { "Require path #{path} could not be resolved in RBS" } unless path == 'set' - nil - end - end - - # @param gemspec [Gem::Specification] - # @param rbs_version_cache_key [String] - # @return [Array, nil] - def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key - return if rbs_collection_pins_in_memory.key?([gemspec, rbs_version_cache_key]) - cached = PinCache.deserialize_rbs_collection_gem(gemspec, rbs_version_cache_key) - if cached - logger.info { "Loaded #{cached.length} pins from RBS collection cache for #{gemspec.name}:#{gemspec.version}" } unless cached.empty? - rbs_collection_pins_in_memory[[gemspec, rbs_version_cache_key]] = cached - cached - else - logger.debug "No RBS collection pin cache for #{gemspec.name} #{gemspec.version}" - @uncached_rbs_collection_gemspecs.push gemspec - nil - end - end - # @param path [String] # @return [::Array, nil] def resolve_path_to_gemspecs path @@ -354,8 +226,10 @@ def change_gemspec_version gemspec, version end # @param gemspec [Gem::Specification] + # @param out [IO, nil] + # # @return [Array] - def fetch_dependencies gemspec + def fetch_dependencies gemspec, out: nil # @param spec [Gem::Dependency] only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps| Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}" diff --git a/lib/solargraph/gem_pins.rb b/lib/solargraph/gem_pins.rb index a193a8a39..3b61b6a65 100644 --- a/lib/solargraph/gem_pins.rb +++ b/lib/solargraph/gem_pins.rb @@ -41,15 +41,6 @@ def self.combine_method_pins(*pins) out end - # @param yard_plugins [Array] The names of YARD plugins to use. - # @param gemspec [Gem::Specification] - # @return [Array] - def self.build_yard_pins(yard_plugins, gemspec) - Yardoc.cache(yard_plugins, gemspec) unless Yardoc.cached?(gemspec) - yardoc = Yardoc.load!(gemspec) - YardMap::Mapper.new(yardoc, gemspec).map - end - # @param yard_pins [Array] # @param rbs_pins [Array] # @@ -68,7 +59,9 @@ def self.combine(yard_pins, rbs_pins) end out = combine_method_pins(rbs_pin, yard_pin) - logger.debug { "GemPins.combine: Combining yard.path=#{yard_pin.path} - rbs=#{rbs_pin.inspect} with yard=#{yard_pin.inspect} into #{out}" } + logger.debug do + "GemPins.combine: Combining yard.path=#{yard_pin.path} - rbs=#{rbs_pin.inspect} with yard=#{yard_pin.inspect} into #{out}" + end out end in_rbs_only = rbs_pins.select do |pin| diff --git a/lib/solargraph/library.rb b/lib/solargraph/library.rb index 9d5162431..9b4072d69 100644 --- a/lib/solargraph/library.rb +++ b/lib/solargraph/library.rb @@ -1,9 +1,16 @@ # frozen_string_literal: true +require 'rubygems' require 'pathname' require 'observer' require 'open3' +# @!parse +# class ::Gem::Specification +# # @return [String] +# def name; end +# end + module Solargraph # A Library handles coordination between a Workspace and an ApiMap. # @@ -273,12 +280,12 @@ def references_from filename, line, column, strip: false, only: false # HACK: for language clients that exclude special characters from the start of variable names if strip && match = cursor.word.match(/^[^a-z0-9_]+/i) found.map! do |loc| - Solargraph::Location.new(loc.filename, Solargraph::Range.from_to(loc.range.start.line, loc.range.start.column + match[0].length, loc.range.ending.line, loc.range.ending.column)) + Solargraph::Location.new(loc.filename, + Solargraph::Range.from_to(loc.range.start.line, loc.range.start.column + match[0].length, loc.range.ending.line, + loc.range.ending.column)) end end - result.concat(found.sort do |a, b| - a.range.start.line <=> b.range.start.line - end) + result.concat(found.sort { |a, b| a.range.start.line <=> b.range.start.line }) end result.uniq end @@ -303,9 +310,7 @@ def locate_ref location return nil if pin.nil? # @param full [String] return_if_match = proc do |full| - if source_map_hash.key?(full) - return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0)) - end + return Location.new(full, Solargraph::Range.from_to(0, 0, 0, 0)) if source_map_hash.key?(full) end workspace.require_paths.each do |path| full = File.join path, pin.name @@ -500,7 +505,12 @@ def external_requires private - # @return [Hash{String => Array}] + # @return [PinCache] + def pin_cache + workspace.pin_cache + end + + # @return [Hash{String => Set}] def source_map_external_require_hash @source_map_external_require_hash ||= {} end @@ -580,12 +590,13 @@ def cache_errors def cache_next_gemspec return if @cache_progress + # @type [Gem::Specification] spec = cacheable_specs.first return end_cache_progress unless spec pending = api_map.uncached_gemspecs.length - cache_errors.length - 1 - if Yardoc.processing?(spec) + if pin_cache.yardoc_processing?(spec) logger.info "Enqueuing cache of #{spec.name} #{spec.version} (already being processed)" queued_gemspec_cache.push(spec) return if pending - queued_gemspec_cache.length < 1 @@ -596,7 +607,11 @@ def cache_next_gemspec logger.info "Caching #{spec.name} #{spec.version}" Thread.new do report_cache_progress spec.name, pending - _o, e, s = Open3.capture3(workspace.command_path, 'cache', spec.name, spec.version.to_s) + kwargs = {} + kwargs[:chdir] = workspace.directory.to_s if workspace.directory && !workspace.directory.empty? + # @sg-ignore Unresolved call to capture3 on Module + _o, e, s = Open3.capture3(workspace.command_path, 'cache', spec.name, spec.version.to_s, + **kwargs) if s.success? logger.info "Cached #{spec.name} #{spec.version}" else @@ -613,8 +628,7 @@ def cache_next_gemspec # @return [Array] def cacheable_specs - cacheable = api_map.uncached_yard_gemspecs + - api_map.uncached_rbs_collection_gemspecs - + cacheable = api_map.uncached_gemspecs + queued_gemspec_cache - cache_errors.to_a return cacheable unless cacheable.empty? @@ -673,8 +687,7 @@ def sync_catalog source_map_hash.values.each { |map| find_external_requires(map) } api_map.catalog bench logger.info "Catalog complete (#{api_map.source_maps.length} files, #{api_map.pins.length} pins)" - logger.info "#{api_map.uncached_yard_gemspecs.length} uncached YARD gemspecs" - logger.info "#{api_map.uncached_rbs_collection_gemspecs.length} uncached RBS collection gemspecs" + logger.info "#{api_map.uncached_gemspecs.length} uncached gemspecs" cache_next_gemspec @sync_count = 0 end diff --git a/lib/solargraph/parser/parser_gem/class_methods.rb b/lib/solargraph/parser/parser_gem/class_methods.rb index ddc742bd8..50c537531 100644 --- a/lib/solargraph/parser/parser_gem/class_methods.rb +++ b/lib/solargraph/parser/parser_gem/class_methods.rb @@ -32,6 +32,9 @@ def parse code, filename = nil, line = 0 buffer = ::Parser::Source::Buffer.new(filename, line) buffer.source = code parser.parse(buffer) + # @sg-ignore Unresolved type Parser::SyntaxError, + # Parser::UnknownEncodingInMagicComment for variable e + # https://github.com/castwide/solargraph/pull/1005 rescue ::Parser::SyntaxError, ::Parser::UnknownEncodingInMagicComment => e raise Parser::SyntaxError, e.message end diff --git a/lib/solargraph/pin_cache.rb b/lib/solargraph/pin_cache.rb index 2a0ec4639..8c47cfef4 100644 --- a/lib/solargraph/pin_cache.rb +++ b/lib/solargraph/pin_cache.rb @@ -1,12 +1,424 @@ -require 'yard-activesupport-concern' require 'fileutils' require 'rbs' +require 'rubygems' module Solargraph - module PinCache + class PinCache + include Logging + + attr_reader :directory, :rbs_collection_path, :rbs_collection_config_path, :yard_plugins + + # @param rbs_collection_path [String, nil] + # @param rbs_collection_config_path [String, nil] + # @param directory [String, nil] + # @param yard_plugins [Array] + def initialize rbs_collection_path:, rbs_collection_config_path:, + directory:, + yard_plugins: + @rbs_collection_path = rbs_collection_path + @rbs_collection_config_path = rbs_collection_config_path + @directory = directory + @yard_plugins = yard_plugins + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + def cached? gemspec + rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec) + combined_gem?(gemspec, rbs_version_cache_key) + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param rebuild [Boolean] whether to rebuild the cache regardless of whether it already exists + # @param out [IO, nil] output stream for logging + # @return [void] + def cache_gem gemspec:, rebuild: false, out: nil + rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec) + + build_yard, build_rbs_collection, build_combined = + calculate_build_needs(gemspec, + rebuild: rebuild, + rbs_version_cache_key: rbs_version_cache_key) + + return unless build_yard || build_rbs_collection || build_combined + + build_combine_and_cache(gemspec, + rbs_version_cache_key, + build_yard: build_yard, + build_rbs_collection: build_rbs_collection, + build_combined: build_combined, + out: out) + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param rbs_version_cache_key [String] + def suppress_yard_cache? gemspec, rbs_version_cache_key + if gemspec.name == 'parser' && rbs_version_cache_key != RbsMap::CACHE_KEY_UNRESOLVED + # parser takes forever to build YARD pins, but has excellent RBS collection pins + return true + end + false + end + + # @param out [IO, nil] output stream for logging + # + # @return [void] + def cache_all_stdlibs out: $stderr + possible_stdlibs.each do |stdlib| + RbsMap::StdlibMap.new(stdlib, out: out) + end + end + + # @param path [String] require path that might be in the RBS stdlib collection + # @return [void] + def cache_stdlib_rbs_map path + # these are held in memory in RbsMap::StdlibMap + map = RbsMap::StdlibMap.load(path) + if map.resolved? + logger.debug { "Loading stdlib pins for #{path}" } + pins = map.pins + logger.debug { "Loaded #{pins.length} stdlib pins for #{path}" } + pins + else + # @todo Temporarily ignoring unresolved `require 'set'` + logger.debug { "Require path #{path} could not be resolved in RBS" } unless path == 'set' + nil + end + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # + # @return [String] + def lookup_rbs_version_cache_key gemspec + rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path) + rbs_map.cache_key + end + + # @param gemspec [Gem::Specification] + # @param rbs_version_cache_key [String] + # @param yard_pins [Array] + # @param rbs_collection_pins [Array] + # @return [void] + def cache_combined_pins gemspec, rbs_version_cache_key, yard_pins, rbs_collection_pins + combined_pins = GemPins.combine(yard_pins, rbs_collection_pins) + serialize_combined_gem(gemspec, rbs_version_cache_key, combined_pins) + end + + # @param gemspec [Gem::Specification] + # @return [Array] + def deserialize_combined_pin_cache gemspec + rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec) + + load_combined_gem(gemspec, rbs_version_cache_key) + end + + # @param gemspec [Gem::Specification] + # @param out [IO, nil] + # @return [void] + def uncache_gem gemspec, out: nil + PinCache.uncache(yardoc_path(gemspec), out: out) + PinCache.uncache(yard_gem_path(gemspec), out: out) + uncache_by_prefix(rbs_collection_pins_path_prefix(gemspec), out: out) + uncache_by_prefix(combined_path_prefix(gemspec), out: out) + combined_pins_in_memory.delete([gemspec.name, gemspec.version]) + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + def yardoc_processing? gemspec + Yardoc.processing?(yardoc_path(gemspec)) + end + + # @return [Array] a list of possible standard library names + def possible_stdlibs + # all dirs and .rb files in Gem::RUBYGEMS_DIR + Dir.glob(File.join(Gem::RUBYGEMS_DIR, '*')).map do |file_or_dir| + basename = File.basename(file_or_dir) + # remove .rb + basename = basename[0..-4] if basename.end_with?('.rb') + basename + end.sort.uniq + rescue StandardError => e + logger.info { "Failed to get possible stdlibs: #{e.message}" } + logger.debug { e.backtrace.join("\n") } + [] + end + + private + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param rebuild [Boolean] whether to rebuild the cache regardless of whether it already exists + # @param rbs_version_cache_key [String, nil] the cache key for the gem in the RBS collection + # + # @return [Array(Boolean, Boolean, Boolean)] whether to build YARD + # pins, RBS collection pins, and combined pins + def calculate_build_needs gemspec, rebuild:, rbs_version_cache_key: + if rebuild + build_yard = true + build_rbs_collection = true + build_combined = true + else + build_yard = !yard_gem?(gemspec) + build_rbs_collection = !rbs_collection_pins?(gemspec, rbs_version_cache_key) + build_combined = !combined_gem?(gemspec, rbs_version_cache_key) || build_yard || build_rbs_collection + end + + build_yard = false if suppress_yard_cache?(gemspec, rbs_version_cache_key) + + [build_yard, build_rbs_collection, build_combined] + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param rbs_version_cache_key [String, nil] + # @param build_yard [Boolean] + # @param build_rbs_collection [Boolean] + # @param build_combined [Boolean] + # @param out [IO, nil] + # + # @return [void] + def build_combine_and_cache gemspec, + rbs_version_cache_key, + build_yard:, + build_rbs_collection:, + build_combined:, + out: + log_cache_info(gemspec, rbs_version_cache_key, + build_yard: build_yard, + build_rbs_collection: build_rbs_collection, + build_combined: build_combined, + out: out) + cache_yard_pins(gemspec, out) if build_yard + # this can be nil even if we aren't told to build it - see suppress_yard_cache? + yard_pins = deserialize_yard_pin_cache(gemspec) || [] + cache_rbs_collection_pins(gemspec, out) if build_rbs_collection + rbs_collection_pins = deserialize_rbs_collection_cache(gemspec, rbs_version_cache_key) || [] + cache_combined_pins(gemspec, rbs_version_cache_key, yard_pins, rbs_collection_pins) if build_combined + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param rbs_version_cache_key [String, nil] + # @param build_yard [Boolean] + # @param build_rbs_collection [Boolean] + # @param build_combined [Boolean] + # @param out [IO, nil] + # + # @return [void] + def log_cache_info gemspec, + rbs_version_cache_key, + build_yard:, + build_rbs_collection:, + build_combined:, + out: + type = [] + type << 'YARD' if build_yard + rbs_source_desc = RbsMap.rbs_source_desc(rbs_version_cache_key) + type << rbs_source_desc if build_rbs_collection && !rbs_source_desc.nil? + # we'll build it anyway, but it won't take long to build with + # only a single source + + # 'combining' is awkward terminology in this case + just_yard = build_yard && rbs_source_desc.nil? + + type << 'combined' if build_combined && !just_yard + out&.puts("Caching #{type.join(' and ')} pins for gem #{gemspec.name}:#{gemspec.version}") + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param out [IO, nil] + # @return [Array] + def cache_yard_pins gemspec, out + gem_yardoc_path = yardoc_path(gemspec) + Yardoc.build_docs(gem_yardoc_path, yard_plugins, gemspec) unless Yardoc.docs_built?(gem_yardoc_path) + pins = Yardoc.build_pins(gem_yardoc_path, gemspec, out: out) + serialize_yard_gem(gemspec, pins) + logger.info { "Cached #{pins.length} YARD pins for gem #{gemspec.name}:#{gemspec.version}" } unless pins.empty? + pins + end + + # @return [Hash{Array(String, String, String) => Array}] + def combined_pins_in_memory + PinCache.all_combined_pins_in_memory[yard_plugins] ||= {} + end + + # @param gemspec [Gem::Specification] + # @param _out [IO, nil] + # @return [Array] + def cache_rbs_collection_pins gemspec, _out + rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path) + pins = rbs_map.pins + rbs_version_cache_key = rbs_map.cache_key + # cache pins even if result is zero, so we don't retry building pins + pins ||= [] + serialize_rbs_collection_pins(gemspec, rbs_version_cache_key, pins) + logger.info do + unless pins.empty? + "Cached #{pins.length} RBS collection pins for gem #{gemspec.name} #{gemspec.version} with " \ + "cache_key #{rbs_version_cache_key.inspect}" + end + end + pins + end + + # @param gemspec [Gem::Specification] + # @return [Array] + def deserialize_yard_pin_cache gemspec + cached = load_yard_gem(gemspec) + if cached + cached + else + logger.debug "No YARD pin cache for #{gemspec.name}:#{gemspec.version}" + nil + end + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param rbs_version_cache_key [String] + # @return [Array] + def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key + cached = load_rbs_collection_pins(gemspec, rbs_version_cache_key) + Solargraph.assert_or_log(:pin_cache_rbs_collection, 'Asked for non-existent rbs collection') if cached.nil? + logger.info do + "Loaded #{cached&.length} pins from RBS collection cache for #{gemspec.name}:#{gemspec.version}" + end + cached + end + + # @return [Array] + def yard_path_components + ["yard-#{YARD::VERSION}", + yard_plugins.sort.uniq.join('-')] + end + + # @param gemspec [Gem::Specification] + # @return [String] + def yardoc_path gemspec + File.join(PinCache.base_dir, + *yard_path_components, + "#{gemspec.name}-#{gemspec.version}.yardoc") + end + + # @param gemspec [Gem::Specification] + # @return [String] + def yard_gem_path gemspec + File.join(PinCache.work_dir, *yard_path_components, "#{gemspec.name}-#{gemspec.version}.ser") + end + + # @param gemspec [Gem::Specification] + # @return [Array, nil] + def load_yard_gem gemspec + PinCache.load(yard_gem_path(gemspec)) + end + + # @param gemspec [Gem::Specification] + # @param pins [Array] + # @return [void] + def serialize_yard_gem gemspec, pins + PinCache.save(yard_gem_path(gemspec), pins) + end + + # @param gemspec [Gem::Specification] + # @return [Boolean] + def yard_gem? gemspec + exist?(yard_gem_path(gemspec)) + end + + # @param gemspec [Gem::Specification] + # @param hash [String, nil] + # @return [String] + def rbs_collection_pins_path gemspec, hash + rbs_collection_pins_path_prefix(gemspec) + "#{hash || 0}.ser" + end + + # @param gemspec [Gem::Specification] + # @return [String] + def rbs_collection_pins_path_prefix gemspec + File.join(PinCache.work_dir, 'rbs', "#{gemspec.name}-#{gemspec.version}-") + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param hash [String] + # + # @return [Array, nil] + def load_rbs_collection_pins gemspec, hash + PinCache.load(rbs_collection_pins_path(gemspec, hash)) + end + + # @param gemspec [Gem::Specification] + # @param hash [String, nil] + # @param pins [Array] + # @return [void] + def serialize_rbs_collection_pins gemspec, hash, pins + PinCache.save(rbs_collection_pins_path(gemspec, hash), pins) + end + + # @param gemspec [Gem::Specification] + # @param hash [String, nil] + # @return [String] + def combined_path gemspec, hash + File.join(combined_path_prefix(gemspec) + "-#{hash || 0}.ser") + end + + # @param gemspec [Gem::Specification] + # @return [String] + def combined_path_prefix gemspec + File.join(PinCache.work_dir, 'combined', yard_plugins.sort.join('-'), "#{gemspec.name}-#{gemspec.version}") + end + + # @param gemspec [Gem::Specification] + # @param hash [String, nil] + # @param pins [Array] + # @return [void] + def serialize_combined_gem gemspec, hash, pins + PinCache.save(combined_path(gemspec, hash), pins) + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param hash [String] + def combined_gem? gemspec, hash + exist?(combined_path(gemspec, hash)) + end + + # @param gemspec [Gem::Specification] + # @param hash [String, nil] + # @return [Array, nil] + def load_combined_gem gemspec, hash + PinCache.load(combined_path(gemspec, hash)) + end + + # @param gemspec [Gem::Specification] + # @param hash [String] + def rbs_collection_pins? gemspec, hash + exist?(rbs_collection_pins_path(gemspec, hash)) + end + + include Logging + + # @param path [String] + def exist? *path + File.file? File.join(*path) + end + + # @return [void] + # @param path_segments [Array] + def uncache_by_prefix *path_segments, out: nil + path = File.join(*path_segments) + glob = "#{path}*" + out&.puts "Clearing pin cache in #{glob}" + Dir.glob(glob).each do |file| + next unless File.file?(file) + FileUtils.rm_rf file, secure: true + out&.puts "Clearing pin cache in #{file}" + end + end + class << self include Logging + # @return [Hash{Array => Hash{Array(String, String) => + # Array}}] yard plugins, then gemspec name and + # version + def all_combined_pins_in_memory + @all_combined_pins_in_memory ||= {} + end + # The base directory where cached YARD documentation and serialized pins are serialized # # @return [String] @@ -18,6 +430,32 @@ def base_dir File.join(Dir.home, '.cache', 'solargraph') end + # @param path_segments [Array] + # @return [void] + def uncache *path_segments, out: nil + path = File.join(*path_segments) + if File.exist?(path) + FileUtils.rm_rf path, secure: true + out&.puts "Clearing pin cache in #{path}" + else + out&.puts "Pin cache file #{path} does not exist" + end + end + + # @param out [IO, nil] + # @return [void] + def uncache_core out: nil + uncache(core_path, out: out) + # ApiMap keep this in memory + ApiMap.reset_core(out: out) + end + + # @param out [IO, nil] + # @return [void] + def uncache_stdlib out: nil + uncache(stdlib_path, out: out) + end + # The working directory for the current Ruby, RBS, and Solargraph versions. # # @return [String] @@ -27,15 +465,6 @@ def work_dir File.join(base_dir, "ruby-#{RUBY_VERSION}", "rbs-#{RBS::VERSION}", "solargraph-#{Solargraph::VERSION}") end - # @param gemspec [Gem::Specification] - # @return [String] - def yardoc_path gemspec - File.join(base_dir, - "yard-#{YARD::VERSION}", - "yard-activesupport-concern-#{YARD::ActiveSupport::Concern::VERSION}", - "#{gemspec.name}-#{gemspec.version}.yardoc") - end - # @return [String] def stdlib_path File.join(work_dir, 'stdlib') @@ -164,33 +593,11 @@ def has_rbs_collection?(gemspec, hash) exist?(rbs_collection_path(gemspec, hash)) end - # @return [void] - def uncache_core - uncache(core_path) - end - - # @return [void] - def uncache_stdlib - uncache(stdlib_path) - end - - # @param gemspec [Gem::Specification] - # @param out [IO, nil] - # @return [void] - def uncache_gem(gemspec, out: nil) - uncache(yardoc_path(gemspec), out: out) - uncache_by_prefix(rbs_collection_path_prefix(gemspec), out: out) - uncache(yard_gem_path(gemspec), out: out) - uncache_by_prefix(combined_path_prefix(gemspec), out: out) - end - # @return [void] def clear FileUtils.rm_rf base_dir, secure: true end - private - # @param file [String] # @return [Array, nil] def load file @@ -202,11 +609,6 @@ def load file nil end - # @param path [String] - def exist? *path - File.file? File.join(*path) - end - # @param file [String] # @param pins [Array] # @return [void] @@ -218,27 +620,19 @@ def save file, pins logger.debug { "Cache#save: Saved #{pins.length} pins to #{file}" } end - # @param path_segments [Array] - # @return [void] - def uncache *path_segments, out: nil - path = File.join(*path_segments) - if File.exist?(path) - FileUtils.rm_rf path, secure: true - out.puts "Clearing pin cache in #{path}" unless out.nil? - end + def core? + File.file?(core_path) end - # @return [void] - # @param path_segments [Array] - def uncache_by_prefix *path_segments, out: nil - path = File.join(*path_segments) - glob = "#{path}*" - out.puts "Clearing pin cache in #{glob}" unless out.nil? - Dir.glob(glob).each do |file| - next unless File.file?(file) - FileUtils.rm_rf file, secure: true - out.puts "Clearing pin cache in #{file}" unless out.nil? - end + # @param out [IO, nil] + # @return [Array] + def cache_core out: $stderr + RbsMap::CoreMap.new.cache_core(out: out) + end + + # @param path [String] + def exist? *path + File.file? File.join(*path) end end end diff --git a/lib/solargraph/rbs_map.rb b/lib/solargraph/rbs_map.rb index c6c10bac6..f6309bb55 100644 --- a/lib/solargraph/rbs_map.rb +++ b/lib/solargraph/rbs_map.rb @@ -23,10 +23,11 @@ class RbsMap attr_reader :rbs_collection_config_path # @param library [String] - # @param version [String, nil + # @param version [String, nil] # @param rbs_collection_config_path [String, Pathname, nil] # @param rbs_collection_paths [Array] - def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: [] + # @param out [IO, nil] where to log messages + def initialize library, version = nil, rbs_collection_config_path: nil, rbs_collection_paths: [], out: $stderr if rbs_collection_config_path.nil? && !rbs_collection_paths.empty? raise 'Please provide rbs_collection_config_path if you provide rbs_collection_paths' end @@ -37,6 +38,28 @@ def initialize library, version = nil, rbs_collection_config_path: nil, rbs_coll add_library loader, library, version end + CACHE_KEY_GEM_EXPORT = 'gem-export' + CACHE_KEY_UNRESOLVED = 'unresolved' + CACHE_KEY_STDLIB = 'stdlib' + CACHE_KEY_LOCAL = 'local' + + # @param cache_key [String] + # @return [String, nil] a description of the source of the RBS info + def self.rbs_source_desc cache_key + case cache_key + when CACHE_KEY_GEM_EXPORT + 'RBS gem export' + when CACHE_KEY_UNRESOLVED + nil + when CACHE_KEY_STDLIB + 'RBS standard library' + when CACHE_KEY_LOCAL + 'local RBS shims' + else + 'RBS collection' + end + end + # @return [RBS::EnvironmentLoader] def loader @loader ||= RBS::EnvironmentLoader.new(core_root: nil, repository: repository) @@ -47,9 +70,13 @@ def loader # updated upstream for the same library and version. May change # if the config for where information comes form changes. def cache_key + return CACHE_KEY_UNRESOLVED unless resolved? + @hextdigest ||= begin # @type [String, nil] data = nil + # @type gem_config [nil, Hash{String => Hash{String => String}}] + gem_config = nil if rbs_collection_config_path lockfile_path = RBS::Collection::Config.to_lockfile_path(Pathname.new(rbs_collection_config_path)) if lockfile_path.exist? @@ -58,21 +85,26 @@ def cache_key data = gem_config&.to_s end end - if data.nil? || data.empty? - if resolved? - # definitely came from the gem itself and not elsewhere - - # only one version per gem - 'gem-export' + if gem_config.nil? + CACHE_KEY_STDLIB + else + # @type [String] + source = gem_config.dig('source', 'type') + case source + when 'rubygems' + CACHE_KEY_GEM_EXPORT + when 'local' + CACHE_KEY_LOCAL + when 'stdlib' + CACHE_KEY_STDLIB else - 'unresolved' + Digest::SHA1.hexdigest(data) end - else - Digest::SHA1.hexdigest(data) end end end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @param rbs_collection_path [String, Pathname, nil] # @param rbs_collection_config_path [String, Pathname, nil] # @return [RbsMap] @@ -83,14 +115,24 @@ def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path return rbs_map if rbs_map.resolved? # try any version of the gem in the collection - RbsMap.new(gemspec.name, nil, - rbs_collection_paths: [rbs_collection_path].compact, - rbs_collection_config_path: rbs_collection_config_path) + rbs_map = RbsMap.new(gemspec.name, nil, + rbs_collection_paths: [rbs_collection_path].compact, + rbs_collection_config_path: rbs_collection_config_path) + + return rbs_map if rbs_map.resolved? + + StdlibMap.new(gemspec.name) end + # @param out [IO, nil] where to log messages # @return [Array] - def pins - @pins ||= resolved? ? conversions.pins : [] + def pins out: $stderr + @pins ||= if resolved? + loader.libs.each { |lib| log_caching(lib, out: out) } + conversions.pins + else + [] + end end # @generic T @@ -140,15 +182,22 @@ def conversions @conversions ||= Conversions.new(loader: loader) end + # @param lib [RBS::EnvironmentLoader::Library] + # @param out [IO, nil] where to log messages + # @return [void] + def log_caching lib, out:; end + # @param loader [RBS::EnvironmentLoader] # @param library [String] - # @param version [String, nil] + # @param version [String, nil] the version of the library to load, or nil for any + # @param out [IO, nil] where to log messages # @return [Boolean] true if adding the library succeeded - def add_library loader, library, version + def add_library loader, library, version, out: $stderr @resolved = if loader.has_library?(library: library, version: version) - loader.add library: library, version: version - logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" } - true + # we find our own dependencies from gemfile.lock + loader.add library: library, version: version, resolve_dependencies: false + logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" } + true else logger.info { "#{short_name} did not find data for library #{library}:#{version}" } false diff --git a/lib/solargraph/rbs_map/core_map.rb b/lib/solargraph/rbs_map/core_map.rb index 8c3d7dbdd..a9b647b20 100644 --- a/lib/solargraph/rbs_map/core_map.rb +++ b/lib/solargraph/rbs_map/core_map.rb @@ -14,28 +14,37 @@ def resolved? def initialize; end + # @param out [IO, nil] output stream for logging # @return [Enumerable] - def pins + def pins out: $stderr return @pins if @pins + @pins = cache_core(out: out) + end - @pins = [] + # @param out [IO, nil] output stream for logging + # @return [Array] + def cache_core out: $stderr + new_pins = [] cache = PinCache.deserialize_core - if cache - @pins.replace cache - else - loader.add(path: Pathname(FILLS_DIRECTORY)) - @pins = conversions.pins - @pins.concat RbsMap::CoreFills::ALL - processed = ApiMap::Store.new(pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) } - @pins.replace processed - - PinCache.serialize_core @pins - end - @pins - end + return cache if cache - def loader - @loader ||= RBS::EnvironmentLoader.new(repository: RBS::Repository.new(no_stdlib: false)) + new_pins.concat conversions.pins + + # Avoid RBS::DuplicatedDeclarationError by loading in a different EnvironmentLoader + fill_loader = RBS::EnvironmentLoader.new(core_root: nil, repository: RBS::Repository.new(no_stdlib: false)) + fill_loader.add(path: Pathname(FILLS_DIRECTORY)) + out&.puts 'Caching RBS pins for Ruby core' + fill_conversions = Conversions.new(loader: fill_loader) + new_pins.concat fill_conversions.pins + + new_pins.concat RbsMap::CoreFills::ALL + + processed = ApiMap::Store.new(new_pins).pins.reject { |p| p.is_a?(Solargraph::Pin::Reference::Override) } + new_pins.replace processed + + PinCache.serialize_core new_pins + + new_pins end private diff --git a/lib/solargraph/rbs_map/stdlib_map.rb b/lib/solargraph/rbs_map/stdlib_map.rb index b6804157f..e7891bfe3 100644 --- a/lib/solargraph/rbs_map/stdlib_map.rb +++ b/lib/solargraph/rbs_map/stdlib_map.rb @@ -12,8 +12,13 @@ class StdlibMap < RbsMap # @type [Hash{String => RbsMap}] @stdlib_maps_hash = {} + def log_caching lib, out: $stderr + out&.puts("Caching RBS pins for standard library #{lib.name}") + end + # @param library [String] - def initialize library + # @param out [IO, nil] where to log messages + def initialize library, out: $stderr cached_pins = PinCache.deserialize_stdlib_require library if cached_pins @pins = cached_pins @@ -24,7 +29,7 @@ def initialize library super unless resolved? @pins = [] - logger.info { "Could not resolve #{library.inspect}" } + logger.debug { "StdlibMap could not resolve #{library.inspect}" } return end generated_pins = pins @@ -33,6 +38,22 @@ def initialize library end end + # @return [RBS::Collection::Sources::Stdlib] + def self.source + @source ||= RBS::Collection::Sources::Stdlib.instance + end + + # @param name [String] + # @param version [String, nil] + # @return [Array String}>, nil] + def self.stdlib_dependencies name, version = nil + if source.has?(name, version) + source.dependencies_of(name, version) + else + [] + end + end + # @param library [String] # @return [StdlibMap] def self.load library diff --git a/lib/solargraph/shell.rb b/lib/solargraph/shell.rb index a005f600b..735e6c290 100755 --- a/lib/solargraph/shell.rb +++ b/lib/solargraph/shell.rb @@ -3,6 +3,7 @@ require 'benchmark' require 'thor' require 'yard' +require 'yaml' module Solargraph class Shell < Thor @@ -118,19 +119,21 @@ def cache gem, version = nil # @return [void] def uncache *gems raise ArgumentError, 'No gems specified.' if gems.empty? + workspace = Solargraph::Workspace.new(Dir.pwd) + gems.each do |gem| if gem == 'core' - PinCache.uncache_core + PinCache.uncache_core(out: $stdout) next end if gem == 'stdlib' - PinCache.uncache_stdlib + PinCache.uncache_stdlib(out: $stdout) next end spec = Gem::Specification.find_by_name(gem) - PinCache.uncache_gem(spec, out: $stdout) + workspace.uncache_gem(spec, out: $stdout) end end diff --git a/lib/solargraph/workspace.rb b/lib/solargraph/workspace.rb index ffd653d96..92be0c8c3 100644 --- a/lib/solargraph/workspace.rb +++ b/lib/solargraph/workspace.rb @@ -2,6 +2,7 @@ require 'open3' require 'json' +require 'yaml' module Solargraph # A workspace consists of the files in a project's directory and the @@ -9,7 +10,10 @@ module Solargraph # in an associated Library or ApiMap. # class Workspace + include Logging + autoload :Config, 'solargraph/workspace/config' + autoload :RequirePaths, 'solargraph/workspace/require_paths' # @return [String] attr_reader :directory @@ -19,14 +23,12 @@ class Workspace # @return [Array] attr_reader :require_paths - # @return [Array] - attr_reader :gemnames - alias source_gems gemnames - - # @param directory [String] + # @param directory [String] TODO: Document and test '' and '*' semantics # @param config [Config, nil] # @param server [Hash] def initialize directory = '', config = nil, server = {} + raise ArgumentError, 'directory must be a String' unless directory.is_a?(String) + @directory = directory @config = config @server = server @@ -41,6 +43,56 @@ def config @config ||= Solargraph::Workspace::Config.new(directory) end + # @return [Solargraph::PinCache] + def pin_cache + @pin_cache ||= fresh_pincache + end + + # @param stdlib_name [String] + # + # @return [Array] + def stdlib_dependencies stdlib_name + deps = RbsMap::StdlibMap.stdlib_dependencies(stdlib_name, nil) || [] + deps.map { |dep| dep['name'] }.compact + end + + # @return [Environ] + def global_environ + # empty docmap, since the result needs to work in any possible + # context here + @global_environ ||= Convention.for_global(DocMap.new([], [], self)) + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param out [IO, nil] output stream for logging + # @param rebuild [Boolean] whether to rebuild the pins even if they are cached + # + # @return [void] + def cache_gem gemspec, out: nil, rebuild: false + pin_cache.cache_gem(gemspec: gemspec, out: out, rebuild: rebuild) + end + + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param out [IO, nil] output stream for logging + # + # @return [void] + def uncache_gem gemspec, out: nil + pin_cache.uncache_gem(gemspec, out: out) + end + + # @return [Solargraph::PinCache] + def fresh_pincache + PinCache.new(rbs_collection_path: rbs_collection_path, + rbs_collection_config_path: rbs_collection_config_path, + yard_plugins: yard_plugins, + directory: directory) + end + + # @return [Array] + def yard_plugins + @yard_plugins ||= global_environ.yard_plugins.sort.uniq + end + # Merge the source. A merge will update the existing source for the file # or add it to the sources if the workspace is configured to include it. # The source is ignored if the configuration excludes it. @@ -135,12 +187,23 @@ def rbs_collection_path # @return [String, nil] def rbs_collection_config_path - @rbs_collection_config_path ||= begin - unless directory.empty? || directory == '*' - yaml_file = File.join(directory, 'rbs_collection.yaml') - yaml_file if File.file?(yaml_file) + @rbs_collection_config_path ||= + begin + unless directory.empty? || directory == '*' + yaml_file = File.join(directory, 'rbs_collection.yaml') + yaml_file if File.file?(yaml_file) + end end - end + end + + # @param name [String] + # @param version [String, nil] + # + # @return [Gem::Specification, nil] + def find_gem name, version = nil + Gem::Specification.find_by_name(name, version) + rescue Gem::MissingSpecError + nil end # Synchronize the workspace from the provided updater. @@ -182,7 +245,10 @@ def load_sources source_hash.clear unless directory.empty? || directory == '*' size = config.calculated.length - raise WorkspaceTooLargeError, "The workspace is too large to index (#{size} files, #{config.max_files} max)" if config.max_files > 0 and size > config.max_files + if config.max_files > 0 and size > config.max_files + raise WorkspaceTooLargeError, + "The workspace is too large to index (#{size} files, #{config.max_files} max)" + end config.calculated.each do |filename| begin source_hash[filename] = Solargraph::Source.load(filename) diff --git a/lib/solargraph/yardoc.rb b/lib/solargraph/yardoc.rb index 625e41ce4..ffe7da4c3 100644 --- a/lib/solargraph/yardoc.rb +++ b/lib/solargraph/yardoc.rb @@ -8,45 +8,55 @@ module Solargraph module Yardoc module_function - # Build and cache a gem's yardoc and return the path. If the cache already - # exists, do nothing and return the path. + # Build and save a gem's yardoc into a given path. # - # @param yard_plugins [Array] The names of YARD plugins to use. + # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem + # @param yard_plugins [Array] # @param gemspec [Gem::Specification] - # @return [String] The path to the cached yardoc. - def cache(yard_plugins, gemspec) - path = PinCache.yardoc_path gemspec - return path if cached?(gemspec) + # + # @return [void] + def build_docs gem_yardoc_path, yard_plugins, gemspec + return if docs_built?(gem_yardoc_path) - Solargraph.logger.info "Caching yardoc for #{gemspec.name} #{gemspec.version}" - cmd = "yardoc --db #{path} --no-output --plugin solargraph" + Solargraph.logger.info "Saving yardoc for #{gemspec.name} #{gemspec.version} into #{gem_yardoc_path}" + cmd = "yardoc --db #{gem_yardoc_path} --no-output --plugin solargraph" yard_plugins.each { |plugin| cmd << " --plugin #{plugin}" } Solargraph.logger.debug { "Running: #{cmd}" } # @todo set these up to run in parallel - # - # @sg-ignore RBS gem doesn't reflect that Open3.* also include - # kwopts from Process.spawn() - stdout_and_stderr_str, status = Open3.capture2e(cmd, chdir: gemspec.gem_dir) - unless status.success? - Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" } - Solargraph.logger.info stdout_and_stderr_str + unless File.exist?(gemspec.gem_dir) + Solargraph.logger.info { "Bad info from gemspec - #{gemspec.gem_dir} does not exist" } + return end - path + + # @sg-ignore + stdout_and_stderr_str, status = Open3.capture2e(current_bundle_env_tweaks, cmd, chdir: gemspec.gem_dir) + return if status.success? + Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" } + Solargraph.logger.info stdout_and_stderr_str + end + + # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem + # @param gemspec [Gem::Specification] + # @param out [IO, nil] where to log messages + # @return [Array] + def build_pins gem_yardoc_path, gemspec, out: $stderr + yardoc = load!(gem_yardoc_path) + YardMap::Mapper.new(yardoc, gemspec).map end # True if the gem yardoc is cached. # - # @param gemspec [Gem::Specification] - def cached?(gemspec) - yardoc = File.join(PinCache.yardoc_path(gemspec), 'complete') + # @param gem_yardoc_path [String] + def docs_built? gem_yardoc_path + yardoc = File.join(gem_yardoc_path, 'complete') File.exist?(yardoc) end # True if another process is currently building the yardoc cache. # - # @param gemspec [Gem::Specification] - def processing?(gemspec) - yardoc = File.join(PinCache.yardoc_path(gemspec), 'processing') + # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem + def processing? gem_yardoc_path + yardoc = File.join(gem_yardoc_path, 'processing') File.exist?(yardoc) end @@ -54,11 +64,28 @@ def processing?(gemspec) # # @note This method modifies the global YARD registry. # - # @param gemspec [Gem::Specification] + # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem # @return [Array] - def load!(gemspec) - YARD::Registry.load! PinCache.yardoc_path gemspec + def load! gem_yardoc_path + YARD::Registry.load! gem_yardoc_path YARD::Registry.all end + + # If the BUNDLE_GEMFILE environment variable is set, we need to + # make sure it's an absolute path, as we'll be changing + # directories. + # + # 'bundle exec' sets an absolute path here, but at least the + # overcommit gem does not, breaking on-the-fly documention with a + # spawned yardoc command from our current bundle + # + # @return [Hash{String => String}] a hash of environment variables to override + def current_bundle_env_tweaks + tweaks = {} + if ENV['BUNDLE_GEMFILE'] && !ENV['BUNDLE_GEMFILE'].empty? + tweaks['BUNDLE_GEMFILE'] = File.expand_path(ENV['BUNDLE_GEMFILE']) + end + tweaks + end end end diff --git a/spec/doc_map_spec.rb b/spec/doc_map_spec.rb index b03e573f0..b87970d48 100644 --- a/spec/doc_map_spec.rb +++ b/spec/doc_map_spec.rb @@ -1,80 +1,129 @@ # frozen_string_literal: true +require 'bundler' +require 'benchmark' + describe Solargraph::DocMap do - before :all do - # We use ast here because it's a known dependency. - gemspec = Gem::Specification.find_by_name('ast') - yard_pins = Solargraph::GemPins.build_yard_pins([], gemspec) - Solargraph::PinCache.serialize_yard_gem(gemspec, yard_pins) + subject(:doc_map) do + described_class.new(requires, [], workspace, out: out) end - it 'generates pins from gems' do - doc_map = Solargraph::DocMap.new(['ast'], []) - doc_map.cache_all!($stderr) - node_pin = doc_map.pins.find { |pin| pin.path == 'AST::Node' } - expect(node_pin).to be_a(Solargraph::Pin::Namespace) + let(:out) { StringIO.new } + let(:pre_cache) { true } + let(:requires) { [] } + + let(:workspace) do + Solargraph::Workspace.new(Dir.pwd) end - it 'tracks unresolved requires' do - doc_map = Solargraph::DocMap.new(['not_a_gem'], []) - expect(doc_map.unresolved_requires).to include('not_a_gem') + let(:plain_doc_map) { described_class.new([], [], workspace, out: nil) } + + before do + doc_map.cache_doc_map_gems!(nil) if pre_cache end - it 'tracks uncached_gemspecs' do - gemspec = Gem::Specification.new do |spec| - spec.name = 'not_a_gem' - spec.version = '1.0.0' + context 'with a require in solargraph test bundle' do + let(:requires) do + ['ast'] + end + + it 'generates pins from gems' do + node_pin = doc_map.pins.find { |pin| pin.path == 'AST::Node' } + expect(node_pin).to be_a(Solargraph::Pin::Namespace) end - allow(Gem::Specification).to receive(:find_by_path).and_return(gemspec) - doc_map = Solargraph::DocMap.new(['not_a_gem'], [gemspec]) - expect(doc_map.uncached_yard_gemspecs).to eq([gemspec]) - expect(doc_map.uncached_rbs_collection_gemspecs).to eq([gemspec]) end - it 'imports all gems when bundler/require used' do - workspace = Solargraph::Workspace.new(Dir.pwd) - plain_doc_map = Solargraph::DocMap.new([], [], workspace) - doc_map_with_bundler_require = Solargraph::DocMap.new(['bundler/require'], [], workspace) + context 'when deserialization takes a while' do + let(:pre_cache) { false } + let(:requires) { ['backport'] } - expect(doc_map_with_bundler_require.pins.length - plain_doc_map.pins.length).to be_positive + before do + # proxy this method to simulate a long-running deserialization + allow(Benchmark).to receive(:measure) do |&block| + block.call + 5.0 + end + end + + it 'logs timing' do + # force lazy evaluation + _pins = doc_map.pins + expect(out.string).to include('Deserialized ').and include(' gem pins ').and include(' ms') + end end - it 'does not warn for redundant requires' do - # Requiring 'set' is unnecessary because it's already included in core. It - # might make sense to log redundant requires, but a warning is overkill. - expect(Solargraph.logger).not_to receive(:warn).with(/path set/) - Solargraph::DocMap.new(['set'], []) + context 'with an uncached but valid gemspec' do + let(:requires) { ['uncached_gem'] } + let(:pre_cache) { false } + let(:workspace) { instance_double(Solargraph::Workspace) } + + it 'tracks uncached_gemspecs' do + pincache = instance_double(Solargraph::PinCache) + uncached_gemspec = Gem::Specification.new('uncached_gem', '1.0.0') + allow(workspace).to receive_messages(fresh_pincache: pincache) + allow(Gem::Specification).to receive(:find_by_path).with('uncached_gem').and_return(uncached_gemspec) + allow(workspace).to receive(:global_environ).and_return(Solargraph::Environ.new) + allow(pincache).to receive(:deserialize_combined_pin_cache).with(uncached_gemspec).and_return(nil) + expect(doc_map.uncached_gemspecs).to eq([uncached_gemspec]) + end end - it 'ignores nil requires' do - expect { Solargraph::DocMap.new([nil], []) }.not_to raise_error + context 'with require as bundle/require' do + it 'imports all gems when bundler/require used' do + doc_map_with_bundler_require = described_class.new(['bundler/require'], [], workspace, out: nil) + doc_map_with_bundler_require.cache_doc_map_gems!(nil) + expect(doc_map_with_bundler_require.pins.length - plain_doc_map.pins.length).to be_positive + end end - it 'ignores empty requires' do - expect { Solargraph::DocMap.new([''], []) }.not_to raise_error + context 'with a require not needed by Ruby core' do + let(:requires) { ['set'] } + + it 'does not warn' do + # Requiring 'set' is unnecessary because it's already included in core. It + # might make sense to log redundant requires, but a warning is overkill. + allow(Solargraph.logger).to receive(:warn) + doc_map + expect(Solargraph.logger).not_to have_received(:warn).with(/path set/) + end end - it 'collects dependencies' do - doc_map = Solargraph::DocMap.new(['rspec'], []) - expect(doc_map.dependencies.map(&:name)).to include('rspec-core') + context 'with a nil require' do + let(:requires) { [nil] } + + it 'does not raise error' do + expect { doc_map }.not_to raise_error + end end - it 'includes convention requires from environ' do - dummy_convention = Class.new(Solargraph::Convention::Base) do - def global(doc_map) - Solargraph::Environ.new( - requires: ['convention_gem1', 'convention_gem2'] - ) - end + context 'with an empty require' do + let(:requires) { [''] } + + it 'does not raise error' do + expect { doc_map }.not_to raise_error end + end - Solargraph::Convention.register dummy_convention + context 'with convention' do + let(:pre_cache) { false } - doc_map = Solargraph::DocMap.new(['original_gem'], []) + it 'includes convention requires from environ' do + dummy_convention = Class.new(Solargraph::Convention::Base) do + def global(doc_map) + Solargraph::Environ.new( + requires: ['convention_gem1', 'convention_gem2'] + ) + end + end - expect(doc_map.requires).to include('original_gem', 'convention_gem1', 'convention_gem2') + Solargraph::Convention.register dummy_convention - # Clean up the registered convention - Solargraph::Convention.deregister dummy_convention + doc_map = Solargraph::DocMap.new(['original_gem'], [], workspace) + + expect(doc_map.requires).to include('original_gem', 'convention_gem1', 'convention_gem2') + ensure + # Clean up the registered convention + Solargraph::Convention.deregister dummy_convention + end end end diff --git a/spec/gem_pins_spec.rb b/spec/gem_pins_spec.rb index d630784cf..4d2bb4ff5 100644 --- a/spec/gem_pins_spec.rb +++ b/spec/gem_pins_spec.rb @@ -1,14 +1,49 @@ # frozen_string_literal: true describe Solargraph::GemPins do - it 'can merge YARD and RBS' do - gemspec = Gem::Specification.find_by_name('rbs') - yard_pins = Solargraph::GemPins.build_yard_pins([], gemspec) - rbs_map = Solargraph::RbsMap.from_gemspec(gemspec, nil, nil) - pins = Solargraph::GemPins.combine yard_pins, rbs_map.pins - - core_root = pins.find { |pin| pin.path == 'RBS::EnvironmentLoader#core_root' } - expect(core_root.return_type.to_s).to eq('Pathname, nil') - expect(core_root.location.filename).to end_with('environment_loader.rb') + let(:workspace) { Solargraph::Workspace.new(Dir.pwd) } + let(:doc_map) { Solargraph::DocMap.new(requires, [], workspace, out: nil) } + let(:pin) { doc_map.pins.find { |pin| pin.path == path } } + + before do + doc_map.cache_doc_map_gems!(STDERR) # rubocop:disable Style/GlobalStdStream + end + + context 'with a combined method pin' do + let(:path) { 'RBS::EnvironmentLoader#core_root' } + let(:requires) { ['rbs'] } + + it 'can merge YARD and RBS' do + expect(pin.source).to eq(:combined) + end + + it 'finds types from RBS' do + expect(pin.return_type.to_s).to eq('Pathname, nil') + end + + it 'finds locations from YARD' do + expect(pin.location.filename).to end_with('environment_loader.rb') + end + end + + context 'with a YARD-only pin' do + let(:requires) { ['rake'] } + let(:path) { 'Rake::Task#prerequisites' } + + it 'found a pin' do + expect(pin.source).not_to be_nil + end + + it 'can merge YARD and RBS' do + expect(pin.source).to eq(:yardoc) + end + + it 'does not find types from YARD in this case' do + expect(pin.return_type.to_s).to eq('undefined') + end + + it 'finds locations from YARD' do + expect(pin.location.filename).to end_with('task.rb') + end end end diff --git a/spec/language_server/host/diagnoser_spec.rb b/spec/language_server/host/diagnoser_spec.rb index d59a843f1..69ee0b866 100644 --- a/spec/language_server/host/diagnoser_spec.rb +++ b/spec/language_server/host/diagnoser_spec.rb @@ -3,7 +3,8 @@ host = double(Solargraph::LanguageServer::Host, options: { 'diagnostics' => true }, synchronizing?: false) diagnoser = Solargraph::LanguageServer::Host::Diagnoser.new(host) diagnoser.schedule 'file.rb' - expect(host).to receive(:diagnose).with('file.rb') + allow(host).to receive(:diagnose) diagnoser.tick + expect(host).to have_received(:diagnose).with('file.rb') end end diff --git a/spec/language_server/host/message_worker_spec.rb b/spec/language_server/host/message_worker_spec.rb index b9ce2a41f..f7c17cb6d 100644 --- a/spec/language_server/host/message_worker_spec.rb +++ b/spec/language_server/host/message_worker_spec.rb @@ -2,7 +2,7 @@ it "handle requests on queue" do host = double(Solargraph::LanguageServer::Host) message = {'method' => '$/example'} - expect(host).to receive(:receive).with(message).and_return(nil) + allow(host).to receive(:receive).with(message).and_return(nil) worker = Solargraph::LanguageServer::Host::MessageWorker.new(host) worker.queue(message) diff --git a/spec/library_spec.rb b/spec/library_spec.rb index 34de9e1f0..f7daafdf4 100644 --- a/spec/library_spec.rb +++ b/spec/library_spec.rb @@ -26,6 +26,32 @@ expect(completion.pins.map(&:name)).to include('x') end + context 'with a require from a not-yet-cached external gem' do + before do + Solargraph::Shell.new.uncache('backport') + end + + it "returns a Completion", time_limit_seconds: 50 do + library = Solargraph::Library.new(Solargraph::Workspace.new(Dir.pwd, + Solargraph::Workspace::Config.new)) + library.attach Solargraph::Source.load_string(%( + require 'backport' + + # @param adapter [Backport::Adapter] + def foo(adapter) + adapter.remo + end + ), 'file.rb', 0) + completion = nil + # give Solargraph time to cache the gem + while (completion = library.completions_at('file.rb', 5, 19)).pins.empty? + sleep 0.25 + end + expect(completion).to be_a(Solargraph::SourceMap::Completion) + expect(completion.pins.map(&:name)).to include('remote') + end + end + context 'with a require from an already-cached external gem' do before do Solargraph::Shell.new.gems('backport') @@ -161,10 +187,47 @@ def bar expect(pins.map(&:path)).to include('Foo#bar') end - it "collects references to an instance method symbol" do - workspace = Solargraph::Workspace.new('*') - library = Solargraph::Library.new(workspace) - src1 = Solargraph::Source.load_string(%( + describe '#references_from' do + it "collects references to a new method on a constant from assignment of Class.new" do + workspace = Solargraph::Workspace.new('*') + library = Solargraph::Library.new(workspace) + src1 = Solargraph::Source.load_string(%( + Foo.new + ), 'file1.rb', 0) + library.merge src1 + src2 = Solargraph::Source.load_string(%( + Foo = Class.new + ), 'file2.rb', 0) + library.merge src2 + library.catalog + locs = library.references_from('file1.rb', 1, 12) + expect(locs.map { |l| [l.filename, l.range.start.line] }) + .to eq([["file1.rb", 1]]) + end + + it "collects references to a new method to a constant from assignment" do + workspace = Solargraph::Workspace.new('*') + library = Solargraph::Library.new(workspace) + src1 = Solargraph::Source.load_string(%( + Foo.new + ), 'file1.rb', 0) + library.merge src1 + src2 = Solargraph::Source.load_string(%( + class Foo + end + blah = Foo.new + ), 'file2.rb', 0) + library.merge src2 + library.catalog + locs = library.references_from('file2.rb', 3, 21) + expect(locs.map { |l| [l.filename, l.range.start.line] }) + .to eq([["file1.rb", 1], ["file2.rb", 3]]) + end + + it "collects references to an instance method symbol" do + workspace = Solargraph::Workspace.new('*') + library = Solargraph::Library.new(workspace) + src1 = Solargraph::Source.load_string(%( class Foo def bar end @@ -172,8 +235,8 @@ def bar Foo.new.bar ), 'file1.rb', 0) - library.merge src1 - src2 = Solargraph::Source.load_string(%( + library.merge src1 + src2 = Solargraph::Source.load_string(%( foo = Foo.new foo.bar class Other @@ -181,17 +244,17 @@ def bar; end end Other.new.bar ), 'file2.rb', 0) - library.merge src2 - library.catalog - locs = library.references_from('file2.rb', 2, 11) - expect(locs.length).to eq(3) - expect(locs.select{|l| l.filename == 'file2.rb' && l.range.start.line == 6}).to be_empty - end + library.merge src2 + library.catalog + locs = library.references_from('file2.rb', 2, 11) + expect(locs.length).to eq(3) + expect(locs.select{|l| l.filename == 'file2.rb' && l.range.start.line == 6}).to be_empty + end - it "collects references to a class method symbol" do - workspace = Solargraph::Workspace.new('*') - library = Solargraph::Library.new(workspace) - src1 = Solargraph::Source.load_string(%( + it "collects references to a class method symbol" do + workspace = Solargraph::Workspace.new('*') + library = Solargraph::Library.new(workspace) + src1 = Solargraph::Source.load_string(%( class Foo def self.bar end @@ -203,8 +266,8 @@ def bar Foo.bar Foo.new.bar ), 'file1.rb', 0) - library.merge src1 - src2 = Solargraph::Source.load_string(%( + library.merge src1 + src2 = Solargraph::Source.load_string(%( Foo.bar Foo.new.bar class Other @@ -214,48 +277,48 @@ def bar; end Other.bar Other.new.bar ), 'file2.rb', 0) - library.merge src2 - library.catalog - locs = library.references_from('file2.rb', 1, 11) - expect(locs.length).to eq(3) - expect(locs.select{|l| l.filename == 'file1.rb' && l.range.start.line == 2}).not_to be_empty - expect(locs.select{|l| l.filename == 'file1.rb' && l.range.start.line == 9}).not_to be_empty - expect(locs.select{|l| l.filename == 'file2.rb' && l.range.start.line == 1}).not_to be_empty - end + library.merge src2 + library.catalog + locs = library.references_from('file2.rb', 1, 11) + expect(locs.length).to eq(3) + expect(locs.select{|l| l.filename == 'file1.rb' && l.range.start.line == 2}).not_to be_empty + expect(locs.select{|l| l.filename == 'file1.rb' && l.range.start.line == 9}).not_to be_empty + expect(locs.select{|l| l.filename == 'file2.rb' && l.range.start.line == 1}).not_to be_empty + end - it "collects stripped references to constant symbols" do - workspace = Solargraph::Workspace.new('*') - library = Solargraph::Library.new(workspace) - src1 = Solargraph::Source.load_string(%( + it "collects stripped references to constant symbols" do + workspace = Solargraph::Workspace.new('*') + library = Solargraph::Library.new(workspace) + src1 = Solargraph::Source.load_string(%( class Foo def bar end end Foo.new.bar ), 'file1.rb', 0) - library.merge src1 - src2 = Solargraph::Source.load_string(%( + library.merge src1 + src2 = Solargraph::Source.load_string(%( class Other foo = Foo.new foo.bar end ), 'file2.rb', 0) - library.merge src2 - library.catalog - locs = library.references_from('file1.rb', 1, 12, strip: true) - expect(locs.length).to eq(3) - locs.each do |l| - code = library.read_text(l.filename) - o1 = Solargraph::Position.to_offset(code, l.range.start) - o2 = Solargraph::Position.to_offset(code, l.range.ending) - expect(code[o1..o2-1]).to eq('Foo') + library.merge src2 + library.catalog + locs = library.references_from('file1.rb', 1, 12, strip: true) + expect(locs.length).to eq(3) + locs.each do |l| + code = library.read_text(l.filename) + o1 = Solargraph::Position.to_offset(code, l.range.start) + o2 = Solargraph::Position.to_offset(code, l.range.ending) + expect(code[o1..o2-1]).to eq('Foo') + end end - end - it 'rejects new references from different classes' do - workspace = Solargraph::Workspace.new('*') - library = Solargraph::Library.new(workspace) - source = Solargraph::Source.load_string(%( + it 'rejects new references from different classes' do + workspace = Solargraph::Workspace.new('*') + library = Solargraph::Library.new(workspace) + source = Solargraph::Source.load_string(%( class Foo def bar end @@ -263,106 +326,131 @@ def bar Foo.new Array.new ), 'test.rb') - library.merge source - library.catalog - foo_new_locs = library.references_from('test.rb', 5, 10) - expect(foo_new_locs).to eq([Solargraph::Location.new('test.rb', Solargraph::Range.from_to(5, 10, 5, 13))]) - obj_new_locs = library.references_from('test.rb', 6, 12) - expect(obj_new_locs).to eq([Solargraph::Location.new('test.rb', Solargraph::Range.from_to(6, 12, 6, 15))]) - end + library.merge source + library.catalog + foo_new_locs = library.references_from('test.rb', 5, 10) + expect(foo_new_locs).to eq([Solargraph::Location.new('test.rb', Solargraph::Range.from_to(5, 10, 5, 13))]) + obj_new_locs = library.references_from('test.rb', 6, 12) + expect(obj_new_locs).to eq([Solargraph::Location.new('test.rb', Solargraph::Range.from_to(6, 12, 6, 15))]) + end - it "searches the core for queries" do - library = Solargraph::Library.new - result = library.search('String') - expect(result).not_to be_empty - end + it "searches the core for queries" do + library = Solargraph::Library.new + result = library.search('String') + expect(result).not_to be_empty + end - it "returns YARD documentation from the core" do - library = Solargraph::Library.new - api_map, result = library.document('String') - expect(result).not_to be_empty - expect(result.first).to be_a(Solargraph::Pin::Base) - end + it "returns YARD documentation from the core" do + library = Solargraph::Library.new + api_map, result = library.document('String') + expect(result).not_to be_empty + expect(result.first).to be_a(Solargraph::Pin::Base) + end - it "returns YARD documentation from sources" do - library = Solargraph::Library.new - src = Solargraph::Source.load_string(%( + it "returns YARD documentation from sources" do + library = Solargraph::Library.new + src = Solargraph::Source.load_string(%( class Foo # My bar method def bar; end end ), 'test.rb', 0) - library.attach src - api_map, result = library.document('Foo#bar') - expect(result).not_to be_empty - expect(result.first).to be_a(Solargraph::Pin::Base) - end + library.attach src + api_map, result = library.document('Foo#bar') + expect(result).not_to be_empty + expect(result.first).to be_a(Solargraph::Pin::Base) + end - it "synchronizes sources from updaters" do - library = Solargraph::Library.new - src = Solargraph::Source.load_string(%( + it "synchronizes sources from updaters" do + library = Solargraph::Library.new + src = Solargraph::Source.load_string(%( class Foo end ), 'test.rb', 1) - library.attach src - repl = %( + library.attach src + repl = %( class Foo def bar; end end ) - updater = Solargraph::Source::Updater.new( - 'test.rb', - 2, - [Solargraph::Source::Change.new(nil, repl)] - ) - library.attach src.synchronize(updater) - expect(library.current.code).to eq(repl) - end + updater = Solargraph::Source::Updater.new( + 'test.rb', + 2, + [Solargraph::Source::Change.new(nil, repl)] + ) + library.attach src.synchronize(updater) + expect(library.current.code).to eq(repl) + end - it "finds unique references" do - library = Solargraph::Library.new(Solargraph::Workspace.new('*')) - src1 = Solargraph::Source.load_string(%( + it "finds unique references" do + library = Solargraph::Library.new(Solargraph::Workspace.new('*')) + src1 = Solargraph::Source.load_string(%( class Foo end ), 'src1.rb', 1) - library.merge src1 - src2 = Solargraph::Source.load_string(%( + library.merge src1 + src2 = Solargraph::Source.load_string(%( foo = Foo.new ), 'src2.rb', 1) - library.merge src2 - library.catalog - refs = library.references_from('src2.rb', 1, 12) - expect(refs.length).to eq(2) - end + library.merge src2 + library.catalog + refs = library.references_from('src2.rb', 1, 12) + expect(refs.length).to eq(2) + end - it "includes method parameters in references" do - library = Solargraph::Library.new(Solargraph::Workspace.new('*')) - source = Solargraph::Source.load_string(%( + it "includes method parameters in references" do + library = Solargraph::Library.new(Solargraph::Workspace.new('*')) + source = Solargraph::Source.load_string(%( class Foo def bar(baz) baz.upcase end end ), 'test.rb', 1) - library.attach source - from_def = library.references_from('test.rb', 2, 16) - expect(from_def.length).to eq(2) - from_ref = library.references_from('test.rb', 3, 10) - expect(from_ref.length).to eq(2) - end + library.attach source + from_def = library.references_from('test.rb', 2, 16) + expect(from_def.length).to eq(2) + from_ref = library.references_from('test.rb', 3, 10) + expect(from_ref.length).to eq(2) + end - it "includes block parameters in references" do - library = Solargraph::Library.new(Solargraph::Workspace.new('*')) - source = Solargraph::Source.load_string(%( + it "lies about names when client can't handle the truth" do + library = Solargraph::Library.new(Solargraph::Workspace.new('*')) + source = Solargraph::Source.load_string(%( + class Foo + def 🤦🏻foo♀️; 123; end + end + ), 'test.rb', 1) + library.attach source + from_def = library.references_from('test.rb', 2, 16, strip: true) + expect(from_def.first.range.start.column).to eq(14) + end + + it "tells the truth about names when client can handle the truth" do + library = Solargraph::Library.new(Solargraph::Workspace.new('*')) + source = Solargraph::Source.load_string(%( + class Foo + def 🤦🏻foo♀️; 123; end + end + ), 'test.rb', 1) + library.attach source + from_def = library.references_from('test.rb', 2, 16, strip: false) + expect(from_def.first.range.start.column).to eq(12) + end + + it "includes block parameters in references" do + library = Solargraph::Library.new(Solargraph::Workspace.new('*')) + source = Solargraph::Source.load_string(%( 100.times do |foo| puts foo end ), 'test.rb', 1) - library.attach source - from_def = library.references_from('test.rb', 1, 20) - expect(from_def.length).to eq(2) - from_ref = library.references_from('test.rb', 2, 13) - expect(from_ref.length).to eq(2) + library.attach source + from_def = library.references_from('test.rb', 1, 20) + expect(from_def.length).to eq(2) + from_ref = library.references_from('test.rb', 2, 13) + expect(from_ref.length).to eq(2) + end end it 'defines YARD tags' do diff --git a/spec/pin_cache_spec.rb b/spec/pin_cache_spec.rb new file mode 100644 index 000000000..0a11686f5 --- /dev/null +++ b/spec/pin_cache_spec.rb @@ -0,0 +1,197 @@ +# frozen_string_literal: true + +require 'bundler' +require 'benchmark' + +describe Solargraph::PinCache do + subject(:pin_cache) do + described_class.new(rbs_collection_path: '.gem_rbs_collection', + rbs_collection_config_path: 'rbs_collection.yaml', + directory: Dir.pwd, + yard_plugins: ['activesupport-concern']) + end + + describe '#cached?' do + it 'returns true for a gem that is cached' do + allow(File).to receive(:file?).with(%r{.*stdlib/backport.ser$}).and_return(false) + allow(File).to receive(:file?).with(%r{.*combined/.*/backport-.*.ser$}).and_return(true) + + gemspec = Gem::Specification.find_by_name('backport') + expect(pin_cache.cached?(gemspec)).to be true + end + + it 'returns false for a gem that is not cached' do + gemspec = Gem::Specification.new.tap do |spec| + spec.name = 'nonexistent' + spec.version = '0.0.1' + end + expect(pin_cache.cached?(gemspec)).to be false + end + end + + describe '.core?' do + it 'returns true when core pins exist' do + allow(File).to receive(:file?).with(%r{.*/core.ser$}).and_return(true) + + expect(described_class.core?).to be true + end + + it "returns true when core pins don't" do + allow(File).to receive(:file?).with(%r{.*/core.ser$}).and_return(false) + + expect(described_class.core?).to be false + end + end + + describe '#possible_stdlibs' do + it 'is tolerant of less usual Ruby installations' do + stub_const('Gem::RUBYGEMS_DIR', nil) + + expect(pin_cache.possible_stdlibs).to eq([]) + end + end + + describe '#cache_all_stdlibs' do + it 'creates stdlibmaps' do + allow(Solargraph::RbsMap::StdlibMap).to receive(:new).and_return(instance_double(Solargraph::RbsMap::StdlibMap)) + + pin_cache.cache_all_stdlibs + + expect(Solargraph::RbsMap::StdlibMap).to have_received(:new).at_least(:once) + end + end + + describe '#cache_gem' do + context 'with an already in-memory gem' do + let(:backport_gemspec) { Gem::Specification.find_by_name('backport') } + + before do + pin_cache.cache_gem(gemspec: backport_gemspec, out: nil) + end + + it 'does not load the gem again' do + allow(Marshal).to receive(:load).and_call_original + + pin_cache.cache_gem(gemspec: backport_gemspec, out: nil) + + expect(Marshal).not_to have_received(:load).with(anything) + end + end + + context 'with the parser gem' do + before do + Solargraph::Shell.new.uncache('parser') + allow(Solargraph::Yardoc).to receive(:build_docs) + end + + it 'chooses not to use YARD' do + parser_gemspec = Gem::Specification.find_by_name('parser') + pin_cache.cache_gem(gemspec: parser_gemspec, out: nil) + # if this fails, you may not have run `bundle exec rbs collection update` + expect(Solargraph::Yardoc).not_to have_received(:build_docs).with(any_args) + end + end + + context 'with an installed gem' do + before do + Solargraph::Shell.new.gems('kramdown') + end + + it 'uncaches when asked' do + gemspec = Gem::Specification.find_by_name('kramdown') + expect do + pin_cache.uncache_gem(gemspec, out: nil) + end.not_to raise_error + end + end + + context 'with the rebuild flag' do + before do + allow(Solargraph::Yardoc).to receive(:build_docs) + end + + it 'chooses not to use YARD' do + parser_gemspec = Gem::Specification.find_by_name('parser') + pin_cache.cache_gem(gemspec: parser_gemspec, rebuild: true, out: nil) + # if this fails, you may not have run `bundle exec rbs collection update` + expect(Solargraph::Yardoc).not_to have_received(:build_docs).with(any_args) + end + end + + context 'with a stdlib gem' do + let(:gem_name) { 'logger' } + + before do + Solargraph::Shell.new.uncache(gem_name) + end + + it 'caches' do + yaml_gemspec = Gem::Specification.find_by_name(gem_name) + allow(File).to receive(:write).and_call_original + + pin_cache.cache_gem(gemspec: yaml_gemspec, out: nil) + + # match arguments with regexp using rspec-matchers syntax + expect(File).to have_received(:write).with(%r{combined/.*/logger-.*-stdlib.ser$}, any_args).once + end + end + + context 'with gem packaged with its own RBS gem' do + let(:gem_name) { 'base64' } + + before do + Solargraph::Shell.new.uncache(gem_name) + end + + it 'caches' do + yaml_gemspec = Gem::Specification.find_by_name(gem_name) + allow(File).to receive(:write).and_call_original + + pin_cache.cache_gem(gemspec: yaml_gemspec, out: nil) + + # match arguments with regexp using rspec-matchers syntax + expect(File).to have_received(:write).with(%r{combined/.*/base64-.*-export.ser$}, any_args, mode: 'wb').once + end + end + end + + describe '#uncache_gem' do + subject(:call) { pin_cache.uncache_gem(gemspec, out: out) } + + let(:out) { StringIO.new } + + before do + allow(FileUtils).to receive(:rm_rf) + end + + context 'with an already cached gem' do + let(:gemspec) { Gem::Specification.find_by_name('backport') } + + it 'deletes files' do + call + + expect(FileUtils).to have_received(:rm_rf).at_least(:once) + end + end + + context 'with a non-existent gem' do + let(:gemspec) { instance_double(Gem::Specification, name: 'nonexistent', version: '0.0.1') } + + it 'does not raise an error' do + expect { call }.not_to raise_error + end + + it 'logs a message' do + call + + expect(out.string).to include('does not exist') + end + + it 'does not delete files' do + call + + expect(FileUtils).not_to have_received(:rm_rf) + end + end + end +end diff --git a/spec/rbs_map_spec.rb b/spec/rbs_map_spec.rb index b06c975d1..f3ca90a36 100644 --- a/spec/rbs_map_spec.rb +++ b/spec/rbs_map_spec.rb @@ -3,7 +3,18 @@ spec = Gem::Specification.find_by_name('rbs') rbs_map = Solargraph::RbsMap.from_gemspec(spec, nil, nil) pin = rbs_map.path_pin('RBS::EnvironmentLoader#add_collection') - expect(pin).to be + expect(pin).not_to be_nil + end + + it 'fails if it does not find data from gemspec' do + spec = Gem::Specification.find_by_name('backport') + rbs_map = Solargraph::RbsMap.from_gemspec(spec, nil, nil) + expect(rbs_map).not_to be_resolved + end + + it 'fails if it does not find data from name' do + rbs_map = Solargraph::RbsMap.new('lskdflaksdfjl') + expect(rbs_map.pins).to be_empty end it 'converts constants and aliases to correct types' do diff --git a/spec/shell_spec.rb b/spec/shell_spec.rb index 91f84b4c7..6e2a83074 100644 --- a/spec/shell_spec.rb +++ b/spec/shell_spec.rb @@ -1,7 +1,10 @@ +# frozen_string_literal: true + require 'tmpdir' require 'open3' describe Solargraph::Shell do + let(:shell) { described_class.new } let(:temp_dir) { Dir.mktmpdir } before do @@ -25,20 +28,122 @@ def bundle_exec(*cmd) FileUtils.rm_rf(temp_dir) end - describe "--version" do - it "returns a version when run" do - output = bundle_exec("solargraph", "--version") + describe '--version' do + let(:output) { bundle_exec('solargraph', '--version') } + it 'returns output' do expect(output).not_to be_empty + end + + it 'returns a version when run' do expect(output).to eq("#{Solargraph::VERSION}\n") end end - describe "uncache" do - it "uncaches without erroring out" do - output = bundle_exec("solargraph", "uncache", "solargraph") + describe 'uncache' do + it 'uncaches without erroring out' do + output = capture_stdout do + shell.uncache('backport') + end expect(output).to include('Clearing pin cache in') end + + it 'uncaches stdlib without erroring out' do + expect { shell.uncache('stdlib') }.not_to raise_error + end + + it 'uncaches core without erroring out' do + expect { shell.uncache('core') }.not_to raise_error + end + end + + describe 'scan' do + context 'with mocked dependencies' do + let(:api_map) { instance_double(Solargraph::ApiMap) } + + before do + allow(Solargraph::ApiMap).to receive(:load_with_cache).and_return(api_map) + end + + it 'scans without erroring out' do + allow(api_map).to receive(:pins).and_return([]) + output = capture_stdout do + shell.options = { directory: 'spec/fixtures/workspace' } + shell.scan + end + + expect(output).to include('Scanned ').and include(' seconds.') + end + end + end + + describe 'typecheck' do + context 'with mocked dependencies' do + let(:type_checker) { instance_double(Solargraph::TypeChecker) } + let(:api_map) { instance_double(Solargraph::ApiMap) } + + before do + allow(Solargraph::ApiMap).to receive(:load_with_cache).and_return(api_map) + allow(Solargraph::TypeChecker).to receive(:new).and_return(type_checker) + allow(type_checker).to receive(:problems).and_return([]) + end + + it 'typechecks without erroring out' do + output = capture_stdout do + shell.options = { level: 'normal', directory: '.' } + shell.typecheck('Gemfile') + end + + expect(output).to include('Typecheck finished in') + end + end + end + + describe 'gems' do + context 'without mocked ApiMap' do + it 'complains when gem does not exist' do + output = capture_both do + shell.gems('nonexistentgem') + end + + expect(output).to include("Gem 'nonexistentgem' not found") + end + + it 'caches core without erroring out' do + pending('https://github.com/castwide/solargraph/pull/1061') + + capture_both do + shell.uncache('core') + end + + expect { shell.cache('core') }.not_to raise_error + end + + it 'gives sensible error for gem that does not exist' do + output = capture_both do + shell.gems('solargraph123') + end + + expect(output).to include("Gem 'solargraph123' not found") + end + end + end + + describe 'cache' do + it 'caches a stdlib gem without erroring out' do + expect { shell.cache('stringio') }.not_to raise_error + end + + context 'when gem does not exist' do + subject(:call) { shell.cache('nonexistentgem8675309') } + + it 'gives a good error message' do + pending('https://github.com/castwide/solargraph/pull/1061') + + # capture stderr output + expect { call }.to output(/not found/).to_stderr + end + end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 00cc6c8c3..0a0c1dde4 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,7 +26,9 @@ c.example_status_persistence_file_path = 'rspec-examples.txt' end require 'solargraph' -# Suppress logger output in specs (if possible) +# execute any logging blocks to make sure they don't blow up +Solargraph::Logging.logger.sev_threshold = Logger::DEBUG +# ...but still suppress logger output in specs (if possible) if Solargraph::Logging.logger.respond_to?(:reopen) && !ENV.key?('SOLARGRAPH_LOG') Solargraph::Logging.logger.reopen(File::NULL) end @@ -43,3 +45,29 @@ def with_env_var(name, value) ENV[name] = old_value # Restore the old value end end + +def capture_stdout &block + original_stdout = $stdout + $stdout = StringIO.new + begin + block.call + $stdout.string + ensure + $stdout = original_stdout + end +end + +def capture_both &block + original_stdout = $stdout + original_stderr = $stderr + stringio = StringIO.new + $stdout = stringio + $stderr = stringio + begin + block.call + ensure + $stdout = original_stdout + $stderr = original_stderr + end + stringio.string +end diff --git a/spec/type_checker/levels/normal_spec.rb b/spec/type_checker/levels/normal_spec.rb index 3b38f55d8..0b3024f62 100644 --- a/spec/type_checker/levels/normal_spec.rb +++ b/spec/type_checker/levels/normal_spec.rb @@ -1,5 +1,5 @@ describe Solargraph::TypeChecker do - context 'normal level' do + context 'when checking at normal level' do def type_checker(code) Solargraph::TypeChecker.load_string(code, 'test.rb', :normal) end @@ -221,9 +221,9 @@ def bar; end # @todo This test uses kramdown-parser-gfm because it's a gem dependency known to # lack typed methods. A better test wouldn't depend on the state of # vendored code. + workspace = Solargraph::Workspace.new(Dir.pwd) gemspec = Gem::Specification.find_by_name('kramdown-parser-gfm') - yard_pins = Solargraph::GemPins.build_yard_pins([], gemspec) - Solargraph::PinCache.serialize_yard_gem(gemspec, yard_pins) + workspace.cache_gem(gemspec) checker = type_checker(%( require 'kramdown-parser-gfm' diff --git a/spec/yard_map/mapper_spec.rb b/spec/yard_map/mapper_spec.rb index 6b00e5c33..3afa3a4ca 100644 --- a/spec/yard_map/mapper_spec.rb +++ b/spec/yard_map/mapper_spec.rb @@ -1,4 +1,14 @@ describe Solargraph::YardMap::Mapper do + before :all do # rubocop:disable RSpec/BeforeAfterAll + @api_map = Solargraph::ApiMap.load('.') + end + + def pins_with require + doc_map = Solargraph::DocMap.new([require], [], @api_map.workspace, out: nil) # rubocop:disable RSpec/InstanceVariable + doc_map.cache_doc_map_gems!(nil) + doc_map.pins + end + it 'converts nil docstrings to empty strings' do dir = File.absolute_path(File.join('spec', 'fixtures', 'yard_map')) Dir.chdir dir do @@ -14,50 +24,33 @@ it 'marks explicit methods' do # Using rspec-expectations because it's a known dependency - rspec = Gem::Specification.find_by_name('rspec-expectations') - Solargraph::Yardoc.cache([], rspec) - Solargraph::Yardoc.load!(rspec) - pins = Solargraph::YardMap::Mapper.new(YARD::Registry.all).map - pin = pins.find { |pin| pin.path == 'RSpec::Matchers#be_truthy' } + pin = pins_with('rspec/expectations').find { |pin| pin.path == 'RSpec::Matchers#be_truthy' } + expect(pin).not_to be_nil expect(pin.explicit?).to be(true) end it 'marks correct return type from Logger.new' do # Using logger because it's a known dependency - logger = Gem::Specification.find_by_name('logger') - Solargraph::Yardoc.cache([], logger) - registry = Solargraph::Yardoc.load!(logger) - pins = Solargraph::YardMap::Mapper.new(registry).map - pins = pins.select { |pin| pin.path == 'Logger.new' } + pins = pins_with('logger').select { |pin| pin.path == 'Logger.new' } expect(pins.map(&:return_type).uniq.map(&:to_s)).to eq(['self']) end it 'marks correct return type from RuboCop::Options.new' do # Using rubocop because it's a known dependency - rubocop = Gem::Specification.find_by_name('rubocop') - Solargraph::Yardoc.cache([], rubocop) - Solargraph::Yardoc.load!(rubocop) - pins = Solargraph::YardMap::Mapper.new(YARD::Registry.all).map - pins = pins.select { |pin| pin.path == 'RuboCop::Options.new' } + pins = pins_with('rubocop').select { |pin| pin.path == 'RuboCop::Options.new' } expect(pins.map(&:return_type).uniq.map(&:to_s)).to eq(['self']) expect(pins.flat_map(&:signatures).map(&:return_type).uniq.map(&:to_s)).to eq(['self']) end it 'marks non-explicit methods' do # Using rspec-expectations because it's a known dependency - rspec = Gem::Specification.find_by_name('rspec-expectations') - Solargraph::Yardoc.load!(rspec) - pins = Solargraph::YardMap::Mapper.new(YARD::Registry.all).map - pin = pins.find { |pin| pin.path == 'RSpec::Matchers#expect' } + pin = pins_with('rspec/expectations').find { |pin| pin.path == 'RSpec::Matchers#expect' } expect(pin.explicit?).to be(false) end it 'adds superclass references' do # Asssuming the yard gem exists because it's a known dependency - gemspec = Gem::Specification.find_by_name('yard') - Solargraph::Yardoc.cache([], gemspec) - pins = Solargraph::YardMap::Mapper.new(Solargraph::Yardoc.load!(gemspec)).map - pin = pins.find do |pin| + pin = pins_with('yard').find do |pin| pin.is_a?(Solargraph::Pin::Reference::Superclass) && pin.name == 'YARD::CodeObjects::NamespaceObject' end expect(pin.closure.path).to eq('YARD::CodeObjects::ClassObject') @@ -65,10 +58,7 @@ it 'adds include references' do # Asssuming the ast gem exists because it's a known dependency - gemspec = Gem::Specification.find_by_name('ast') - Solargraph::Yardoc.cache([], gemspec) - pins = Solargraph::YardMap::Mapper.new(Solargraph::Yardoc.load!(gemspec)).map - inc= pins.find do |pin| + inc = pins_with('ast').find do |pin| pin.is_a?(Solargraph::Pin::Reference::Include) && pin.name == 'AST::Processor::Mixin' && pin.closure.path == 'AST::Processor' end expect(inc).to be_a(Solargraph::Pin::Reference::Include) @@ -76,10 +66,7 @@ it 'adds extend references' do # Asssuming the yard gem exists because it's a known dependency - gemspec = Gem::Specification.find_by_name('yard') - Solargraph::Yardoc.cache([], gemspec) - pins = Solargraph::YardMap::Mapper.new(Solargraph::Yardoc.load!(gemspec)).map - ext = pins.find do |pin| + ext = pins_with('yard').find do |pin| pin.is_a?(Solargraph::Pin::Reference::Extend) && pin.name == 'Enumerable' && pin.closure.path == 'YARD::Registry' end expect(ext).to be_a(Solargraph::Pin::Reference::Extend) diff --git a/spec/yardoc_spec.rb b/spec/yardoc_spec.rb new file mode 100644 index 000000000..2e821498e --- /dev/null +++ b/spec/yardoc_spec.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +require 'tmpdir' +require 'open3' + +describe Solargraph::Yardoc do + around do |testobj| + @tmpdir = Dir.mktmpdir + + testobj.run + ensure + FileUtils.remove_entry(@tmpdir) # rubocop:disable RSpec/InstanceVariable + end + + let(:gem_yardoc_path) do + File.join(@tmpdir, 'solargraph', 'yardoc', 'test_gem') # rubocop:disable RSpec/InstanceVariable + end + + before do + FileUtils.mkdir_p(gem_yardoc_path) + end + + describe '#processing?' do + it 'returns true if the yardoc is being processed' do + FileUtils.touch(File.join(gem_yardoc_path, 'processing')) + expect(described_class.processing?(gem_yardoc_path)).to be(true) + end + + it 'returns false if the yardoc is not being processed' do + expect(described_class.processing?(gem_yardoc_path)).to be(false) + end + end + + describe '#load!' do + it 'does not blow up when called on empty directory' do + expect { described_class.load!(gem_yardoc_path) }.not_to raise_error + end + end + + describe '#build_docs' do + let(:workspace) { Solargraph::Workspace.new(Dir.pwd) } + let(:gemspec) { workspace.find_gem('rubocop') } + let(:output) { '' } + + before do + allow(Solargraph.logger).to receive(:warn) + allow(Solargraph.logger).to receive(:info) + FileUtils.rm_rf(gem_yardoc_path) + end + + it 'builds docs for a gem' do + described_class.build_docs(gem_yardoc_path, [], gemspec) + expect(File.exist?(File.join(gem_yardoc_path, 'complete'))).to be true + end + + it 'bails quietly if directory given does not exist' do + allow(File).to receive(:exist?).and_return(false) + + expect do + described_class.build_docs(gem_yardoc_path, [], gemspec) + end.not_to raise_error + end + + it 'is idempotent' do + described_class.build_docs(gem_yardoc_path, [], gemspec) + described_class.build_docs(gem_yardoc_path, [], gemspec) # second time + expect(File.exist?(File.join(gem_yardoc_path, 'complete'))).to be true + end + + context 'with an error from yard' do + before do + allow(Open3).to receive(:capture2e).and_return([output, result]) + end + + let(:result) { instance_double(Process::Status) } + + it 'does not raise on error from yard' do + allow(result).to receive(:success?).and_return(false) + + expect do + described_class.build_docs(gem_yardoc_path, [], gemspec) + end.not_to raise_error + end + end + + context 'when given a relative BUNDLE_GEMFILE path' do + around do |example| + # turn absolute BUNDLE_GEMFILE path into relative + existing_gemfile = ENV.fetch('BUNDLE_GEMFILE', nil) + current_dir = Dir.pwd + # remove prefix current_dir from path + ENV['BUNDLE_GEMFILE'] = existing_gemfile.sub("#{current_dir}/", '') + raise 'could not figure out relative path' if Pathname.new(ENV.fetch('BUNDLE_GEMFILE', nil)).absolute? + example.run + ENV['BUNDLE_GEMFILE'] = existing_gemfile + end + + it 'sends Open3 an absolute path' do + called_with = nil + allow(Open3).to receive(:capture2e) do |*args| + called_with = args + ['output', instance_double(Process::Status, success?: true)] + end + + described_class.build_docs(gem_yardoc_path, [], gemspec) + + expect(called_with[0]['BUNDLE_GEMFILE']).to start_with('/') + end + end + end +end From c7b66cf1ae782dda517f6d262551772b4b19af76 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 3 Sep 2025 20:47:37 -0400 Subject: [PATCH 04/81] Exclude more scenarios that RBS does not support --- .github/workflows/rspec.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 7b2255b0e..4038be21a 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -29,7 +29,15 @@ jobs: rbs-version: '3.9.4' - ruby-version: '3.0' rbs-version: '4.0.0.dev.4' - steps: + # Missing require in 'rbs collection update' - hopefully + # fixed in next RBS dev release + - ruby-version: 'head' + rbs-version: '4.0.0.dev.4' + - ruby-version: 'head' + rbs-version: '3.9.4' + - ruby-version: 'head' + rbs-version: '3.6.1' + steps: - uses: actions/checkout@v3 - name: Set up Ruby uses: ruby/setup-ruby@v1 From eb676b70da386a704f0b8cc7b09a5a26e67787d1 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 3 Sep 2025 20:49:09 -0400 Subject: [PATCH 05/81] Fix indentation --- .github/workflows/rspec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 4038be21a..4846551ea 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -37,7 +37,7 @@ jobs: rbs-version: '3.9.4' - ruby-version: 'head' rbs-version: '3.6.1' - steps: + steps: - uses: actions/checkout@v3 - name: Set up Ruby uses: ruby/setup-ruby@v1 From 8ea210411fce0b2fcb8cf4d0b392a98454a2baad Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 3 Sep 2025 23:02:00 -0400 Subject: [PATCH 06/81] Adjust comment location --- .github/workflows/rspec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 4846551ea..0c83e8434 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -23,8 +23,8 @@ jobs: matrix: ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4', 'head'] rbs-version: ['3.6.1', '3.9.4', '4.0.0.dev.4'] - # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 exclude: + # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 - ruby-version: '3.0' rbs-version: '3.9.4' - ruby-version: '3.0' From 2b3152e32da43a8fafe3b6435ba6e1035d5a06a8 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 3 Sep 2025 23:03:04 -0400 Subject: [PATCH 07/81] Ensure using latest RBS version in undercover --- .github/workflows/rspec.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 0c83e8434..6fe05a9b9 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -74,7 +74,9 @@ jobs: ruby-version: '3.4' bundler-cache: false - name: Install gems - run: bundle install + run: | + bundle install + bundle update rbs # use latest available for this Ruby version - name: Install types run: bundle exec rbs collection update - name: Run tests From 1b644b48452e7875233765bc0f2c40361cf84308 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Thu, 4 Sep 2025 09:09:19 -0400 Subject: [PATCH 08/81] Add regression specs --- spec/api_map/index_spec.rb | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 spec/api_map/index_spec.rb diff --git a/spec/api_map/index_spec.rb b/spec/api_map/index_spec.rb new file mode 100644 index 000000000..8afb74759 --- /dev/null +++ b/spec/api_map/index_spec.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +describe Solargraph::ApiMap::Index do + subject(:output_pins) { described_class.new(input_pins).pins } + + describe '#map_overrides' do + let(:foo_class) do + Solargraph::Pin::Namespace.new(name: 'Foo') + end + + let(:foo_initialize) do + init = Solargraph::Pin::Method.new(name: 'initialize', + scope: :instance, + parameters: [], + closure: foo_class) + # no return type specified + param = Solargraph::Pin::Parameter.new(name: 'bar', + closure: init) + init.parameters << param + init + end + + let(:foo_new) do + init = Solargraph::Pin::Method.new(name: 'new', + scope: :class, + parameters: [], + closure: foo_class) + # no return type specified + param = Solargraph::Pin::Parameter.new(name: 'bar', + closure: init) + init.parameters << param + init + end + + let(:foo_override) do + Solargraph::Pin::Reference::Override.from_comment('Foo#initialize', + '@param [String] bar') + end + + let(:input_pins) do + [ + foo_initialize, + foo_new, + foo_override + ] + end + + it 'has a docstring to process on override' do + expect(foo_override.docstring.tags).to be_empty + end + + it 'overrides .new method' do + method_pin = output_pins.find { |pin| pin.path == 'Foo.new' } + first_parameter = method_pin.parameters.first + expect(first_parameter.return_type.tag).to eq('String') + end + + it 'overrides #initialize method in signature' do + method_pin = output_pins.find { |pin| pin.path == 'Foo#initialize' } + first_parameter = method_pin.parameters.first + expect(first_parameter.return_type.tag).to eq('String') + end + end +end From aafaa5d867458d3bb2895387cfc80d067ccd50ad Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Thu, 4 Sep 2025 10:49:29 -0400 Subject: [PATCH 09/81] Ensure overrides are handled properly regardless of state of pin --- lib/solargraph/api_map/index.rb | 12 +++++++----- lib/solargraph/pin/callable.rb | 5 +++++ lib/solargraph/pin/parameter.rb | 5 +++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/solargraph/api_map/index.rb b/lib/solargraph/api_map/index.rb index a5870ff50..8234e4718 100644 --- a/lib/solargraph/api_map/index.rb +++ b/lib/solargraph/api_map/index.rb @@ -169,10 +169,13 @@ def map_overrides ovr.tags.each do |tag| pin.docstring.add_tag(tag) redefine_return_type pin, tag - if new_pin - new_pin.docstring.add_tag(tag) - redefine_return_type new_pin, tag - end + pin.reset_generated! + + next unless new_pin + + new_pin.docstring.add_tag(tag) + redefine_return_type new_pin, tag + new_pin.reset_generated! end end end @@ -189,7 +192,6 @@ def redefine_return_type pin, tag pin.signatures.each do |sig| sig.instance_variable_set(:@return_type, ComplexType.try_parse(tag.type)) end - pin.reset_generated! end end end diff --git a/lib/solargraph/pin/callable.rb b/lib/solargraph/pin/callable.rb index 504dd4862..7d9fd69be 100644 --- a/lib/solargraph/pin/callable.rb +++ b/lib/solargraph/pin/callable.rb @@ -205,6 +205,11 @@ def arity_matches? arguments, with_block true end + def reset_generated! + super + @parameters.each(&:reset_generated!) + end + # @return [Integer] def mandatory_positional_param_count parameters.count(&:arg?) diff --git a/lib/solargraph/pin/parameter.rb b/lib/solargraph/pin/parameter.rb index 512ee0ead..9f58ec067 100644 --- a/lib/solargraph/pin/parameter.rb +++ b/lib/solargraph/pin/parameter.rb @@ -123,6 +123,11 @@ def full_name end end + def reset_generated! + super + @return_type = nil if @return_type&.undefined? + end + # @return [String] def full full_name + case decl From e2ba56923e5e4e26d997a89447cf8fdd8c6433e8 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Thu, 4 Sep 2025 11:03:01 -0400 Subject: [PATCH 10/81] Lint fixes --- spec/yard_map/mapper_spec.rb | 2 +- spec/yardoc_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/yard_map/mapper_spec.rb b/spec/yard_map/mapper_spec.rb index 3afa3a4ca..770d9e9ef 100644 --- a/spec/yard_map/mapper_spec.rb +++ b/spec/yard_map/mapper_spec.rb @@ -4,7 +4,7 @@ end def pins_with require - doc_map = Solargraph::DocMap.new([require], [], @api_map.workspace, out: nil) # rubocop:disable RSpec/InstanceVariable + doc_map = Solargraph::DocMap.new([require], [], @api_map.workspace, out: nil) doc_map.cache_doc_map_gems!(nil) doc_map.pins end diff --git a/spec/yardoc_spec.rb b/spec/yardoc_spec.rb index 2e821498e..6e7171afe 100644 --- a/spec/yardoc_spec.rb +++ b/spec/yardoc_spec.rb @@ -9,11 +9,11 @@ testobj.run ensure - FileUtils.remove_entry(@tmpdir) # rubocop:disable RSpec/InstanceVariable + FileUtils.remove_entry(@tmpdir) end let(:gem_yardoc_path) do - File.join(@tmpdir, 'solargraph', 'yardoc', 'test_gem') # rubocop:disable RSpec/InstanceVariable + File.join(@tmpdir, 'solargraph', 'yardoc', 'test_gem') end before do From bb0f6079024f1e28ee9f12c26bbc626fe475d2ce Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 6 Sep 2025 14:18:16 -0400 Subject: [PATCH 11/81] Rerun rubocop todo --- .rubocop_todo.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 0ed335f34..c55a29039 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -64,7 +64,6 @@ Layout/BlockAlignment: Layout/ClosingHeredocIndentation: Exclude: - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowForAlignment. @@ -167,7 +166,6 @@ Layout/HashAlignment: Layout/HeredocIndentation: Exclude: - 'spec/diagnostics/rubocop_spec.rb' - - 'spec/rbs_map/conversions_spec.rb' - 'spec/yard_map/mapper/to_method_spec.rb' # This cop supports safe autocorrection (--autocorrect). @@ -685,10 +683,13 @@ RSpec/LetBeforeExamples: Exclude: - 'spec/complex_type_spec.rb' -# Configuration parameters: . +# Configuration parameters: EnforcedStyle. # SupportedStyles: have_received, receive RSpec/MessageSpies: - EnforcedStyle: receive + Exclude: + - 'spec/doc_map_spec.rb' + - 'spec/language_server/host/diagnoser_spec.rb' + - 'spec/language_server/host/message_worker_spec.rb' RSpec/MissingExampleGroupArgument: Exclude: @@ -750,10 +751,6 @@ RSpec/ScatteredLet: Exclude: - 'spec/complex_type_spec.rb' -# Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata. -RSpec/SpecFilePathFormat: - Enabled: false - RSpec/StubbedMock: Exclude: - 'spec/language_server/host/message_worker_spec.rb' From 837d7f67872f47619200320bafb7d80da9abad95 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 16:57:05 -0400 Subject: [PATCH 12/81] Force build --- .github/workflows/rspec.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index ecc3d9771..bfa6dce07 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -48,8 +48,8 @@ jobs: run: | bundle install bundle update rbs # use latest available for this Ruby version - - name: Run tests - run: bundle exec rake spec +# - name: Run tests +# run: bundle exec rake spec undercover: runs-on: ubuntu-latest steps: From a4208e71241a3b2e5e2f9198d8d135a065bd7ea4 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:10:41 -0400 Subject: [PATCH 13/81] Restore --- .github/workflows/rspec.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index bfa6dce07..ecc3d9771 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -48,8 +48,8 @@ jobs: run: | bundle install bundle update rbs # use latest available for this Ruby version -# - name: Run tests -# run: bundle exec rake spec + - name: Run tests + run: bundle exec rake spec undercover: runs-on: ubuntu-latest steps: From b66f2ac85a8d5599e36decc6a24fce36eed2f382 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:14:22 -0400 Subject: [PATCH 14/81] install -> update with rbs collection --- .github/workflows/plugins.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 730882e30..b013abd3b 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -164,7 +164,7 @@ jobs: cd ${RAILS_DIR} bundle install bundle exec --gemfile ../../Gemfile rbs --version - bundle exec --gemfile ../../Gemfile rbs collection install + bundle exec --gemfile ../../Gemfile rbs collection update cd ../../ # bundle exec rbs collection init # bundle exec rbs collection install From a09a9af2bc797134fac776c370ce4fcc2c6db121 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:25:05 -0400 Subject: [PATCH 15/81] Try Ruby 3.2 --- .github/workflows/plugins.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index b013abd3b..af9997846 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -144,7 +144,8 @@ jobs: uses: ruby/setup-ruby@v1 with: # solargraph-rails supports Ruby 3.0+ - ruby-version: '3.0' + # RBS 3.9 supports Ruby 3.2+ + ruby-version: '3.2' bundler-cache: false bundler: latest env: @@ -164,7 +165,7 @@ jobs: cd ${RAILS_DIR} bundle install bundle exec --gemfile ../../Gemfile rbs --version - bundle exec --gemfile ../../Gemfile rbs collection update + bundle exec --gemfile ../../Gemfile rbs collection install cd ../../ # bundle exec rbs collection init # bundle exec rbs collection install From 6fc8febcdd4cb9515785e0f85788497ad8923ae7 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:44:39 -0400 Subject: [PATCH 16/81] Update solargraph --- .github/workflows/plugins.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index af9997846..ef9fe0155 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -158,8 +158,7 @@ jobs: export BUNDLE_PATH cd ../solargraph-rails echo "gem 'solargraph', path: '${GITHUB_WORKSPACE:?}'" >> Gemfile - bundle install - bundle update rbs + bundle update solargraph rbs RAILS_DIR="$(pwd)/spec/rails7" export RAILS_DIR cd ${RAILS_DIR} From 388c170d76531530012eb1dff32579a059e3bda6 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:45:56 -0400 Subject: [PATCH 17/81] Re-add bundle install --- .github/workflows/plugins.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index ef9fe0155..a97b27c7c 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -158,6 +158,7 @@ jobs: export BUNDLE_PATH cd ../solargraph-rails echo "gem 'solargraph', path: '${GITHUB_WORKSPACE:?}'" >> Gemfile + bundle install bundle update solargraph rbs RAILS_DIR="$(pwd)/spec/rails7" export RAILS_DIR From f80b73a020dd405addf8f56d2317e31614c2f8da Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:58:16 -0400 Subject: [PATCH 18/81] Drop MATRIX_SOLARGRAPH_VERSION --- .github/workflows/plugins.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index a97b27c7c..4dedbd93f 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -149,7 +149,6 @@ jobs: bundler-cache: false bundler: latest env: - MATRIX_SOLARGRAPH_VERSION: '>=0.56.0.pre1' MATRIX_RAILS_VERSION: "7.0" - name: Install gems run: | @@ -170,7 +169,6 @@ jobs: # bundle exec rbs collection init # bundle exec rbs collection install env: - MATRIX_SOLARGRAPH_VERSION: '>=0.56.0.pre1' MATRIX_RAILS_VERSION: "7.0" MATRIX_RAILS_MAJOR_VERSION: '7' - name: Run specs @@ -184,5 +182,4 @@ jobs: bundle info yard ALLOW_IMPROVEMENTS=true bundle exec rake spec env: - MATRIX_SOLARGRAPH_VERSION: '>=0.56.0.pre1' MATRIX_RAILS_VERSION: "7.0" From ce2bee62f20628f33f1e9abb98f7faf96f69166f Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 18:09:04 -0400 Subject: [PATCH 19/81] Drop debugging changes --- .github/workflows/plugins.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 4dedbd93f..b5984f3cb 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -144,8 +144,7 @@ jobs: uses: ruby/setup-ruby@v1 with: # solargraph-rails supports Ruby 3.0+ - # RBS 3.9 supports Ruby 3.2+ - ruby-version: '3.2' + ruby-version: '3.0' bundler-cache: false bundler: latest env: @@ -158,7 +157,7 @@ jobs: cd ../solargraph-rails echo "gem 'solargraph', path: '${GITHUB_WORKSPACE:?}'" >> Gemfile bundle install - bundle update solargraph rbs + bundle update rbs RAILS_DIR="$(pwd)/spec/rails7" export RAILS_DIR cd ${RAILS_DIR} From dbe9a3edc5291e6cf50632560893306ee074a79f Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 18:40:51 -0400 Subject: [PATCH 20/81] Update expectations from master branch --- .rubocop_todo.yml | 11 ----------- spec/convention_spec.rb | 2 -- 2 files changed, 13 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c55a29039..89f703d23 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -280,7 +280,6 @@ Layout/TrailingWhitespace: Exclude: - 'lib/solargraph/language_server/message/client/register_capability.rb' - 'spec/api_map/config_spec.rb' - - 'spec/convention_spec.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowedMethods, AllowedPatterns. @@ -338,11 +337,6 @@ Lint/DuplicateBranch: Lint/DuplicateMethods: Enabled: false -# Configuration parameters: AllowComments, AllowEmptyLambdas. -Lint/EmptyBlock: - Exclude: - - 'spec/convention_spec.rb' - # Configuration parameters: AllowComments. Lint/EmptyClass: Enabled: false @@ -618,11 +612,6 @@ RSpec/DescribeClass: RSpec/DescribedClass: Enabled: false -# This cop supports unsafe autocorrection (--autocorrect-all). -RSpec/EmptyExampleGroup: - Exclude: - - 'spec/convention_spec.rb' - # This cop supports safe autocorrection (--autocorrect). RSpec/EmptyLineAfterFinalLet: Exclude: diff --git a/spec/convention_spec.rb b/spec/convention_spec.rb index 98a8f41bf..b6f4fc52e 100644 --- a/spec/convention_spec.rb +++ b/spec/convention_spec.rb @@ -1,5 +1,4 @@ describe Solargraph::Convention do - # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations it 'newly defined pins are resolved by ApiMap after file changes' do filename = 'test.rb' @@ -106,5 +105,4 @@ def local _source_map described_class.unregister updated_dummy_convention end - # rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations end From 217fecdcf8bf20402c78348a86aa9f4c083c1a6d Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 18:40:51 -0400 Subject: [PATCH 21/81] Update expectations from master branch --- .rubocop_todo.yml | 11 ----------- spec/convention_spec.rb | 2 -- 2 files changed, 13 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 3965777d9..1b3783d86 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -279,7 +279,6 @@ Layout/TrailingWhitespace: Exclude: - 'lib/solargraph/language_server/message/client/register_capability.rb' - 'spec/api_map/config_spec.rb' - - 'spec/convention_spec.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowedMethods, AllowedPatterns. @@ -337,11 +336,6 @@ Lint/DuplicateBranch: Lint/DuplicateMethods: Enabled: false -# Configuration parameters: AllowComments, AllowEmptyLambdas. -Lint/EmptyBlock: - Exclude: - - 'spec/convention_spec.rb' - # Configuration parameters: AllowComments. Lint/EmptyClass: Enabled: false @@ -609,11 +603,6 @@ RSpec/DescribeClass: RSpec/DescribedClass: Enabled: false -# This cop supports unsafe autocorrection (--autocorrect-all). -RSpec/EmptyExampleGroup: - Exclude: - - 'spec/convention_spec.rb' - # This cop supports safe autocorrection (--autocorrect). RSpec/EmptyLineAfterFinalLet: Exclude: diff --git a/spec/convention_spec.rb b/spec/convention_spec.rb index 98a8f41bf..b6f4fc52e 100644 --- a/spec/convention_spec.rb +++ b/spec/convention_spec.rb @@ -1,5 +1,4 @@ describe Solargraph::Convention do - # rubocop:disable RSpec/ExampleLength, RSpec/MultipleExpectations it 'newly defined pins are resolved by ApiMap after file changes' do filename = 'test.rb' @@ -106,5 +105,4 @@ def local _source_map described_class.unregister updated_dummy_convention end - # rubocop:enable RSpec/ExampleLength, RSpec/MultipleExpectations end From 2d2f0a77d8d17b9dabeee2a65f3ed636e528437b Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:14:22 -0400 Subject: [PATCH 22/81] install -> update with rbs collection --- .github/workflows/plugins.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 730882e30..b013abd3b 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -164,7 +164,7 @@ jobs: cd ${RAILS_DIR} bundle install bundle exec --gemfile ../../Gemfile rbs --version - bundle exec --gemfile ../../Gemfile rbs collection install + bundle exec --gemfile ../../Gemfile rbs collection update cd ../../ # bundle exec rbs collection init # bundle exec rbs collection install From 3db4b1f3b049338fea2f871724c2b6a7d5de7277 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:25:05 -0400 Subject: [PATCH 23/81] Try Ruby 3.2 --- .github/workflows/plugins.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index b013abd3b..af9997846 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -144,7 +144,8 @@ jobs: uses: ruby/setup-ruby@v1 with: # solargraph-rails supports Ruby 3.0+ - ruby-version: '3.0' + # RBS 3.9 supports Ruby 3.2+ + ruby-version: '3.2' bundler-cache: false bundler: latest env: @@ -164,7 +165,7 @@ jobs: cd ${RAILS_DIR} bundle install bundle exec --gemfile ../../Gemfile rbs --version - bundle exec --gemfile ../../Gemfile rbs collection update + bundle exec --gemfile ../../Gemfile rbs collection install cd ../../ # bundle exec rbs collection init # bundle exec rbs collection install From faa64283a3e63ec203d94a8d76ff1de3b14bcd1f Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:44:39 -0400 Subject: [PATCH 24/81] Update solargraph --- .github/workflows/plugins.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index af9997846..ef9fe0155 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -158,8 +158,7 @@ jobs: export BUNDLE_PATH cd ../solargraph-rails echo "gem 'solargraph', path: '${GITHUB_WORKSPACE:?}'" >> Gemfile - bundle install - bundle update rbs + bundle update solargraph rbs RAILS_DIR="$(pwd)/spec/rails7" export RAILS_DIR cd ${RAILS_DIR} From 3f68a02944a1bd249a3ea6d2c5964dd0f467c798 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:45:56 -0400 Subject: [PATCH 25/81] Re-add bundle install --- .github/workflows/plugins.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index ef9fe0155..a97b27c7c 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -158,6 +158,7 @@ jobs: export BUNDLE_PATH cd ../solargraph-rails echo "gem 'solargraph', path: '${GITHUB_WORKSPACE:?}'" >> Gemfile + bundle install bundle update solargraph rbs RAILS_DIR="$(pwd)/spec/rails7" export RAILS_DIR From b8c16054ec9be28fb3143113bd58424af82acdd6 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 17:58:16 -0400 Subject: [PATCH 26/81] Drop MATRIX_SOLARGRAPH_VERSION --- .github/workflows/plugins.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index a97b27c7c..4dedbd93f 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -149,7 +149,6 @@ jobs: bundler-cache: false bundler: latest env: - MATRIX_SOLARGRAPH_VERSION: '>=0.56.0.pre1' MATRIX_RAILS_VERSION: "7.0" - name: Install gems run: | @@ -170,7 +169,6 @@ jobs: # bundle exec rbs collection init # bundle exec rbs collection install env: - MATRIX_SOLARGRAPH_VERSION: '>=0.56.0.pre1' MATRIX_RAILS_VERSION: "7.0" MATRIX_RAILS_MAJOR_VERSION: '7' - name: Run specs @@ -184,5 +182,4 @@ jobs: bundle info yard ALLOW_IMPROVEMENTS=true bundle exec rake spec env: - MATRIX_SOLARGRAPH_VERSION: '>=0.56.0.pre1' MATRIX_RAILS_VERSION: "7.0" From d3a0c36a5ca735759a050e1ccc5114832e01ba36 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 7 Sep 2025 18:09:04 -0400 Subject: [PATCH 27/81] Drop debugging changes --- .github/workflows/plugins.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 4dedbd93f..b5984f3cb 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -144,8 +144,7 @@ jobs: uses: ruby/setup-ruby@v1 with: # solargraph-rails supports Ruby 3.0+ - # RBS 3.9 supports Ruby 3.2+ - ruby-version: '3.2' + ruby-version: '3.0' bundler-cache: false bundler: latest env: @@ -158,7 +157,7 @@ jobs: cd ../solargraph-rails echo "gem 'solargraph', path: '${GITHUB_WORKSPACE:?}'" >> Gemfile bundle install - bundle update solargraph rbs + bundle update rbs RAILS_DIR="$(pwd)/spec/rails7" export RAILS_DIR cd ${RAILS_DIR} From 9b713b27c4f3ced6377b4b352fd249e2bda0ab59 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 9 Sep 2025 11:20:02 -0400 Subject: [PATCH 28/81] Fix combined gem cache implementation --- lib/solargraph/pin_cache.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/solargraph/pin_cache.rb b/lib/solargraph/pin_cache.rb index 8c47cfef4..d48873c53 100644 --- a/lib/solargraph/pin_cache.rb +++ b/lib/solargraph/pin_cache.rb @@ -119,7 +119,8 @@ def uncache_gem gemspec, out: nil PinCache.uncache(yard_gem_path(gemspec), out: out) uncache_by_prefix(rbs_collection_pins_path_prefix(gemspec), out: out) uncache_by_prefix(combined_path_prefix(gemspec), out: out) - combined_pins_in_memory.delete([gemspec.name, gemspec.version]) + rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec) + combined_pins_in_memory.delete([gemspec.name, gemspec.version, rbs_version_cache_key]) end # @param gemspec [Gem::Specification, Bundler::LazySpecification] @@ -380,7 +381,11 @@ def combined_gem? gemspec, hash # @param hash [String, nil] # @return [Array, nil] def load_combined_gem gemspec, hash - PinCache.load(combined_path(gemspec, hash)) + cached = combined_pins_in_memory[[gemspec.name, gemspec.version, hash]] + return cached if cached + loaded = PinCache.load(combined_path(gemspec, hash)) + combined_pins_in_memory[[gemspec.name, gemspec.version, hash]] = loaded if loaded + loaded end # @param gemspec [Gem::Specification] From db725f78fdb3756c917044e35dd6d1eec1c86095 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 13 Sep 2025 16:30:39 -0400 Subject: [PATCH 29/81] Update rubocop todo --- .rubocop_todo.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 89f703d23..f7e83b95f 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -285,7 +285,6 @@ Layout/TrailingWhitespace: # Configuration parameters: AllowedMethods, AllowedPatterns. Lint/AmbiguousBlockAssociation: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/language_server/host.rb' # This cop supports safe autocorrection (--autocorrect). @@ -1108,7 +1107,6 @@ Style/RedundantFreeze: # This cop supports unsafe autocorrection (--autocorrect-all). Style/RedundantInterpolation: Exclude: - - 'lib/solargraph/api_map/store.rb' - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - 'lib/solargraph/source_map/mapper.rb' @@ -1133,7 +1131,6 @@ Style/RedundantRegexpEscape: # Configuration parameters: AllowMultipleReturnValues. Style/RedundantReturn: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/complex_type/type_methods.rb' - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/parser/parser_gem/node_methods.rb' @@ -1268,7 +1265,11 @@ Style/YAMLFileRead: # This cop supports unsafe autocorrection (--autocorrect-all). Style/ZeroLengthPredicate: - Enabled: false + Exclude: + - 'lib/solargraph/language_server/host.rb' + - 'lib/solargraph/pin/method.rb' + - 'lib/solargraph/source/chain/array.rb' + - 'spec/language_server/protocol_spec.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. From a398b84bd2f09c4e9148aee79c8ee0a643c651a1 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 26 Sep 2025 12:45:46 -0400 Subject: [PATCH 30/81] Resolve constants in references Also replaces 'include' logic with call to ApiMap::Constants Fixes #1099 --- lib/solargraph/api_map.rb | 13 +--- lib/solargraph/api_map/constants.rb | 23 ++++--- lib/solargraph/parser/node_methods.rb | 97 --------------------------- spec/api_map/constants_spec.rb | 27 ++++++++ 4 files changed, 44 insertions(+), 116 deletions(-) delete mode 100644 lib/solargraph/parser/node_methods.rb diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index 44ca19035..7f53e7596 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -772,17 +772,8 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false if scope == :instance store.get_includes(fqns).reverse.each do |ref| - const = get_constants('', *ref.closure.gates).find { |pin| pin.path.end_with? ref.name } - if const.is_a?(Pin::Namespace) - result.concat inner_get_methods(const.path, scope, visibility, deep, skip, true) - elsif const.is_a?(Pin::Constant) - type = const.infer(self) - result.concat inner_get_methods(type.namespace, scope, visibility, deep, skip, true) if type.defined? - else - referenced_tag = ref.parametrized_tag - next unless referenced_tag.defined? - result.concat inner_get_methods_from_reference(referenced_tag.to_s, namespace_pin, rooted_type, scope, visibility, deep, skip, true) - end + fqin = dereference(ref) + result.concat inner_get_methods(fqin, scope, visibility, deep, skip, true) end rooted_sc_tag = qualify_superclass(rooted_tag) unless rooted_sc_tag.nil? diff --git a/lib/solargraph/api_map/constants.rb b/lib/solargraph/api_map/constants.rb index 430303ae1..5dbcd4b67 100644 --- a/lib/solargraph/api_map/constants.rb +++ b/lib/solargraph/api_map/constants.rb @@ -12,14 +12,21 @@ def initialize store # Resolve a name to a fully qualified namespace or constant. # - # `Constants#resolve` is similar to `Constants#qualify`` in that its - # purpose is to find fully qualified (absolute) namespaces, except - # `#resolve`` is only concerned with real namespaces. It disregards - # parametrized types and special types like literals, self, and Boolean. + # `Constants#resolve` finds fully qualified (absolute) + # namespaces based on relative names and the open gates + # (namespaces) provided. Names must be runtime-visible (erased) + # non-literal types - e.g., TrueClass, NilClass, Integer and + # Hash instead of true, nil, 96, or Hash{String => Symbol} # - # @param name [String] - # @param gates [Array, String>] - # @return [String, nil] + # Note: You may want to be using #qualify. Notably, #resolve: + # - will not gracefully handle nil, self and Boolean + # - will return a constant name instead of following its assignment + # + # @param name [String] Namespace which may relative and not be rooted. + # @param gates [Array, String>] Namespaces to search while resolving the name + # + # @return [String, nil] fully qualified namespace (i.e., is + # absolute, but will not start with ::) def resolve(name, *gates) return store.get_path_pins(name[2..]).first&.path if name.start_with?('::') @@ -33,7 +40,7 @@ def resolve(name, *gates) # @param pin [Pin::Reference] # @return [String, nil] def dereference pin - resolve(pin.name, pin.reference_gates) + qualify(pin.name, pin.reference_gates) end # Collect a list of all constants defined in the specified gates. diff --git a/lib/solargraph/parser/node_methods.rb b/lib/solargraph/parser/node_methods.rb deleted file mode 100644 index f33a924c1..000000000 --- a/lib/solargraph/parser/node_methods.rb +++ /dev/null @@ -1,97 +0,0 @@ -module Solargraph - module Parser - module NodeMethods - module_function - - # @abstract - # @param node [Parser::AST::Node] - # @return [String] - def unpack_name node - raise NotImplementedError - end - - # @abstract - # @todo Temporarily here for testing. Move to Solargraph::Parser. - # @param node [Parser::AST::Node] - # @return [Array] - def call_nodes_from node - raise NotImplementedError - end - - # Find all the nodes within the provided node that potentially return a - # value. - # - # The node parameter typically represents a method's logic, e.g., the - # second child (after the :args node) of a :def node. A simple one-line - # method would typically return itself, while a node with conditions - # would return the resulting node from each conditional branch. Nodes - # that follow a :return node are assumed to be unreachable. Nil values - # are converted to nil node types. - # - # @abstract - # @param node [Parser::AST::Node] - # @return [Array] - def returns_from_method_body node - raise NotImplementedError - end - - # @abstract - # @param node [Parser::AST::Node] - # - # @return [Array] - def const_nodes_from node - raise NotImplementedError - end - - # @abstract - # @param cursor [Solargraph::Source::Cursor] - # @return [Parser::AST::Node, nil] - def find_recipient_node cursor - raise NotImplementedError - end - - # @abstract - # @param node [Parser::AST::Node] - # @return [Array] low-level value nodes in - # value position. Does not include explicit return - # statements - def value_position_nodes_only(node) - raise NotImplementedError - end - - # @abstract - # @param nodes [Enumerable] - def any_splatted_call?(nodes) - raise NotImplementedError - end - - # @abstract - # @param node [Parser::AST::Node] - # @return [void] - def process node - raise NotImplementedError - end - - # @abstract - # @param node [Parser::AST::Node] - # @return [Hash{Symbol => Source::Chain}] - def convert_hash node - raise NotImplementedError - end - - # @abstract - # @param node [Parser::AST::Node] - # @return [Position] - def get_node_start_position(node) - raise NotImplementedError - end - - # @abstract - # @param node [Parser::AST::Node] - # @return [Position] - def get_node_end_position(node) - raise NotImplementedError - end - end - end -end diff --git a/spec/api_map/constants_spec.rb b/spec/api_map/constants_spec.rb index 26eaf6b25..e09c12c29 100644 --- a/spec/api_map/constants_spec.rb +++ b/spec/api_map/constants_spec.rb @@ -20,6 +20,33 @@ module Quuz expect(resolved).to eq('Foo::Bar') end + it 'resolves constants in includes' do + code = %( + module A + module Parser + module C + module_function + + # @return [String] + def baz; "abc"; end + end + + B = C + end + + class Foo + include Parser::B + + # @return [String] + def bar + baz + end + end + end) + checker = Solargraph::TypeChecker.load_string(code, 'test.rb', :strong) + expect(checker.problems.map(&:message)).to be_empty + end + it 'returns namespaces for nested namespaces' do source_map = Solargraph::SourceMap.load_string(%( module Foo From dd06a479b9f12e797b12caef53bdff482f686426 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 26 Sep 2025 12:51:45 -0400 Subject: [PATCH 31/81] Linting --- spec/api_map/constants_spec.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/api_map/constants_spec.rb b/spec/api_map/constants_spec.rb index e09c12c29..ef07c00b7 100644 --- a/spec/api_map/constants_spec.rb +++ b/spec/api_map/constants_spec.rb @@ -25,8 +25,6 @@ module Quuz module A module Parser module C - module_function - # @return [String] def baz; "abc"; end end From cc86aec403ca74694a408e85e6ccd1f5f5e32343 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 26 Sep 2025 13:00:55 -0400 Subject: [PATCH 32/81] Ratchet RuboCop --- .rubocop_todo.yml | 35 +---------------------------------- lib/solargraph/api_map.rb | 2 -- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 89fd47c5d..0de27608a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --no-exclude-limit --no-offense-counts --no-auto-gen-timestamp` -# using RuboCop version 1.80.2. +# using RuboCop version 1.80.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -280,7 +280,6 @@ Layout/MultilineMethodCallBraceLayout: # SupportedStyles: aligned, indented, indented_relative_to_receiver Layout/MultilineMethodCallIndentation: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/diagnostics/type_check.rb' - 'lib/solargraph/language_server/message/completion_item/resolve.rb' - 'lib/solargraph/language_server/message/text_document/hover.rb' @@ -356,7 +355,6 @@ Layout/SpaceBeforeBlockBraces: - 'lib/solargraph/source.rb' - 'lib/solargraph/source/chain/call.rb' - 'lib/solargraph/source/chain/class_variable.rb' - - 'lib/solargraph/source/chain/constant.rb' - 'lib/solargraph/source/chain/global_variable.rb' - 'lib/solargraph/source/chain/instance_variable.rb' - 'lib/solargraph/source/chain/variable.rb' @@ -433,13 +431,11 @@ Layout/TrailingWhitespace: Exclude: - 'lib/solargraph/language_server/message/client/register_capability.rb' - 'spec/api_map/config_spec.rb' - - 'spec/convention_spec.rb' # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowedMethods, AllowedPatterns. Lint/AmbiguousBlockAssociation: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/language_server/host.rb' # This cop supports safe autocorrection (--autocorrect). @@ -512,11 +508,6 @@ Lint/DuplicateMethods: - 'lib/solargraph/rbs_map/core_map.rb' - 'lib/solargraph/source/chain/link.rb' -# Configuration parameters: AllowComments, AllowEmptyLambdas. -Lint/EmptyBlock: - Exclude: - - 'spec/convention_spec.rb' - # Configuration parameters: AllowComments. Lint/EmptyClass: Exclude: @@ -998,11 +989,6 @@ RSpec/DescribedClass: - 'spec/yard_map/mapper/to_method_spec.rb' - 'spec/yard_map/mapper_spec.rb' -# This cop supports unsafe autocorrection (--autocorrect-all). -RSpec/EmptyExampleGroup: - Exclude: - - 'spec/convention_spec.rb' - # This cop supports safe autocorrection (--autocorrect). RSpec/EmptyLineAfterFinalLet: Exclude: @@ -1321,7 +1307,6 @@ Style/AccessorGrouping: # SupportedStyles: always, conditionals Style/AndOr: Exclude: - - 'lib/solargraph/api_map/source_to_yard.rb' - 'lib/solargraph/complex_type/unique_type.rb' - 'lib/solargraph/language_server/message/base.rb' - 'lib/solargraph/page.rb' @@ -1510,7 +1495,6 @@ Style/Documentation: - 'lib/solargraph/parser.rb' - 'lib/solargraph/parser/comment_ripper.rb' - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/parser/node_methods.rb' - 'lib/solargraph/parser/node_processor/base.rb' - 'lib/solargraph/parser/parser_gem.rb' - 'lib/solargraph/parser/parser_gem/class_methods.rb' @@ -1651,7 +1635,6 @@ Style/FrozenStringLiteralComment: - 'lib/solargraph/parser.rb' - 'lib/solargraph/parser/comment_ripper.rb' - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/parser/node_methods.rb' - 'lib/solargraph/parser/parser_gem.rb' - 'lib/solargraph/parser/snippet.rb' - 'lib/solargraph/pin/breakable.rb' @@ -1782,7 +1765,6 @@ Style/GlobalStdStream: # Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. Style/GuardClause: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/library.rb' - 'lib/solargraph/parser/parser_gem/node_processors/send_node.rb' - 'lib/solargraph/pin_cache.rb' @@ -1835,7 +1817,6 @@ Style/IfInsideElse: # This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/api_map/index.rb' - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/complex_type/unique_type.rb' @@ -1903,7 +1884,6 @@ Style/MethodDefParentheses: Exclude: - 'lib/solargraph.rb' - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - 'lib/solargraph/api_map/store.rb' - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/complex_type/type_methods.rb' @@ -1925,7 +1905,6 @@ Style/MethodDefParentheses: - 'lib/solargraph/location.rb' - 'lib/solargraph/parser/comment_ripper.rb' - 'lib/solargraph/parser/flow_sensitive_typing.rb' - - 'lib/solargraph/parser/node_methods.rb' - 'lib/solargraph/parser/node_processor/base.rb' - 'lib/solargraph/parser/parser_gem/flawed_builder.rb' - 'lib/solargraph/parser/parser_gem/node_chainer.rb' @@ -1947,7 +1926,6 @@ Style/MethodDefParentheses: - 'lib/solargraph/shell.rb' - 'lib/solargraph/source.rb' - 'lib/solargraph/source/chain/call.rb' - - 'lib/solargraph/source/chain/constant.rb' - 'lib/solargraph/source_map.rb' - 'lib/solargraph/source_map/mapper.rb' - 'lib/solargraph/type_checker.rb' @@ -2049,8 +2027,6 @@ Style/NumericLiterals: Style/NumericPredicate: Exclude: - 'spec/**/*' - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - 'lib/solargraph/api_map/store.rb' - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/complex_type/type_methods.rb' @@ -2131,7 +2107,6 @@ Style/RedundantFreeze: # This cop supports unsafe autocorrection (--autocorrect-all). Style/RedundantInterpolation: Exclude: - - 'lib/solargraph/api_map/store.rb' - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - 'lib/solargraph/source_map/mapper.rb' @@ -2143,7 +2118,6 @@ Style/RedundantParentheses: - 'lib/solargraph/parser/parser_gem/node_chainer.rb' - 'lib/solargraph/pin/method.rb' - 'lib/solargraph/pin/parameter.rb' - - 'lib/solargraph/pin/search.rb' - 'lib/solargraph/source.rb' - 'lib/solargraph/type_checker.rb' @@ -2170,7 +2144,6 @@ Style/RedundantRegexpEscape: # Configuration parameters: AllowMultipleReturnValues. Style/RedundantReturn: Exclude: - - 'lib/solargraph/api_map.rb' - 'lib/solargraph/complex_type/type_methods.rb' - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/parser/parser_gem/node_methods.rb' @@ -2269,8 +2242,6 @@ Style/StderrPuts: # Configuration parameters: Mode. Style/StringConcatenation: Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - 'lib/solargraph/pin/base.rb' - 'lib/solargraph/pin/callable.rb' - 'lib/solargraph/pin/closure.rb' @@ -2286,7 +2257,6 @@ Style/StringLiterals: Exclude: - 'Gemfile' - 'Rakefile' - - 'lib/solargraph/api_map/index.rb' - 'lib/solargraph/complex_type.rb' - 'lib/solargraph/complex_type/unique_type.rb' - 'lib/solargraph/convention/struct_definition.rb' @@ -2504,8 +2474,6 @@ Style/YAMLFileRead: # This cop supports unsafe autocorrection (--autocorrect-all). Style/ZeroLengthPredicate: Exclude: - - 'lib/solargraph/api_map.rb' - - 'lib/solargraph/api_map/index.rb' - 'lib/solargraph/language_server/host.rb' - 'lib/solargraph/pin/method.rb' - 'lib/solargraph/source/chain/array.rb' @@ -2614,7 +2582,6 @@ Layout/LineLength: - 'lib/solargraph/workspace.rb' - 'lib/solargraph/workspace/config.rb' - 'lib/solargraph/yard_map/mapper/to_method.rb' - - 'spec/api_map_spec.rb' - 'spec/complex_type_spec.rb' - 'spec/language_server/message/completion_item/resolve_spec.rb' - 'spec/language_server/message/extended/check_gem_version_spec.rb' diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index 7f53e7596..7bac1395c 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -737,7 +737,6 @@ def store # @param skip [Set] # @param no_core [Boolean] Skip core classes if true # @return [Array] - # rubocop:disable Metrics/CyclomaticComplexity def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false rooted_type = ComplexType.parse(rooted_tag).force_rooted fqns = rooted_type.namespace @@ -802,7 +801,6 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false end result end - # rubocop:enable Metrics/CyclomaticComplexity # @return [Hash] def path_macros From 343cd23307e00ae0c0d4952514f326eac209de5b Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 26 Sep 2025 14:36:29 -0400 Subject: [PATCH 33/81] Fix lack of parameters in include types --- lib/solargraph/api_map.rb | 6 ++-- lib/solargraph/api_map/constants.rb | 37 +++++++++++++-------- lib/solargraph/api_map/store.rb | 2 +- lib/solargraph/complex_type/type_methods.rb | 4 +++ lib/solargraph/pin/reference.rb | 13 ++------ 5 files changed, 34 insertions(+), 28 deletions(-) diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index 7bac1395c..14d33b1d7 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -771,8 +771,8 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false if scope == :instance store.get_includes(fqns).reverse.each do |ref| - fqin = dereference(ref) - result.concat inner_get_methods(fqin, scope, visibility, deep, skip, true) + in_tag = dereference(ref) + result.concat inner_get_methods_from_reference(in_tag, namespace_pin, rooted_type, scope, visibility, deep, skip, true) end rooted_sc_tag = qualify_superclass(rooted_tag) unless rooted_sc_tag.nil? @@ -781,7 +781,7 @@ def inner_get_methods rooted_tag, scope, visibility, deep, skip, no_core = false else logger.info { "ApiMap#inner_get_methods(#{fqns}, #{scope}, #{visibility}, #{deep}, #{skip}) - looking for get_extends() from #{fqns}" } store.get_extends(fqns).reverse.each do |em| - fqem = store.constants.dereference(em) + fqem = dereference(em) result.concat inner_get_methods(fqem, :instance, visibility, deep, skip, true) unless fqem.nil? end rooted_sc_tag = qualify_superclass(rooted_tag) diff --git a/lib/solargraph/api_map/constants.rb b/lib/solargraph/api_map/constants.rb index 5dbcd4b67..0b6070507 100644 --- a/lib/solargraph/api_map/constants.rb +++ b/lib/solargraph/api_map/constants.rb @@ -15,10 +15,12 @@ def initialize store # `Constants#resolve` finds fully qualified (absolute) # namespaces based on relative names and the open gates # (namespaces) provided. Names must be runtime-visible (erased) - # non-literal types - e.g., TrueClass, NilClass, Integer and - # Hash instead of true, nil, 96, or Hash{String => Symbol} + # non-literal types, non-duck, non-signature types - e.g., + # TrueClass, NilClass, Integer and Hash instead of true, nil, + # 96, or Hash{String => Symbol} # # Note: You may want to be using #qualify. Notably, #resolve: + # - does not handle anything with type parameters # - will not gracefully handle nil, self and Boolean # - will return a constant name instead of following its assignment # @@ -40,7 +42,7 @@ def resolve(name, *gates) # @param pin [Pin::Reference] # @return [String, nil] def dereference pin - qualify(pin.name, pin.reference_gates) + qualify_type(pin.type, pin.reference_gates)&.tag end # Collect a list of all constants defined in the specified gates. @@ -52,27 +54,36 @@ def collect(*gates) cached_collect[flat] || collect_and_cache(flat) end - # Determine a fully qualified namespace for a given name referenced - # from the specified open gates. This method will search in each gate - # until it finds a match for the name. + # Determine a fully qualified namespace for a given tag + # referenced from the specified open gates. This method will + # search in each gate until it finds a match for the name. # - # @param name [String, nil] The namespace to match + # @param tag [String, nil] The type to match # @param gates [Array] # @return [String, nil] fully qualified tag - def qualify name, *gates - return name if ['Boolean', 'self', nil].include?(name) + def qualify tag, *gates + type = ComplexType.try_parse(tag) + qualify_type(type)&.tag + end + + # @param type [ComplexType, nil] The type to match + # @param gates [Array] + # + # @return [ComplexType, nil] A new rooted ComplexType + def qualify_type type, *gates + return nil if type.nil? + return type if type.selfy? || type.literal? || type.tag == 'nil' || type.interface? gates.push '' unless gates.include?('') - fqns = resolve(name, gates) + fqns = resolve(type.namespace, type.namespace) return unless fqns pin = store.get_path_pins(fqns).first if pin.is_a?(Pin::Constant) const = Solargraph::Parser::NodeMethods.unpack_name(pin.assignment) return unless const - resolve(const, pin.gates) - else - fqns + fqns = resolve(const, pin.gates) end + type.recreate(new_name: fqns, rooted: true) end # @return [void] diff --git a/lib/solargraph/api_map/store.rb b/lib/solargraph/api_map/store.rb index b3953cfec..a0b2ae856 100644 --- a/lib/solargraph/api_map/store.rb +++ b/lib/solargraph/api_map/store.rb @@ -244,7 +244,7 @@ def get_ancestors(fqns) # Add includes, prepends, and extends [get_includes(current), get_prepends(current), get_extends(current)].each do |refs| next if refs.nil? - refs.map(&:parametrized_tag).map(&:to_s).each do |ref| + refs.map(&:type).map(&:to_s).each do |ref| next if ref.nil? || ref.empty? || visited.include?(ref) ancestors << ref queue << ref diff --git a/lib/solargraph/complex_type/type_methods.rb b/lib/solargraph/complex_type/type_methods.rb index d8d4fc7d7..1145bd034 100644 --- a/lib/solargraph/complex_type/type_methods.rb +++ b/lib/solargraph/complex_type/type_methods.rb @@ -43,6 +43,10 @@ def rooted_tag @rooted_tag ||= rooted_name + rooted_substring end + def interface? + name.start_with?('_') + end + # @return [Boolean] def duck_type? @duck_type ||= name.start_with?('#') diff --git a/lib/solargraph/pin/reference.rb b/lib/solargraph/pin/reference.rb index d678ab7b7..d456fbbf8 100644 --- a/lib/solargraph/pin/reference.rb +++ b/lib/solargraph/pin/reference.rb @@ -18,18 +18,9 @@ def initialize generic_values: [], **splat @generic_values = generic_values end - # @return [String] - def parameter_tag - @parameter_tag ||= if generic_values&.any? - "<#{generic_values.join(', ')}>" - else - '' - end - end - # @return [ComplexType] - def parametrized_tag - @parametrized_tag ||= ComplexType.try_parse( + def type + @type ||= ComplexType.try_parse( name + if generic_values&.length&.> 0 "<#{generic_values.join(', ')}>" From d787886b956aa9b5d748fe4003f0ceb1b4dcd4ca Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 26 Sep 2025 15:16:22 -0400 Subject: [PATCH 34/81] Bug fixes --- lib/solargraph/api_map.rb | 2 +- lib/solargraph/api_map/constants.rb | 13 +++++++------ lib/solargraph/api_map/source_to_yard.rb | 4 ++-- lib/solargraph/api_map/store.rb | 2 +- lib/solargraph/complex_type.rb | 15 +++++++++++++++ .../convention/active_support_concern.rb | 2 +- 6 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index 14d33b1d7..286761db2 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -662,7 +662,7 @@ def super_and_sub?(sup, sub) # # @return [Boolean] def type_include?(host_ns, module_ns) - store.get_includes(host_ns).map { |inc_tag| inc_tag.parametrized_tag.name }.include?(module_ns) + store.get_includes(host_ns).map { |inc_tag| inc_tag.type.name }.include?(module_ns) end # @param pins [Enumerable] diff --git a/lib/solargraph/api_map/constants.rb b/lib/solargraph/api_map/constants.rb index 0b6070507..9463e2037 100644 --- a/lib/solargraph/api_map/constants.rb +++ b/lib/solargraph/api_map/constants.rb @@ -42,7 +42,7 @@ def resolve(name, *gates) # @param pin [Pin::Reference] # @return [String, nil] def dereference pin - qualify_type(pin.type, pin.reference_gates)&.tag + qualify_type(pin.type, *pin.reference_gates)&.tag end # Collect a list of all constants defined in the specified gates. @@ -63,7 +63,7 @@ def collect(*gates) # @return [String, nil] fully qualified tag def qualify tag, *gates type = ComplexType.try_parse(tag) - qualify_type(type)&.tag + qualify_type(type, *gates)&.tag end # @param type [ComplexType, nil] The type to match @@ -72,18 +72,19 @@ def qualify tag, *gates # @return [ComplexType, nil] A new rooted ComplexType def qualify_type type, *gates return nil if type.nil? - return type if type.selfy? || type.literal? || type.tag == 'nil' || type.interface? + return type if type.selfy? || type.literal? || type.tag == 'nil' || type.interface? || + type.tag == 'Boolean' gates.push '' unless gates.include?('') - fqns = resolve(type.namespace, type.namespace) + fqns = resolve(type.rooted_namespace, *gates) return unless fqns pin = store.get_path_pins(fqns).first if pin.is_a?(Pin::Constant) const = Solargraph::Parser::NodeMethods.unpack_name(pin.assignment) return unless const - fqns = resolve(const, pin.gates) + fqns = resolve(const, *pin.gates) end - type.recreate(new_name: fqns, rooted: true) + type.recreate(new_name: fqns, make_rooted: true) end # @return [void] diff --git a/lib/solargraph/api_map/source_to_yard.rb b/lib/solargraph/api_map/source_to_yard.rb index ccbed3eb6..39d86a85c 100644 --- a/lib/solargraph/api_map/source_to_yard.rb +++ b/lib/solargraph/api_map/source_to_yard.rb @@ -46,13 +46,13 @@ def rake_yard store store.get_includes(pin.path).each do |ref| include_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject) unless include_object.nil? || include_object.nil? - include_object.instance_mixins.push code_object_map[ref.parametrized_tag.to_s] + include_object.instance_mixins.push code_object_map[ref.type.to_s] end end store.get_extends(pin.path).each do |ref| extend_object = code_object_at(pin.path, YARD::CodeObjects::ClassObject) next unless extend_object - code_object = code_object_map[ref.parametrized_tag.to_s] + code_object = code_object_map[ref.type.to_s] next unless code_object extend_object.class_mixins.push code_object # @todo add spec showing why this next line is necessary diff --git a/lib/solargraph/api_map/store.rb b/lib/solargraph/api_map/store.rb index a0b2ae856..d97d1d342 100644 --- a/lib/solargraph/api_map/store.rb +++ b/lib/solargraph/api_map/store.rb @@ -97,7 +97,7 @@ def qualify_superclass fq_sub_tag return unless ref res = constants.dereference(ref) return unless res - res + type.substring + res end # @param fqns [String] diff --git a/lib/solargraph/complex_type.rb b/lib/solargraph/complex_type.rb index 8798ecb88..db378743f 100644 --- a/lib/solargraph/complex_type.rb +++ b/lib/solargraph/complex_type.rb @@ -105,6 +105,21 @@ def can_assign?(api_map, atype) any? { |ut| ut.can_assign?(api_map, atype) } end + # @param new_name [String, nil] + # @param make_rooted [Boolean, nil] + # @param new_key_types [Array, nil] + # @param rooted [Boolean, nil] + # @param new_subtypes [Array, nil] + # @return [self] + def recreate(new_name: nil, make_rooted: nil, new_key_types: nil, new_subtypes: nil) + ComplexType.new(map do |ut| + ut.recreate(new_name: new_name, + make_rooted: make_rooted, + new_key_types: new_key_types, + new_subtypes: new_subtypes) + end) + end + # @return [Integer] def length @items.length diff --git a/lib/solargraph/convention/active_support_concern.rb b/lib/solargraph/convention/active_support_concern.rb index 74c9ce765..ed1fba175 100644 --- a/lib/solargraph/convention/active_support_concern.rb +++ b/lib/solargraph/convention/active_support_concern.rb @@ -80,7 +80,7 @@ def process_include include_tag "ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \ "Handling class include include_tag=#{include_tag}" end - module_extends = api_map.get_extends(rooted_include_tag).map(&:parametrized_tag).map(&:to_s) + module_extends = api_map.get_extends(rooted_include_tag).map(&:type).map(&:to_s) logger.debug do "ActiveSupportConcern#object(#{fqns}, #{scope}, #{visibility}, #{deep}) - " \ "found module extends of #{rooted_include_tag}: #{module_extends}" From 63a53dbed3be0c68d0eac7a7a61dd031b6c8466d Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 26 Sep 2025 15:35:50 -0400 Subject: [PATCH 35/81] Add actual type for Mutexes --- lib/solargraph/language_server/progress.rb | 2 +- lib/solargraph/library.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/solargraph/language_server/progress.rb b/lib/solargraph/language_server/progress.rb index 10900a37e..98b155714 100644 --- a/lib/solargraph/language_server/progress.rb +++ b/lib/solargraph/language_server/progress.rb @@ -134,7 +134,7 @@ def keep_alive host end end - # @return [Mutex] + # @return [Thread::Mutex] def mutex @mutex ||= Mutex.new end diff --git a/lib/solargraph/library.rb b/lib/solargraph/library.rb index 9d5162431..bdbd1354f 100644 --- a/lib/solargraph/library.rb +++ b/lib/solargraph/library.rb @@ -522,7 +522,7 @@ def find_external_requires source_map @external_requires = nil end - # @return [Mutex] + # @return [Thread::Mutex] def mutex @mutex ||= Mutex.new end From 7546f7355534c70d3ae9ddbb863304d5be557d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lek=C3=AB=20Mula?= Date: Sun, 21 Sep 2025 17:41:33 +0200 Subject: [PATCH 36/81] Enable solargraph-rspec tests --- .github/workflows/plugins.yml | 55 ++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index b5984f3cb..ded3be5a0 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -105,30 +105,37 @@ jobs: - name: Ensure specs still run run: bundle exec rake spec - # run_solargraph_rspec_specs: - # # check out solargraph-rspec as well as this project, and point the former to use the latter as a local gem - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v3 - # - name: clone https://github.com/lekemula/solargraph-rspec/ - # run: | - # cd .. - # git clone https://github.com/lekemula/solargraph-rspec.git - # cd solargraph-rspec - # - name: Set up Ruby - # uses: ruby/setup-ruby@v1 - # with: - # ruby-version: '3.0' - # bundler-cache: false - # - name: Install gems - # run: | - # cd ../solargraph-rspec - # echo "gem 'solargraph', path: '../solargraph'" >> Gemfile - # bundle install - # - name: Run specs - # run: | - # cd ../solargraph-rspec - # bundle exec rake spec + run_solargraph_rspec_specs: + # check out solargraph-rspec as well as this project, and point the former to use the latter as a local gem + runs-on: ubuntu-latest + env: + SOLARGRAPH_CACHE: ${{ github.workspace }}/solargraph-rspec/vendor/solargraph/cache + steps: + - uses: actions/checkout@v3 + - name: clone https://github.com/lekemula/solargraph-rspec/ + run: | + cd .. + git clone https://github.com/lekemula/solargraph-rspec.git + cd solargraph-rspec + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.4 + bundler-cache: true + - name: Install gems + run: | + cd ../solargraph-rspec + echo "gem 'solargraph', path: '../solargraph'" >> Gemfile + bundle install + - name: Solargraph generate RSpec gems YARD and RBS pins + run: | + cd ../solargraph-rspec + rspec_gems=$(bundle exec ruby -r './lib/solargraph-rspec' -e 'puts Solargraph::Rspec::Gems.gem_names.join(" ")' 2>/dev/null | tail -n1) + bundle exec solargraph gems $rspec_gems + - name: Run specs + run: | + cd ../solargraph-rspec + bundle exec rspec run_solargraph_rails_specs: # check out solargraph-rails as well as this project, and point the former to use the latter as a local gem From 9c79e5b3a01ac3fd8d84b35b94e4cb4110f91b2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lek=C3=AB=20Mula?= Date: Sun, 21 Sep 2025 19:40:15 +0200 Subject: [PATCH 37/81] Fix rspec gems specs --- .github/workflows/plugins.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index ded3be5a0..1c633fda0 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -109,7 +109,8 @@ jobs: # check out solargraph-rspec as well as this project, and point the former to use the latter as a local gem runs-on: ubuntu-latest env: - SOLARGRAPH_CACHE: ${{ github.workspace }}/solargraph-rspec/vendor/solargraph/cache + SOLARGRAPH_CACHE: ${{ github.workspace }}/../solargraph-rspec/vendor/solargraph/cache + BUNDLE_PATH: ${{ github.workspace }}/../solargraph-rspec/vendor/bundle steps: - uses: actions/checkout@v3 - name: clone https://github.com/lekemula/solargraph-rspec/ @@ -121,12 +122,17 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: 3.4 - bundler-cache: true + bundler-cache: false - name: Install gems run: | cd ../solargraph-rspec echo "gem 'solargraph', path: '../solargraph'" >> Gemfile - bundle install + bundle config path ${{ env.BUNDLE_PATH }} + bundle install --jobs 4 --retry 3 + - name: Configure .solargraph.yml + run: | + cd ../solargraph-rspec + cp .solargraph.yml.example .solargraph.yml - name: Solargraph generate RSpec gems YARD and RBS pins run: | cd ../solargraph-rspec @@ -135,7 +141,7 @@ jobs: - name: Run specs run: | cd ../solargraph-rspec - bundle exec rspec + bundle exec rspec --format progress run_solargraph_rails_specs: # check out solargraph-rails as well as this project, and point the former to use the latter as a local gem From 1416e1d1e3f51c5c44dea3807796cbccccd870d3 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 28 Sep 2025 12:08:05 -0400 Subject: [PATCH 38/81] Reduce number of build jobs for faster CI feedback This takes out some lower value combinations - ideally we could keep the number of jobs to <= 20, which is the max that GHA will run simultaneously here. --- .github/workflows/rspec.yml | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index ecc3d9771..33d09b579 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -23,12 +23,26 @@ jobs: matrix: ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4', 'head'] rbs-version: ['3.6.1', '3.9.4', '4.0.0.dev.4'] - # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 exclude: + # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 - ruby-version: '3.0' rbs-version: '3.9.4' - ruby-version: '3.0' rbs-version: '4.0.0.dev.4' + # only include the 3.1 variants we include later + - ruby-version: '3.1' + # only include the 3.2 variants we include later + - ruby-version: '3.2' + # only include the 3.3 variants we include later + - ruby-version: '3.3' + include: + - ruby-version: '3.1' + rbs_version: '3.6.1' + - ruby-version: '3.2' + rbs_version: '3.9.4' + - ruby-version: '3.3' + rbs_version: '4.0.0.dev.4' + steps: - uses: actions/checkout@v3 - name: Set up Ruby From f2abb735f39f7adb08d4a487dd4c6a1b76acbfd2 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 28 Sep 2025 12:10:38 -0400 Subject: [PATCH 39/81] Fix punctuation --- .github/workflows/rspec.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 33d09b579..76003b412 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -37,12 +37,11 @@ jobs: - ruby-version: '3.3' include: - ruby-version: '3.1' - rbs_version: '3.6.1' + rbs-version: '3.6.1' - ruby-version: '3.2' - rbs_version: '3.9.4' + rbs-version: '3.9.4' - ruby-version: '3.3' - rbs_version: '4.0.0.dev.4' - + rbs-version: '4.0.0.dev.4' steps: - uses: actions/checkout@v3 - name: Set up Ruby From eabe151b3dc4fce0600d0e5c62850907b74101c2 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 30 Sep 2025 10:41:55 -0400 Subject: [PATCH 40/81] Update rubocop todo --- .rubocop_todo.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4ab62a41f..7d2e33136 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -34,7 +34,6 @@ Gemspec/OrderedDependencies: # Configuration parameters: Severity. Gemspec/RequireMFA: Exclude: - - 'solargraph.gemspec' - 'spec/fixtures/rdoc-lib/rdoc-lib.gemspec' - 'spec/fixtures/rubocop-custom-version/specifications/rubocop-0.0.0.gemspec' @@ -89,13 +88,6 @@ Layout/EmptyLineBetweenDefs: Layout/EmptyLines: Enabled: false -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle. -# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines, beginning_only, ending_only -Layout/EmptyLinesAroundClassBody: - Exclude: - - 'lib/solargraph/rbs_map/core_map.rb' - # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. # SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines @@ -1266,6 +1258,7 @@ YARD/TagTypeSyntax: Exclude: - 'lib/solargraph/language_server/host.rb' - 'lib/solargraph/parser/comment_ripper.rb' + - 'lib/solargraph/pin/method.rb' - 'lib/solargraph/type_checker.rb' # This cop supports safe autocorrection (--autocorrect). From ce3ce8c3ed11ec0031d53ad01163b43bc029d9eb Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 30 Sep 2025 10:51:49 -0400 Subject: [PATCH 41/81] Fix merge issue --- lib/solargraph/api_map.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index a7462fb50..695de0230 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -109,7 +109,6 @@ def catalog bench if recreate_docmap @doc_map = DocMap.new(unresolved_requires, [], bench.workspace, out: nil) # @todo Implement gem preferences - @gemspecs = @doc_map.workspace.gemspecs @unresolved_requires = @doc_map.unresolved_requires end @cache.clear if store.update(@@core_map.pins, @doc_map.pins, conventions_environ.pins, iced_pins, live_pins) From a6bdfd6336f0e12833fc7a52d87bc47eab39b14b Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 30 Sep 2025 10:57:41 -0400 Subject: [PATCH 42/81] Drop no-longer-needed @sg-ignores --- lib/solargraph/library.rb | 1 - lib/solargraph/yardoc.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/lib/solargraph/library.rb b/lib/solargraph/library.rb index 1faa6a9ba..a14dc40ee 100644 --- a/lib/solargraph/library.rb +++ b/lib/solargraph/library.rb @@ -609,7 +609,6 @@ def cache_next_gemspec report_cache_progress spec.name, pending kwargs = {} kwargs[:chdir] = workspace.directory.to_s if workspace.directory && !workspace.directory.empty? - # @sg-ignore Unresolved call to capture3 on Module _o, e, s = Open3.capture3(workspace.command_path, 'cache', spec.name, spec.version.to_s, **kwargs) if s.success? diff --git a/lib/solargraph/yardoc.rb b/lib/solargraph/yardoc.rb index ffe7da4c3..50f212f13 100644 --- a/lib/solargraph/yardoc.rb +++ b/lib/solargraph/yardoc.rb @@ -28,7 +28,6 @@ def build_docs gem_yardoc_path, yard_plugins, gemspec return end - # @sg-ignore stdout_and_stderr_str, status = Open3.capture2e(current_bundle_env_tweaks, cmd, chdir: gemspec.gem_dir) return if status.success? Solargraph.logger.warn { "YARD failed running #{cmd.inspect} in #{gemspec.gem_dir}" } From d486e6485d4cce9d182da079c588c3821c69cfa6 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 30 Sep 2025 22:36:37 -0400 Subject: [PATCH 43/81] Trim more matrix entries to make room for solargraph-rspec specs --- .github/workflows/rspec.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 76003b412..628bbc8ab 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -35,6 +35,8 @@ jobs: - ruby-version: '3.2' # only include the 3.3 variants we include later - ruby-version: '3.3' + # only include the 3.4 variants we include later + - ruby-version: '3.3' include: - ruby-version: '3.1' rbs-version: '3.6.1' @@ -42,6 +44,8 @@ jobs: rbs-version: '3.9.4' - ruby-version: '3.3' rbs-version: '4.0.0.dev.4' + - ruby-version: '3.4' + rbs-version: '4.0.0.dev.4' steps: - uses: actions/checkout@v3 - name: Set up Ruby From 56342d4a9ff7c1141372404883cd2ddd1f337de7 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 30 Sep 2025 22:50:42 -0400 Subject: [PATCH 44/81] Fix version number --- .github/workflows/rspec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 628bbc8ab..cc4efda4b 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -36,7 +36,7 @@ jobs: # only include the 3.3 variants we include later - ruby-version: '3.3' # only include the 3.4 variants we include later - - ruby-version: '3.3' + - ruby-version: '3.4' include: - ruby-version: '3.1' rbs-version: '3.6.1' From 88e1f7391e2a330185fe626de6ee6212e5076d48 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sun, 5 Oct 2025 21:36:50 -0400 Subject: [PATCH 45/81] Fix merge --- spec/yard_map/mapper_spec.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/spec/yard_map/mapper_spec.rb b/spec/yard_map/mapper_spec.rb index 84d2db90c..14451b97f 100644 --- a/spec/yard_map/mapper_spec.rb +++ b/spec/yard_map/mapper_spec.rb @@ -64,12 +64,9 @@ def pins_with require expect(inc).to be_a(Solargraph::Pin::Reference::Include) end - it 'adds corect gates' do + it 'adds correct gates' do # Asssuming the ast gem exists because it's a known dependency - gemspec = Gem::Specification.find_by_name('ast') - Solargraph::Yardoc.cache([], gemspec) - pins = Solargraph::YardMap::Mapper.new(Solargraph::Yardoc.load!(gemspec)).map - pin = pins.find do |pin| + pin = pins_with('ast').find do |pin| pin.is_a?(Solargraph::Pin::Namespace) && pin.name == 'Mixin' && pin.closure.path == 'AST::Processor' end expect(pin.gates).to eq(['AST::Processor::Mixin', 'AST::Processor', 'AST', '']) From 81ae528a633f654b67414eaea87b56ab8b796203 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Mon, 6 Oct 2025 17:49:55 -0400 Subject: [PATCH 46/81] CLI 'solargraph gems' improvements * Consolidate shell.rb's gem resolution behind the Workspace class so it can take advantage of improvements in other PRs (e.g., pulling info from the bundle directly to resolve gemspecs) * Add documentation on 'solargraph gems' * Allow request to cache core pins from 'solargraph cache' and 'solargraph gems' * Ensure stdlib is cached in 'solargraph gems' --- .rubocop_todo.yml | 1 - lib/solargraph/api_map.rb | 18 ++++------ lib/solargraph/doc_map.rb | 1 - lib/solargraph/shell.rb | 67 ++++++++++++++++++++++++------------- lib/solargraph/workspace.rb | 28 ++++++++++++++-- spec/api_map_method_spec.rb | 32 ++++++++++++++++++ spec/shell_spec.rb | 37 +++++++++++++++++--- spec/workspace_spec.rb | 37 ++++++++++++++++++++ 8 files changed, 177 insertions(+), 44 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 425e66c9a..e86360523 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -80,7 +80,6 @@ Layout/ElseAlignment: # Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines. Layout/EmptyLineBetweenDefs: Exclude: - - 'lib/solargraph/doc_map.rb' - 'lib/solargraph/language_server/message/initialize.rb' - 'lib/solargraph/pin/delegated_method.rb' diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index 695de0230..8a45a3ebd 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -123,8 +123,10 @@ def catalog bench [self.class, @source_map_hash, conventions_environ, @doc_map, @unresolved_requires] end - # @return [DocMap, nil] - attr_reader :doc_map + # @return [DocMap] + def doc_map + @doc_map ||= DocMap.new([], [], Workspace.new('.')) + end # @return [::Array] def uncached_gemspecs @@ -189,15 +191,7 @@ def self.load directory # @param out [IO, nil] # @return [void] def cache_all_for_doc_map! out - @doc_map.cache_doc_map_gems!(out) - end - - # @param gemspec [Gem::Specification] - # @param rebuild [Boolean] - # @param out [IO, nil] - # @return [void] - def cache_gem(gemspec, rebuild: false, out: nil) - @doc_map.cache(gemspec, rebuild: rebuild, out: out) + doc_map.cache_doc_map_gems!(out) end class << self @@ -676,7 +670,7 @@ def resolve_method_aliases pins, visibility = [:public, :private, :protected] # @return [Workspace, nil] def workspace - @doc_map&.workspace + doc_map.workspace end # @param fq_reference_tag [String] A fully qualified whose method should be pulled in diff --git a/lib/solargraph/doc_map.rb b/lib/solargraph/doc_map.rb index 9f119c94c..0691110f5 100644 --- a/lib/solargraph/doc_map.rb +++ b/lib/solargraph/doc_map.rb @@ -250,7 +250,6 @@ def only_runtime_dependencies gemspec gemspec.dependencies - gemspec.development_dependencies end - def inspect self.class.inspect end diff --git a/lib/solargraph/shell.rb b/lib/solargraph/shell.rb index 735e6c290..240fac654 100755 --- a/lib/solargraph/shell.rb +++ b/lib/solargraph/shell.rb @@ -104,9 +104,8 @@ def clear # @param gem [String] # @param version [String, nil] def cache gem, version = nil - api_map = Solargraph::ApiMap.load(Dir.pwd) - spec = Gem::Specification.find_by_name(gem, version) - api_map.cache_gem(spec, rebuild: options[:rebuild], out: $stdout) + gems(gem + (version ? "=#{version}" : '')) + # ' end desc 'uncache GEM [...GEM]', "Delete specific cached gem documentation" @@ -132,28 +131,60 @@ def uncache *gems next end - spec = Gem::Specification.find_by_name(gem) + spec = workspace.find_gem(gem) workspace.uncache_gem(spec, out: $stdout) end end - desc 'gems [GEM[=VERSION]]', 'Cache documentation for installed gems' + desc 'gems [GEM[=VERSION]...] [STDLIB...] [core]', 'Cache documentation for + installed libraries' + long_desc %( This command will cache the + generated type documentation for the specified libraries. While + Solargraph will generate this on the fly when needed, it takes + time. This command will generate it in advance, which can be + useful for CI scenarios. + + With no arguments, it will cache all libraries in the current + workspace. If a gem or standard library name is specified, it + will cache that library's type documentation. + + An equals sign after a gem will allow a specific gem version + to be cached. + + The 'core' argument can be used to cache the type + documentation for the core Ruby libraries. + + If the library is already cached, it will be rebuilt if the + --rebuild option is set. + + Cached documentation is stored in #{PinCache.base_dir}, which + can be stored between CI runs. + ) option :rebuild, type: :boolean, desc: 'Rebuild existing documentation', default: false # @param names [Array] # @return [void] def gems *names - api_map = ApiMap.load('.') + # print time with ms + workspace = Solargraph::Workspace.new('.') + if names.empty? - Gem::Specification.to_a.each { |spec| do_cache spec, api_map } - STDERR.puts "Documentation cached for all #{Gem::Specification.count} gems." + workspace.cache_all_for_workspace!($stdout, rebuild: options[:rebuild]) else + $stderr.puts("Caching these gems: #{names}") names.each do |name| - spec = Gem::Specification.find_by_name(*name.split('=')) - do_cache spec, api_map - rescue Gem::MissingSpecError - warn "Gem '#{name}' not found" + if name == 'core' + PinCache.cache_core(out: $stdout) if !PinCache.core? || options[:rebuild] + next + end + + gemspec = workspace.find_gem(*name.split('=')) + if gemspec.nil? + warn "Gem '#{name}' not found" + else + workspace.cache_gem(gemspec, rebuild: options[:rebuild], out: $stdout) + end end - STDERR.puts "Documentation cached for #{names.count} gems." + $stderr.puts "Documentation cached for #{names.count} gems." end end @@ -194,7 +225,6 @@ def typecheck *files filecount += 1 probcount += problems.length end - # " } puts "Typecheck finished in #{time.real} seconds." puts "#{probcount} problem#{probcount != 1 ? 's' : ''} found#{files.length != 1 ? " in #{filecount} of #{files.length} files" : ''}." @@ -261,14 +291,5 @@ def pin_description pin desc += " (#{pin.location.filename} #{pin.location.range.start.line})" if pin.location desc end - - # @param gemspec [Gem::Specification] - # @param api_map [ApiMap] - # @return [void] - def do_cache gemspec, api_map - # @todo if the rebuild: option is passed as a positional arg, - # typecheck doesn't complain on the below line - api_map.cache_gem(gemspec, rebuild: options.rebuild, out: $stdout) - end end end diff --git a/lib/solargraph/workspace.rb b/lib/solargraph/workspace.rb index 2697e90e0..5e0f07750 100644 --- a/lib/solargraph/workspace.rb +++ b/lib/solargraph/workspace.rb @@ -22,7 +22,8 @@ class Workspace attr_reader :gemnames alias source_gems gemnames - # @param directory [String] TODO: Document and test '' and '*' semantics + # @todo Remove '' and '*' special cases + # @param directory [String] # @param config [Config, nil] # @param server [Hash] def initialize directory = '', config = nil, server = {} @@ -66,7 +67,7 @@ def stdlib_dependencies stdlib_name def global_environ # empty docmap, since the result needs to work in any possible # context here - @global_environ ||= Convention.for_global(DocMap.new([], [], self)) + @global_environ ||= Convention.for_global(DocMap.new([], [], self, out: nil)) end # @param gemspec [Gem::Specification, Bundler::LazySpecification] @@ -195,6 +196,29 @@ def find_gem name, version = nil nil end + # @param out [IO, nil] output stream for logging + # @param rebuild [Boolean] whether to rebuild the pins even if they are cached + # @return [void] + def cache_all_for_workspace! out, rebuild: false + PinCache.cache_core(out: out) unless PinCache.core? + + # @type [Array] + gem_specs = Gem::Specification.to_a + # try any possible standard libraries, but be quiet about it + stdlib_specs = pin_cache.possible_stdlibs.map { |stdlib| find_gem(stdlib, out: nil) }.compact + specs = (gem_specs + stdlib_specs) + specs.each do |spec| + pin_cache.cache_gem(gemspec: spec, rebuild: rebuild, out: out) unless pin_cache.cached?(spec) + end + out&.puts "Documentation cached for all #{specs.length} gems." + + # do this after so that we prefer stdlib requires from gems, + # which are likely to be newer and have more pins + pin_cache.cache_all_stdlibs(out: out) + + out&.puts "Documentation cached for core, standard library and gems." + end + # Synchronize the workspace from the provided updater. # # @param updater [Source::Updater] diff --git a/spec/api_map_method_spec.rb b/spec/api_map_method_spec.rb index 9d4e4f553..b4202e557 100644 --- a/spec/api_map_method_spec.rb +++ b/spec/api_map_method_spec.rb @@ -133,6 +133,38 @@ class B end end + describe '#cache_all_for_doc_map!' do + it 'can cache gems without a bench' do + api_map = Solargraph::ApiMap.new + doc_map = instance_double(Solargraph::DocMap, cache_doc_map_gems!: true) + allow(Solargraph::DocMap).to receive(:new).and_return(doc_map) + api_map.cache_all_for_doc_map!($stderr) + expect(doc_map).to have_received(:cache_doc_map_gems!).with($stderr) + end + end + + describe '#cache_gem' do + it 'can cache gem without a bench' do + api_map = Solargraph::ApiMap.new + gemspec = Gem::Specification.find_by_name('backport') + expect { api_map.cache_gem(gemspec, out: StringIO.new) }.not_to raise_error + end + end + + describe '#workspace' do + it 'can get a default workspace without a bench' do + api_map = Solargraph::ApiMap.new + expect(api_map.workspace).not_to be_nil + end + end + + describe '#uncached_gemspecs' do + it 'can get uncached gemspecs workspace without a bench' do + api_map = Solargraph::ApiMap.new + expect(api_map.uncached_gemspecs).not_to be_nil + end + end + describe '#get_methods' do it 'recognizes mixin references from context' do source = Solargraph::Source.load_string(%( diff --git a/spec/shell_spec.rb b/spec/shell_spec.rb index 6e2a83074..f5eeb5734 100644 --- a/spec/shell_spec.rb +++ b/spec/shell_spec.rb @@ -10,12 +10,14 @@ before do File.open(File.join(temp_dir, 'Gemfile'), 'w') do |file| file.puts "source 'https://rubygems.org'" - file.puts "gem 'solargraph', path: #{File.expand_path('..', __dir__)}" + file.puts "gem 'solargraph', path: '#{File.expand_path('..', __dir__)}'" end output, status = Open3.capture2e("bundle install", chdir: temp_dir) raise "Failure installing bundle: #{output}" unless status.success? end + # @type cmd [Array] + # @return [String] def bundle_exec(*cmd) # run the command in the temporary directory with bundle exec output, status = Open3.capture2e("bundle exec #{cmd.join(' ')}", chdir: temp_dir) @@ -111,8 +113,6 @@ def bundle_exec(*cmd) end it 'caches core without erroring out' do - pending('https://github.com/castwide/solargraph/pull/1061') - capture_both do shell.uncache('core') end @@ -128,6 +128,35 @@ def bundle_exec(*cmd) expect(output).to include("Gem 'solargraph123' not found") end end + + context 'with mocked Workspace' do + let(:workspace) { instance_double(Solargraph::Workspace) } + let(:gemspec) { instance_double(Gem::Specification, name: 'backport') } + + before do + allow(Solargraph::Workspace).to receive(:new).and_return(workspace) + end + + it 'caches all without erroring out' do + allow(workspace).to receive(:cache_all_for_workspace!) + + _output = capture_both { shell.gems } + + expect(workspace).to have_received(:cache_all_for_workspace!) + end + + it 'caches single gem without erroring out' do + allow(workspace).to receive(:find_gem).with('backport').and_return(gemspec) + allow(workspace).to receive(:cache_gem) + + capture_both do + shell.options = { rebuild: false } + shell.gems('backport') + end + + expect(workspace).to have_received(:cache_gem).with(gemspec, out: an_instance_of(StringIO), rebuild: false) + end + end end describe 'cache' do @@ -139,8 +168,6 @@ def bundle_exec(*cmd) subject(:call) { shell.cache('nonexistentgem8675309') } it 'gives a good error message' do - pending('https://github.com/castwide/solargraph/pull/1061') - # capture stderr output expect { call }.to output(/not found/).to_stderr end diff --git a/spec/workspace_spec.rb b/spec/workspace_spec.rb index db8141249..8b5a67aa8 100644 --- a/spec/workspace_spec.rb +++ b/spec/workspace_spec.rb @@ -132,4 +132,41 @@ Solargraph::Workspace.new('./path', config) }.not_to raise_error end + + describe '#cache_all_for_workspace!' do + let(:pin_cache) { instance_double(Solargraph::PinCache) } + + before do + allow(Solargraph::PinCache).to receive(:cache_core) + allow(Solargraph::PinCache).to receive(:possible_stdlibs) + allow(Solargraph::PinCache).to receive(:new).and_return(pin_cache) + allow(pin_cache).to receive_messages(cache_gem: nil, possible_stdlibs: []) + allow(Solargraph::PinCache).to receive(:cache_all_stdlibs) + end + + it 'caches core pins' do + allow(Solargraph::PinCache).to receive_messages(core?: false) + allow(pin_cache).to receive_messages(cached?: true, + cache_all_stdlibs: nil) + + workspace.cache_all_for_workspace!(nil, rebuild: false) + + expect(Solargraph::PinCache).to have_received(:cache_core).with(out: nil) + end + + it 'caches gems' do + gemspec = instance_double(Gem::Specification, name: 'test_gem', version: '1.0.0') + allow(Gem::Specification).to receive(:to_a).and_return([gemspec]) + allow(pin_cache).to receive(:cached?).and_return(false) + allow(pin_cache).to receive(:cache_all_stdlibs).with(out: nil) + + allow(Solargraph::PinCache).to receive_messages(core?: true, + possible_stdlibs: []) + + workspace.cache_all_for_workspace!(nil, rebuild: false) + + expect(pin_cache).to have_received(:cache_gem).with(gemspec: gemspec, out: nil, + rebuild: false) + end + end end From 915c5aab23a3f048d1ae2a5f021be578f2121f9d Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Mon, 6 Oct 2025 18:03:37 -0400 Subject: [PATCH 47/81] Allow PR to build --- .github/workflows/linting.yml | 2 +- .github/workflows/plugins.yml | 2 +- .github/workflows/rspec.yml | 2 +- .github/workflows/typecheck.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index b4ef26bfe..6262dd494 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -8,7 +8,7 @@ name: Linting on: workflow_dispatch: {} pull_request: - branches: [ master ] + branches: ['*'] push: branches: - 'main' diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index b5984f3cb..871252fcc 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -9,7 +9,7 @@ on: push: branches: [master] pull_request: - branches: [master] + branches: ['*'] permissions: contents: read diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 6fe05a9b9..12399f50b 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -11,7 +11,7 @@ on: push: branches: [ master ] pull_request: - branches: [ master ] + branches: ['*'] permissions: contents: read diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 0ae8a3d8a..9f0020065 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -11,7 +11,7 @@ on: push: branches: [ master ] pull_request: - branches: [ master ] + branches: ['*'] permissions: contents: read From 9e29680b0e7d67f4c6165db6d028d3ea87f806c4 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Mon, 6 Oct 2025 18:11:47 -0400 Subject: [PATCH 48/81] Drop spec --- spec/api_map_method_spec.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/spec/api_map_method_spec.rb b/spec/api_map_method_spec.rb index b4202e557..0ee0238cf 100644 --- a/spec/api_map_method_spec.rb +++ b/spec/api_map_method_spec.rb @@ -143,14 +143,6 @@ class B end end - describe '#cache_gem' do - it 'can cache gem without a bench' do - api_map = Solargraph::ApiMap.new - gemspec = Gem::Specification.find_by_name('backport') - expect { api_map.cache_gem(gemspec, out: StringIO.new) }.not_to raise_error - end - end - describe '#workspace' do it 'can get a default workspace without a bench' do api_map = Solargraph::ApiMap.new From 7b4982392773415b9e25bafddebeefedad81e61e Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 8 Oct 2025 07:29:09 -0400 Subject: [PATCH 49/81] Add space for better future merge --- lib/solargraph/workspace.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/solargraph/workspace.rb b/lib/solargraph/workspace.rb index 5e0f07750..36e85efe8 100644 --- a/lib/solargraph/workspace.rb +++ b/lib/solargraph/workspace.rb @@ -196,14 +196,21 @@ def find_gem name, version = nil nil end + # @todo make this actually work against bundle instead of pulling + # all installed gemspecs - + # https://github.com/apiology/solargraph/pull/10 + # @return [Array] + def all_gemspecs_from_bundle + Gem::Specification.to_a + end + # @param out [IO, nil] output stream for logging # @param rebuild [Boolean] whether to rebuild the pins even if they are cached # @return [void] def cache_all_for_workspace! out, rebuild: false PinCache.cache_core(out: out) unless PinCache.core? - # @type [Array] - gem_specs = Gem::Specification.to_a + gem_specs = all_gemspecs_from_bundle # try any possible standard libraries, but be quiet about it stdlib_specs = pin_cache.possible_stdlibs.map { |stdlib| find_gem(stdlib, out: nil) }.compact specs = (gem_specs + stdlib_specs) From d9fa32f6bd89dceefb1eafc423a3dafaefa97eaf Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 8 Oct 2025 15:54:51 -0400 Subject: [PATCH 50/81] Fix a Gem::Specification class limitation found on another branch --- lib/solargraph/doc_map.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/solargraph/doc_map.rb b/lib/solargraph/doc_map.rb index 9f119c94c..79ba2c5d8 100644 --- a/lib/solargraph/doc_map.rb +++ b/lib/solargraph/doc_map.rb @@ -92,14 +92,16 @@ def unresolved_requires @unresolved_requires ||= required_gems_map.select { |_, gemspecs| gemspecs.nil? }.keys end - # @return [Set] + # @return [Array] # @param out [IO] def dependencies out: $stderr @dependencies ||= begin - all_deps = gemspecs.flat_map { |spec| fetch_dependencies(spec, out: out) } + all_deps = gemspecs. + flat_map { |spec| fetch_dependencies(spec, out: out) }. + uniq(&:name) existing_gems = gemspecs.map(&:name) - all_deps.reject { |gemspec| existing_gems.include? gemspec.name }.to_set + all_deps.reject { |gemspec| existing_gems.include? gemspec.name } end end From f4f1620db6319034202fc2c72afce5f9d9db2f0d Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 8 Oct 2025 16:00:34 -0400 Subject: [PATCH 51/81] Fix RuboCop issues --- lib/solargraph/doc_map.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/solargraph/doc_map.rb b/lib/solargraph/doc_map.rb index 79ba2c5d8..cc3a4aed6 100644 --- a/lib/solargraph/doc_map.rb +++ b/lib/solargraph/doc_map.rb @@ -97,9 +97,9 @@ def unresolved_requires def dependencies out: $stderr @dependencies ||= begin - all_deps = gemspecs. - flat_map { |spec| fetch_dependencies(spec, out: out) }. - uniq(&:name) + all_deps = gemspecs + .flat_map { |spec| fetch_dependencies(spec, out: out) } + .uniq(&:name) existing_gems = gemspecs.map(&:name) all_deps.reject { |gemspec| existing_gems.include? gemspec.name } end From bf950718d1180b6aabe12a35b90c82f88fc34a6a Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 8 Oct 2025 19:12:11 -0400 Subject: [PATCH 52/81] Restore actions config --- .github/workflows/linting.yml | 2 +- .github/workflows/plugins.yml | 2 +- .github/workflows/rspec.yml | 2 +- .github/workflows/typecheck.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 6262dd494..b4ef26bfe 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -8,7 +8,7 @@ name: Linting on: workflow_dispatch: {} pull_request: - branches: ['*'] + branches: [ master ] push: branches: - 'main' diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 871252fcc..b5984f3cb 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -9,7 +9,7 @@ on: push: branches: [master] pull_request: - branches: ['*'] + branches: [master] permissions: contents: read diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 12399f50b..6fe05a9b9 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -11,7 +11,7 @@ on: push: branches: [ master ] pull_request: - branches: ['*'] + branches: [ master ] permissions: contents: read diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 9f0020065..0ae8a3d8a 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -11,7 +11,7 @@ on: push: branches: [ master ] pull_request: - branches: ['*'] + branches: [ master ] permissions: contents: read From 6b9bce8e58ce3d17e9e1f23f90aa81914ec85d3f Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Mon, 1 Dec 2025 12:22:31 -0500 Subject: [PATCH 53/81] Annotation fixes --- lib/solargraph/api_map.rb | 8 ++-- lib/solargraph/doc_map.rb | 6 ++- lib/solargraph/pin_cache.rb | 68 +++++++++++++++--------------- lib/solargraph/rbs_map.rb | 2 +- lib/solargraph/rbs_map/core_map.rb | 2 +- lib/solargraph/shell.rb | 1 + lib/solargraph/workspace.rb | 4 +- lib/solargraph/yardoc.rb | 4 +- 8 files changed, 49 insertions(+), 46 deletions(-) diff --git a/lib/solargraph/api_map.rb b/lib/solargraph/api_map.rb index 695de0230..f99de7ffa 100755 --- a/lib/solargraph/api_map.rb +++ b/lib/solargraph/api_map.rb @@ -30,7 +30,7 @@ def initialize pins: [] index pins end - # @param out [IO, nil] output stream for logging + # @param out [StringIO, IO, nil] output stream for logging # @return [void] def self.reset_core out: nil @@core_map = RbsMap::CoreMap.new @@ -136,7 +136,7 @@ def core_pins @@core_map.pins end - # @param name [String] + # @param name [String, nil] # @return [YARD::Tags::MacroDirective, nil] def named_macro name store.named_macros[name] @@ -186,7 +186,7 @@ def self.load directory api_map end - # @param out [IO, nil] + # @param out [StringIO, IO, nil] # @return [void] def cache_all_for_doc_map! out @doc_map.cache_doc_map_gems!(out) @@ -209,7 +209,7 @@ class << self # # # @param directory [String] - # @param out [IO] The output stream for messages + # @param out [IO, StringIO, nil] The output stream for messages # # @return [ApiMap] def self.load_with_cache directory, out = $stderr diff --git a/lib/solargraph/doc_map.rb b/lib/solargraph/doc_map.rb index cc3a4aed6..a82d1eebd 100644 --- a/lib/solargraph/doc_map.rb +++ b/lib/solargraph/doc_map.rb @@ -36,6 +36,7 @@ def requires end alias required requires + # @sg-ignore Translate to something flow sensitive typing understands # @return [Array] def uncached_gemspecs if @uncached_gemspecs.nil? @@ -66,7 +67,7 @@ def any_uncached? end # Cache all pins needed for the sources in this doc_map - # @param out [IO, nil] output stream for logging + # @param out [StringIO, IO, nil] output stream for logging # @return [void] def cache_doc_map_gems! out unless uncached_gemspecs.empty? @@ -109,7 +110,7 @@ def dependencies out: $stderr # # @param gemspec [Gem::Specification] # @param rebuild [Boolean] whether to rebuild the pins even if they are cached - # @param out [IO, nil] output stream for logging + # @param out [StringIO, IO, nil] output stream for logging # # @return [void] def cache gemspec, rebuild: false, out: nil @@ -235,6 +236,7 @@ def change_gemspec_version gemspec, version # @return [Array] def fetch_dependencies gemspec, out: nil # @param spec [Gem::Dependency] + # @param deps [Set] only_runtime_dependencies(gemspec).each_with_object(Set.new) do |spec, deps| Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}" dep = Gem.loaded_specs[spec.name] diff --git a/lib/solargraph/pin_cache.rb b/lib/solargraph/pin_cache.rb index fb3b8d7a4..97f5f5d6a 100644 --- a/lib/solargraph/pin_cache.rb +++ b/lib/solargraph/pin_cache.rb @@ -29,7 +29,7 @@ def cached? gemspec # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @param rebuild [Boolean] whether to rebuild the cache regardless of whether it already exists - # @param out [IO, nil] output stream for logging + # @param out [StringIO, IO, nil] output stream for logging # @return [void] def cache_gem gemspec:, rebuild: false, out: nil rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec) @@ -50,7 +50,7 @@ def cache_gem gemspec:, rebuild: false, out: nil end # @param gemspec [Gem::Specification, Bundler::LazySpecification] - # @param rbs_version_cache_key [String] + # @param rbs_version_cache_key [String, nil] def suppress_yard_cache? gemspec, rbs_version_cache_key if gemspec.name == 'parser' && rbs_version_cache_key != RbsMap::CACHE_KEY_UNRESOLVED # parser takes forever to build YARD pins, but has excellent RBS collection pins @@ -59,7 +59,7 @@ def suppress_yard_cache? gemspec, rbs_version_cache_key false end - # @param out [IO, nil] output stream for logging + # @param out [StringIO, IO, nil] output stream for logging # # @return [void] def cache_all_stdlibs out: $stderr @@ -93,8 +93,8 @@ def lookup_rbs_version_cache_key gemspec rbs_map.cache_key end - # @param gemspec [Gem::Specification] - # @param rbs_version_cache_key [String] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param rbs_version_cache_key [String, nil] # @param yard_pins [Array] # @param rbs_collection_pins [Array] # @return [void] @@ -103,16 +103,16 @@ def cache_combined_pins gemspec, rbs_version_cache_key, yard_pins, rbs_collectio serialize_combined_gem(gemspec, rbs_version_cache_key, combined_pins) end - # @param gemspec [Gem::Specification] - # @return [Array] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @return [Array, nil] def deserialize_combined_pin_cache gemspec rbs_version_cache_key = lookup_rbs_version_cache_key(gemspec) load_combined_gem(gemspec, rbs_version_cache_key) end - # @param gemspec [Gem::Specification] - # @param out [IO, nil] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param out [StringIO, IO, nil] # @return [void] def uncache_gem gemspec, out: nil PinCache.uncache(yardoc_path(gemspec), out: out) @@ -172,7 +172,7 @@ def calculate_build_needs gemspec, rebuild:, rbs_version_cache_key: # @param build_yard [Boolean] # @param build_rbs_collection [Boolean] # @param build_combined [Boolean] - # @param out [IO, nil] + # @param out [StringIO, IO, nil] # # @return [void] def build_combine_and_cache gemspec, @@ -199,7 +199,7 @@ def build_combine_and_cache gemspec, # @param build_yard [Boolean] # @param build_rbs_collection [Boolean] # @param build_combined [Boolean] - # @param out [IO, nil] + # @param out [StringIO, IO, nil] # # @return [void] def log_cache_info gemspec, @@ -223,7 +223,7 @@ def log_cache_info gemspec, end # @param gemspec [Gem::Specification, Bundler::LazySpecification] - # @param out [IO, nil] + # @param out [StringIO, IO, nil] # @return [Array] def cache_yard_pins gemspec, out gem_yardoc_path = yardoc_path(gemspec) @@ -239,8 +239,8 @@ def combined_pins_in_memory PinCache.all_combined_pins_in_memory[yard_plugins] ||= {} end - # @param gemspec [Gem::Specification] - # @param _out [IO, nil] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param _out [StringIO, IO, nil] # @return [Array] def cache_rbs_collection_pins gemspec, _out rbs_map = RbsMap.from_gemspec(gemspec, rbs_collection_path, rbs_collection_config_path) @@ -258,8 +258,8 @@ def cache_rbs_collection_pins gemspec, _out pins end - # @param gemspec [Gem::Specification] - # @return [Array] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @return [Array, nil] def deserialize_yard_pin_cache gemspec cached = load_yard_gem(gemspec) if cached @@ -271,7 +271,7 @@ def deserialize_yard_pin_cache gemspec end # @param gemspec [Gem::Specification, Bundler::LazySpecification] - # @param rbs_version_cache_key [String] + # @param rbs_version_cache_key [String, nil] # @return [Array] def deserialize_rbs_collection_cache gemspec, rbs_version_cache_key cached = load_rbs_collection_pins(gemspec, rbs_version_cache_key) @@ -288,7 +288,7 @@ def yard_path_components yard_plugins.sort.uniq.join('-')] end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @return [String] def yardoc_path gemspec File.join(PinCache.base_dir, @@ -296,39 +296,39 @@ def yardoc_path gemspec "#{gemspec.name}-#{gemspec.version}.yardoc") end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @return [String] def yard_gem_path gemspec File.join(PinCache.work_dir, *yard_path_components, "#{gemspec.name}-#{gemspec.version}.ser") end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @return [Array, nil] def load_yard_gem gemspec PinCache.load(yard_gem_path(gemspec)) end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @param pins [Array] # @return [void] def serialize_yard_gem gemspec, pins PinCache.save(yard_gem_path(gemspec), pins) end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @return [Boolean] def yard_gem? gemspec exist?(yard_gem_path(gemspec)) end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @param hash [String, nil] # @return [String] def rbs_collection_pins_path gemspec, hash rbs_collection_pins_path_prefix(gemspec) + "#{hash || 0}.ser" end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @return [String] def rbs_collection_pins_path_prefix gemspec File.join(PinCache.work_dir, 'rbs', "#{gemspec.name}-#{gemspec.version}-") @@ -342,7 +342,7 @@ def load_rbs_collection_pins gemspec, hash PinCache.load(rbs_collection_pins_path(gemspec, hash)) end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @param hash [String, nil] # @param pins [Array] # @return [void] @@ -350,20 +350,20 @@ def serialize_rbs_collection_pins gemspec, hash, pins PinCache.save(rbs_collection_pins_path(gemspec, hash), pins) end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @param hash [String, nil] # @return [String] def combined_path gemspec, hash File.join(combined_path_prefix(gemspec) + "-#{hash || 0}.ser") end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @return [String] def combined_path_prefix gemspec File.join(PinCache.work_dir, 'combined', yard_plugins.sort.join('-'), "#{gemspec.name}-#{gemspec.version}") end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @param hash [String, nil] # @param pins [Array] # @return [void] @@ -377,7 +377,7 @@ def combined_gem? gemspec, hash exist?(combined_path(gemspec, hash)) end - # @param gemspec [Gem::Specification] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] # @param hash [String, nil] # @return [Array, nil] def load_combined_gem gemspec, hash @@ -388,8 +388,8 @@ def load_combined_gem gemspec, hash loaded end - # @param gemspec [Gem::Specification] - # @param hash [String] + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param hash [String, nil] def rbs_collection_pins? gemspec, hash exist?(rbs_collection_pins_path(gemspec, hash)) end @@ -447,7 +447,7 @@ def uncache *path_segments, out: nil end end - # @param out [IO, nil] + # @param out [StringIO, IO, nil] # @return [void] def uncache_core out: nil uncache(core_path, out: out) @@ -455,7 +455,7 @@ def uncache_core out: nil ApiMap.reset_core(out: out) end - # @param out [IO, nil] + # @param out [StringIO, IO, nil] # @return [void] def uncache_stdlib out: nil uncache(stdlib_path, out: out) @@ -629,7 +629,7 @@ def core? File.file?(core_path) end - # @param out [IO, nil] + # @param out [StringIO, IO, nil] # @return [Array] def cache_core out: $stderr RbsMap::CoreMap.new.cache_core(out: out) diff --git a/lib/solargraph/rbs_map.rb b/lib/solargraph/rbs_map.rb index f6309bb55..a5b998ff0 100644 --- a/lib/solargraph/rbs_map.rb +++ b/lib/solargraph/rbs_map.rb @@ -43,7 +43,7 @@ def initialize library, version = nil, rbs_collection_config_path: nil, rbs_coll CACHE_KEY_STDLIB = 'stdlib' CACHE_KEY_LOCAL = 'local' - # @param cache_key [String] + # @param cache_key [String, nil] # @return [String, nil] a description of the source of the RBS info def self.rbs_source_desc cache_key case cache_key diff --git a/lib/solargraph/rbs_map/core_map.rb b/lib/solargraph/rbs_map/core_map.rb index 275dbbcf4..8fe2afc83 100644 --- a/lib/solargraph/rbs_map/core_map.rb +++ b/lib/solargraph/rbs_map/core_map.rb @@ -22,7 +22,7 @@ def pins out: $stderr @pins = cache_core(out: out) end - # @param out [IO, nil] output stream for logging + # @param out [StringIO, IO, nil] output stream for logging # @return [Array] def cache_core out: $stderr new_pins = [] diff --git a/lib/solargraph/shell.rb b/lib/solargraph/shell.rb index 735e6c290..2a45a67ec 100755 --- a/lib/solargraph/shell.rb +++ b/lib/solargraph/shell.rb @@ -80,6 +80,7 @@ def config(directory = '.') conf['extensions'].push m end end + # @param file [File] File.open(File.join(directory, '.solargraph.yml'), 'w') do |file| file.puts conf.to_yaml end diff --git a/lib/solargraph/workspace.rb b/lib/solargraph/workspace.rb index 2697e90e0..72a802623 100644 --- a/lib/solargraph/workspace.rb +++ b/lib/solargraph/workspace.rb @@ -70,7 +70,7 @@ def global_environ end # @param gemspec [Gem::Specification, Bundler::LazySpecification] - # @param out [IO, nil] output stream for logging + # @param out [StringIO, IO, nil] output stream for logging # @param rebuild [Boolean] whether to rebuild the pins even if they are cached # # @return [void] @@ -79,7 +79,7 @@ def cache_gem gemspec, out: nil, rebuild: false end # @param gemspec [Gem::Specification, Bundler::LazySpecification] - # @param out [IO, nil] output stream for logging + # @param out [StringIO, IO, nil] output stream for logging # # @return [void] def uncache_gem gemspec, out: nil diff --git a/lib/solargraph/yardoc.rb b/lib/solargraph/yardoc.rb index 50f212f13..a7f5d2ab8 100644 --- a/lib/solargraph/yardoc.rb +++ b/lib/solargraph/yardoc.rb @@ -35,8 +35,8 @@ def build_docs gem_yardoc_path, yard_plugins, gemspec end # @param gem_yardoc_path [String] the path to the yardoc cache of a particular gem - # @param gemspec [Gem::Specification] - # @param out [IO, nil] where to log messages + # @param gemspec [Gem::Specification, Bundler::LazySpecification] + # @param out [StringIO, IO, nil] where to log messages # @return [Array] def build_pins gem_yardoc_path, gemspec, out: $stderr yardoc = load!(gem_yardoc_path) From fca10824817356a24245ae8112716b9c2e9ececb Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Mon, 1 Dec 2025 12:27:33 -0500 Subject: [PATCH 54/81] Remove @sg-ignore --- lib/solargraph/doc_map.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/solargraph/doc_map.rb b/lib/solargraph/doc_map.rb index a82d1eebd..3e9e64212 100644 --- a/lib/solargraph/doc_map.rb +++ b/lib/solargraph/doc_map.rb @@ -36,7 +36,6 @@ def requires end alias required requires - # @sg-ignore Translate to something flow sensitive typing understands # @return [Array] def uncached_gemspecs if @uncached_gemspecs.nil? From 95b76c3d87eb09961445be4a16f21e170bff4884 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 30 Dec 2025 23:24:32 -0500 Subject: [PATCH 55/81] Fix merge --- spec/doc_map_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/doc_map_spec.rb b/spec/doc_map_spec.rb index abb7f1c26..4113529f5 100644 --- a/spec/doc_map_spec.rb +++ b/spec/doc_map_spec.rb @@ -75,7 +75,6 @@ def global(doc_map) Solargraph::Environ.new( requires: ['convention_gem1', 'convention_gem2'] ) ->>>>>>> origin/master end end From e935c972a316bde1c7ec71e66500d00228789535 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 30 Dec 2025 23:26:47 -0500 Subject: [PATCH 56/81] Fix RuboCop --- spec/doc_map_spec.rb | 15 --------------- spec/yardoc_spec.rb | 3 --- 2 files changed, 18 deletions(-) diff --git a/spec/doc_map_spec.rb b/spec/doc_map_spec.rb index 4113529f5..6ab97ef97 100644 --- a/spec/doc_map_spec.rb +++ b/spec/doc_map_spec.rb @@ -33,21 +33,6 @@ end end - context 'when deserialization takes a while' do - let(:pre_cache) { false } - let(:requires) { ['backport'] } - - before do - # proxy this method to simulate a long-running deserialization - allow(Benchmark).to receive(:measure) do |&block| - block.call - 5.0 - end - end - - expect(doc_map_with_bundler_require.pins.length - plain_doc_map.pins.length).to be_positive - end - it 'does not warn for redundant requires' do # Requiring 'set' is unnecessary because it's already included in core. It # might make sense to log redundant requires, but a warning is overkill. diff --git a/spec/yardoc_spec.rb b/spec/yardoc_spec.rb index 02444254a..6cd575de0 100644 --- a/spec/yardoc_spec.rb +++ b/spec/yardoc_spec.rb @@ -40,9 +40,6 @@ describe '#build_docs' do let(:workspace) { Solargraph::Workspace.new(Dir.pwd) } let(:gemspec) { workspace.find_gem('rubocop') } - let(:api_map) { Solargraph::ApiMap.new } - let(:doc_map) { api_map.doc_map } - let(:gemspec) { Gem::Specification.find_by_path('rubocop') } let(:output) { '' } before do From f5c63aa01ac15b16dbd3107887e304a0b148dbe9 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Tue, 30 Dec 2025 23:36:14 -0500 Subject: [PATCH 57/81] Fix strong typechecking issues --- lib/solargraph/library.rb | 2 +- lib/solargraph/parser/parser_gem/class_methods.rb | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/solargraph/library.rb b/lib/solargraph/library.rb index 95b4337f7..7de06bacd 100644 --- a/lib/solargraph/library.rb +++ b/lib/solargraph/library.rb @@ -510,7 +510,7 @@ def pin_cache workspace.pin_cache end - # @return [Hash{String => Set}] + # @return [Hash{String => Array}] def source_map_external_require_hash @source_map_external_require_hash ||= {} end diff --git a/lib/solargraph/parser/parser_gem/class_methods.rb b/lib/solargraph/parser/parser_gem/class_methods.rb index a512cdb05..2daf22fc7 100644 --- a/lib/solargraph/parser/parser_gem/class_methods.rb +++ b/lib/solargraph/parser/parser_gem/class_methods.rb @@ -23,9 +23,6 @@ def parse code, filename = nil, line = 0 buffer = ::Parser::Source::Buffer.new(filename, line) buffer.source = code parser.parse(buffer) - # @sg-ignore Unresolved type Parser::SyntaxError, - # Parser::UnknownEncodingInMagicComment for variable e - # https://github.com/castwide/solargraph/pull/1005 rescue ::Parser::SyntaxError, ::Parser::UnknownEncodingInMagicComment => e raise Parser::SyntaxError, e.message end From 2b753e87d0ded080af7fa5c4afa7b22f6ff84e87 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 16:47:28 -0500 Subject: [PATCH 58/81] Bump RBS versions in rspec test --- .github/workflows/rspec.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 73edd47a3..db84786dd 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -21,8 +21,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4', '4.0'] - rbs-version: ['3.6.1', '3.9.5', '4.0.0.dev.4'] + ruby-version: ['3.0', '3.1', '3.2', '3.3', '3.4', '4.0', 'head'] + rbs-version: ['3.6.1', '3.8.1', '3.9.5', '3.10.0', '4.0.0.dev.4'] # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 exclude: # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 @@ -42,16 +42,19 @@ jobs: # fixed in next RBS release - ruby-version: '4.0' rbs-version: '3.6.1' - - ruby-version: '4.0' + - ruby-version: 'head' + rbs-version: '3.6.1' include: - ruby-version: '3.1' rbs-version: '3.6.1' - ruby-version: '3.2' - rbs-version: '3.9.4' + rbs-version: '3.8.1' - ruby-version: '3.3' - rbs-version: '4.0.0.dev.4' + rbs-version: '3.8.5' - ruby-version: '3.4' - rbs-version: '4.0.0.dev.4' + rbs-version: '3.10.0' + - ruby-version: '3.4' + rbs-version: '4.0.0.dev' steps: - uses: actions/checkout@v3 - name: Set up Ruby From e182a53fe173d866e6d7ca4c256a5cdf7d774c55 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 16:48:26 -0500 Subject: [PATCH 59/81] Fix version --- .github/workflows/rspec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index db84786dd..95d721900 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -54,7 +54,7 @@ jobs: - ruby-version: '3.4' rbs-version: '3.10.0' - ruby-version: '3.4' - rbs-version: '4.0.0.dev' + rbs-version: '4.0.0.dev.4' steps: - uses: actions/checkout@v3 - name: Set up Ruby From 34cdf784ad06ae9688c04a65af12310859ebca5a Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 16:50:37 -0500 Subject: [PATCH 60/81] Fix version matrix --- .github/workflows/rspec.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 95d721900..406268714 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -25,9 +25,11 @@ jobs: rbs-version: ['3.6.1', '3.8.1', '3.9.5', '3.10.0', '4.0.0.dev.4'] # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 exclude: - # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 + # Ruby 3.0 doesn't work with RBS >=3.9 - ruby-version: '3.0' rbs-version: '3.9.5' + - ruby-version: '3.0' + rbs-version: '3.8.1' - ruby-version: '3.0' rbs-version: '4.0.0.dev.4' # only include the 3.1 variants we include later @@ -38,12 +40,10 @@ jobs: - ruby-version: '3.3' # only include the 3.4 variants we include later - ruby-version: '3.4' - # Missing require in 'rbs collection update' - hopefully - # fixed in next RBS release - - ruby-version: '4.0' - rbs-version: '3.6.1' - - ruby-version: 'head' - rbs-version: '3.6.1' + # - ruby-version: '4.0' + # rbs-version: '3.6.1' + # - ruby-version: 'head' + # rbs-version: '3.6.1' include: - ruby-version: '3.1' rbs-version: '3.6.1' From 851d142473fd362a04c0c3bca6aad97e3c06224e Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 16:58:47 -0500 Subject: [PATCH 61/81] Fix version matrix --- .github/workflows/rspec.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 406268714..7913bdabf 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -25,13 +25,8 @@ jobs: rbs-version: ['3.6.1', '3.8.1', '3.9.5', '3.10.0', '4.0.0.dev.4'] # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 exclude: - # Ruby 3.0 doesn't work with RBS >=3.9 - - ruby-version: '3.0' - rbs-version: '3.9.5' - - ruby-version: '3.0' - rbs-version: '3.8.1' - - ruby-version: '3.0' - rbs-version: '4.0.0.dev.4' + # only include the 3.0 variants we include later + - ruby-version: '3.1' # only include the 3.1 variants we include later - ruby-version: '3.1' # only include the 3.2 variants we include later @@ -40,11 +35,18 @@ jobs: - ruby-version: '3.3' # only include the 3.4 variants we include later - ruby-version: '3.4' + # only include the 4.0 variants we include later + - ruby-version: '4.0' + # Don't exclude 'head' - let's test all RBS versions we + # can there + # - ruby-version: '4.0' # rbs-version: '3.6.1' # - ruby-version: 'head' # rbs-version: '3.6.1' include: + - ruby-version: '3.0' + rbs-version: '3.6.1' - ruby-version: '3.1' rbs-version: '3.6.1' - ruby-version: '3.2' From e2d27c9dcaec14b90cd8f3e262dc8ca36d3a28c3 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 16:59:50 -0500 Subject: [PATCH 62/81] Fix version matrix --- .github/workflows/rspec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 7913bdabf..94a714508 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -26,7 +26,7 @@ jobs: # Ruby 3.0 doesn't work with RBS 3.9.4 or 4.0.0.dev.4 exclude: # only include the 3.0 variants we include later - - ruby-version: '3.1' + - ruby-version: '3.0' # only include the 3.1 variants we include later - ruby-version: '3.1' # only include the 3.2 variants we include later From 8df808a8bf5cf3b13c3a46d41e4c1ff88286e122 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 17:01:05 -0500 Subject: [PATCH 63/81] Fix version matrix --- .github/workflows/rspec.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 94a714508..dcb726445 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -52,7 +52,7 @@ jobs: - ruby-version: '3.2' rbs-version: '3.8.1' - ruby-version: '3.3' - rbs-version: '3.8.5' + rbs-version: '3.9.5' - ruby-version: '3.4' rbs-version: '3.10.0' - ruby-version: '3.4' From 9974481a534d2e7c386121c01142c933f90c120b Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 17:10:50 -0500 Subject: [PATCH 64/81] Fix version matrix --- .github/workflows/rspec.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index dcb726445..ced8df10d 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -40,10 +40,12 @@ jobs: # Don't exclude 'head' - let's test all RBS versions we # can there - # - ruby-version: '4.0' - # rbs-version: '3.6.1' - # - ruby-version: 'head' - # rbs-version: '3.6.1' + # For some reason 'rbs collection install' is broken in + # 4.0.0.dev.4 on newer Rubies: + # + # https://github.com/castwide/solargraph/actions/runs/20627923548/job/59241444380?pr=1102 + - ruby-version: 'head' + rbs-version: '4.0.0.dev.4' include: - ruby-version: '3.0' rbs-version: '3.6.1' From 56e25350a0bffe071172d3f563bf4935f6290e56 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 17:22:43 -0500 Subject: [PATCH 65/81] Exclude another --- .github/workflows/rspec.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index ced8df10d..65eb8cac8 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -40,10 +40,9 @@ jobs: # Don't exclude 'head' - let's test all RBS versions we # can there - # For some reason 'rbs collection install' is broken in - # 4.0.0.dev.4 on newer Rubies: - # # https://github.com/castwide/solargraph/actions/runs/20627923548/job/59241444380?pr=1102 + - ruby-version: 'head' + rbs-version: '3.8.1' - ruby-version: 'head' rbs-version: '4.0.0.dev.4' include: From d9e49366f2de9f8093c3bd48eecb566ddc751af2 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 17:29:22 -0500 Subject: [PATCH 66/81] Exclude another --- .github/workflows/rspec.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 65eb8cac8..39475cc1d 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -41,6 +41,8 @@ jobs: # can there # https://github.com/castwide/solargraph/actions/runs/20627923548/job/59241444380?pr=1102 + - ruby-version: 'head' + rbs-version: '3.6.1' - ruby-version: 'head' rbs-version: '3.8.1' - ruby-version: 'head' From 751430271fbb5ac9b899923508200605171320b0 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Wed, 31 Dec 2025 17:52:29 -0500 Subject: [PATCH 67/81] Add version, fix doc --- .github/workflows/rspec.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 39475cc1d..f761b61aa 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -38,8 +38,12 @@ jobs: # only include the 4.0 variants we include later - ruby-version: '4.0' # Don't exclude 'head' - let's test all RBS versions we - # can there - + # can there. + # + # + # Just exclude some odd-ball compatibility issues we can't + # work around: + # # https://github.com/castwide/solargraph/actions/runs/20627923548/job/59241444380?pr=1102 - ruby-version: 'head' rbs-version: '3.6.1' @@ -56,6 +60,8 @@ jobs: rbs-version: '3.8.1' - ruby-version: '3.3' rbs-version: '3.9.5' + - ruby-version: '3.3' + rbs-version: '3.10.0' - ruby-version: '3.4' rbs-version: '3.10.0' - ruby-version: '3.4' From 1f0c11d7f40a0e00f66727bcd1d9887f9c5929d5 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Thu, 1 Jan 2026 21:34:25 -0500 Subject: [PATCH 68/81] Fix merge --- spec/doc_map_spec.rb | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/spec/doc_map_spec.rb b/spec/doc_map_spec.rb index 6ab97ef97..376e7d9bd 100644 --- a/spec/doc_map_spec.rb +++ b/spec/doc_map_spec.rb @@ -37,39 +37,23 @@ # Requiring 'set' is unnecessary because it's already included in core. It # might make sense to log redundant requires, but a warning is overkill. allow(Solargraph.logger).to receive(:warn).and_call_original - Solargraph::DocMap.new(['set'], []) + Solargraph::DocMap.new(['set'], [], workspace) expect(Solargraph.logger).not_to have_received(:warn).with(/path set/) end it 'ignores nil requires' do - expect { Solargraph::DocMap.new([nil], []) }.not_to raise_error + expect { Solargraph::DocMap.new([nil], [], workspace) }.not_to raise_error end it 'ignores empty requires' do - expect { Solargraph::DocMap.new([''], []) }.not_to raise_error + expect { Solargraph::DocMap.new([''], [], workspace) }.not_to raise_error end it 'collects dependencies' do - doc_map = Solargraph::DocMap.new(['rspec'], []) + doc_map = Solargraph::DocMap.new(['rspec'], [], workspace) expect(doc_map.dependencies.map(&:name)).to include('rspec-core') end - it 'includes convention requires from environ' do - dummy_convention = Class.new(Solargraph::Convention::Base) do - def global(doc_map) - Solargraph::Environ.new( - requires: ['convention_gem1', 'convention_gem2'] - ) - end - end - - it 'logs timing' do - # force lazy evaluation - _pins = doc_map.pins - expect(out.string).to include('Deserialized ').and include(' gem pins ').and include(' ms') - end - end - context 'with an uncached but valid gemspec' do let(:requires) { ['uncached_gem'] } let(:pre_cache) { false } From 25b114852089ce87515ef34a294790a284d5ef39 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Thu, 1 Jan 2026 21:42:06 -0500 Subject: [PATCH 69/81] Don't use solargraph-rspec branch --- .github/workflows/plugins.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index c7ad72cb4..3f34cbae1 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -116,12 +116,9 @@ jobs: - name: clone https://github.com/lekemula/solargraph-rspec/ run: | cd .. - # git clone https://github.com/lekemula/solargraph-rspec.git + git clone https://github.com/lekemula/solargraph-rspec.git - # pending https://github.com/lekemula/solargraph-rspec/pull/30 - git clone https://github.com/apiology/solargraph-rspec.git cd solargraph-rspec - git checkout reset_closures - name: Set up Ruby uses: ruby/setup-ruby@v1 with: From f44141cc5788e5fcd802fef526214704792d0f69 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Thu, 1 Jan 2026 21:58:08 -0500 Subject: [PATCH 70/81] Fix merge --- spec/gem_pins_spec.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spec/gem_pins_spec.rb b/spec/gem_pins_spec.rb index cafed4cf6..4d2bb4ff5 100644 --- a/spec/gem_pins_spec.rb +++ b/spec/gem_pins_spec.rb @@ -46,9 +46,4 @@ expect(pin.location.filename).to end_with('task.rb') end end - - it 'does not error out when handed incorrect gemspec' do - gemspec = instance_double(Gem::Specification, name: 'foo', version: '1.0', gem_dir: '/not-there') - expect { Solargraph::GemPins.build_yard_pins([], gemspec) }.not_to raise_error - end end From 979850540f21ca22abdd078d83dacf0b987271dd Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Thu, 1 Jan 2026 23:35:16 -0500 Subject: [PATCH 71/81] Debug --- .github/workflows/rspec.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index f761b61aa..ae507e2a5 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -51,6 +51,7 @@ jobs: rbs-version: '3.8.1' - ruby-version: 'head' rbs-version: '4.0.0.dev.4' + - ruby-version: 'head' # TEMP include: - ruby-version: '3.0' rbs-version: '3.6.1' @@ -89,8 +90,6 @@ jobs: run: | bundle _2.5.23_ install bundle update rbs # use latest available for this Ruby version - bundle list - bundle exec solargraph pin 'Bundler::Dsl#source' - name: Update types run: | bundle exec rbs collection update From 5edcd2d3226ef84f718d8f68990fd488a44fe366 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 2 Jan 2026 11:44:49 -0500 Subject: [PATCH 72/81] Add another use of stdlib dependencies in RBS --- .github/workflows/rspec.yml | 1 - lib/solargraph/doc_map.rb | 14 +- rbs/fills/rubygems/0/dependency.rbs | 193 ++++++++++++++++++++++++++++ 3 files changed, 204 insertions(+), 4 deletions(-) create mode 100644 rbs/fills/rubygems/0/dependency.rbs diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index ae507e2a5..72b4a08cc 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -51,7 +51,6 @@ jobs: rbs-version: '3.8.1' - ruby-version: 'head' rbs-version: '4.0.0.dev.4' - - ruby-version: 'head' # TEMP include: - ruby-version: '3.0' rbs-version: '3.6.1' diff --git a/lib/solargraph/doc_map.rb b/lib/solargraph/doc_map.rb index 7dd7b9a3c..891bbabb3 100644 --- a/lib/solargraph/doc_map.rb +++ b/lib/solargraph/doc_map.rb @@ -240,11 +240,9 @@ def fetch_dependencies gemspec, out: nil Solargraph.logger.info "Adding #{spec.name} dependency for #{gemspec.name}" dep = Gem.loaded_specs[spec.name] # @todo is next line necessary? - # @sg-ignore Unresolved call to requirement on Gem::Dependency dep ||= Gem::Specification.find_by_name(spec.name, spec.requirement) deps.merge fetch_dependencies(dep) if deps.add?(dep) rescue Gem::MissingSpecError - # @sg-ignore Unresolved call to requirement on Gem::Dependency Solargraph.logger.warn "Gem dependency #{spec.name} #{spec.requirement} for #{gemspec.name} not found in RubyGems." end.to_a end @@ -252,7 +250,17 @@ def fetch_dependencies gemspec, out: nil # @param gemspec [Gem::Specification] # @return [Array] def only_runtime_dependencies gemspec - gemspec.dependencies - gemspec.development_dependencies + gemspec_deps = gemspec.dependencies - gemspec.development_dependencies + stdlib_dep_names = workspace.stdlib_dependencies(gemspec.name) + stdlib_deps = workspace.stdlib_dependencies(gemspec.name).flat_map do |dep_name| + # already know about this dependency + next [] if gemspec_deps.any? { |dep| dep.name == dep_name } + + stdlib_specs = resolve_path_to_gemspecs(dep_name) || [] + + stdlib_specs.map { |spec| Gem::Dependency.new spec.name, "= #{spec.version}" } + end + gemspec_deps + stdlib_deps end diff --git a/rbs/fills/rubygems/0/dependency.rbs b/rbs/fills/rubygems/0/dependency.rbs new file mode 100644 index 000000000..db572b80d --- /dev/null +++ b/rbs/fills/rubygems/0/dependency.rbs @@ -0,0 +1,193 @@ +# +# The Dependency class holds a Gem name and a Gem::Requirement. +# +class Gem::Dependency + @name: untyped + + @requirement: untyped + + @type: untyped + + @prerelease: untyped + + @version_requirements: untyped + + @version_requirement: untyped + + # + # Valid dependency types. + # + TYPES: ::Array[:development | :runtime] + + # + # Dependency name or regular expression. + # + attr_accessor name: untyped + + # + # Allows you to force this dependency to be a prerelease. + # + attr_writer prerelease: untyped + + # + # Constructs a dependency with `name` and `requirements`. The last argument can + # optionally be the dependency type, which defaults to `:runtime`. + # + def initialize: (untyped name, *untyped requirements) -> void + + def hash: () -> untyped + + def inspect: () -> untyped + + # + # Does this dependency require a prerelease? + # + def prerelease?: () -> untyped + + # + # Is this dependency simply asking for the latest version of a gem? + # + def latest_version?: () -> untyped + + def pretty_print: (untyped q) -> untyped + + # + # What does this dependency require? + # + def requirement: () -> untyped + + # + # + def requirements_list: () -> untyped + + def to_s: () -> ::String + + # + # Dependency type. + # + def type: () -> untyped + + # + # + def runtime?: () -> untyped + + def ==: (untyped other) -> untyped + + # + # Dependencies are ordered by name. + # + def <=>: (untyped other) -> untyped + + # + # Uses this dependency as a pattern to compare to `other`. This dependency will + # match if the name matches the other's name, and other has only an equal + # version requirement that satisfies this dependency. + # + def =~: (untyped other) -> (nil | false | untyped) + + # + # + alias === =~ + + # + # Does this dependency match the specification described by `name` and `version` + # or match `spec`? + # + # NOTE: Unlike #matches_spec? this method does not return true when the version + # is a prerelease version unless this is a prerelease dependency. + # + def match?: (untyped obj, ?untyped? version, ?bool allow_prerelease) -> (false | true | untyped) + + # + # Does this dependency match `spec`? + # + # NOTE: This is not a convenience method. Unlike #match? this method returns + # true when `spec` is a prerelease version even if this dependency is not a + # prerelease dependency. + # + def matches_spec?: (untyped spec) -> (false | true | untyped) + + # + # Merges the requirements of `other` into this dependency + # + def merge: (untyped other) -> untyped + + # + # + def matching_specs: (?bool platform_only) -> untyped + + # + # True if the dependency will not always match the latest version. + # + def specific?: () -> untyped + + # + # + def to_specs: () -> untyped + + # + # + def to_spec: () -> untyped + + # + # + def identity: () -> (:complete | :abs_latest | :latest | :released) + + def encode_with: (untyped coder) -> untyped +end From 8320f5b5cfc28d6d60e472e90db56edf0ee4ff02 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 2 Jan 2026 11:54:39 -0500 Subject: [PATCH 73/81] Mock additional call --- spec/doc_map_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/doc_map_spec.rb b/spec/doc_map_spec.rb index 376e7d9bd..1e50301f4 100644 --- a/spec/doc_map_spec.rb +++ b/spec/doc_map_spec.rb @@ -64,7 +64,7 @@ uncached_gemspec = Gem::Specification.new('uncached_gem', '1.0.0') allow(workspace).to receive_messages(fresh_pincache: pincache) allow(Gem::Specification).to receive(:find_by_path).with('uncached_gem').and_return(uncached_gemspec) - allow(workspace).to receive(:global_environ).and_return(Solargraph::Environ.new) + allow(workspace).to receive_messages(stdlib_dependencies: [], global_environ: Solargraph::Environ.new) allow(pincache).to receive(:deserialize_combined_pin_cache).with(uncached_gemspec).and_return(nil) expect(doc_map.uncached_gemspecs).to eq([uncached_gemspec]) end From 6730e8f50792809893f29cbd5c321764db7c9a3a Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 2 Jan 2026 12:12:44 -0500 Subject: [PATCH 74/81] Fix annotations --- .../language_server/message/extended/check_gem_version.rb | 1 - lib/solargraph/parser/parser_gem/class_methods.rb | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/solargraph/language_server/message/extended/check_gem_version.rb b/lib/solargraph/language_server/message/extended/check_gem_version.rb index ead1eeaf2..0447a7feb 100644 --- a/lib/solargraph/language_server/message/extended/check_gem_version.rb +++ b/lib/solargraph/language_server/message/extended/check_gem_version.rb @@ -83,7 +83,6 @@ def available @fetched = true begin @available ||= begin - # @sg-ignore Variable type could not be inferred for tuple # @type [Gem::Dependency, nil] tuple = CheckGemVersion.fetcher.search_for_dependency(Gem::Dependency.new('solargraph')).flatten.first if tuple.nil? diff --git a/lib/solargraph/parser/parser_gem/class_methods.rb b/lib/solargraph/parser/parser_gem/class_methods.rb index 2daf22fc7..b3caa900a 100644 --- a/lib/solargraph/parser/parser_gem/class_methods.rb +++ b/lib/solargraph/parser/parser_gem/class_methods.rb @@ -30,7 +30,9 @@ def parse code, filename = nil, line = 0 # @return [::Parser::Base] def parser @parser ||= Prism::Translation::Parser.new(FlawedBuilder.new).tap do |parser| + # @sg-ignore Unresolved call to diagnostics on Prism::Translation::Parser parser.diagnostics.all_errors_are_fatal = true + # @sg-ignore Unresolved call to diagnostics on Prism::Translation::Parser parser.diagnostics.ignore_warnings = true end end From 9a88f53a33107d63da42145db4ef227ad5a9c3de Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 2 Jan 2026 12:16:49 -0500 Subject: [PATCH 75/81] Update types in rspec undercover --- .github/workflows/rspec.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rspec.yml b/.github/workflows/rspec.yml index 72b4a08cc..d9473bd3e 100644 --- a/.github/workflows/rspec.yml +++ b/.github/workflows/rspec.yml @@ -90,8 +90,7 @@ jobs: bundle _2.5.23_ install bundle update rbs # use latest available for this Ruby version - name: Update types - run: | - bundle exec rbs collection update + run: bundle exec rbs collection update - name: Run tests run: bundle exec rake spec undercover: @@ -106,9 +105,15 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: '3.4' + # see https://github.com/castwide/solargraph/actions/runs/19391419903/job/55485410493?pr=1119 + # + # match version in Gemfile.lock and use same version below + bundler: 2.5.23 bundler-cache: false - name: Install gems run: bundle install + - name: Update types + run: bundle exec rbs collection update - name: Run tests run: bundle exec rake spec - name: Check PR coverage From 00c2947c9b137026dfb3c97e4b86866d1fc45106 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 2 Jan 2026 14:25:55 -0500 Subject: [PATCH 76/81] Debug --- .github/workflows/plugins.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 3602da38d..5555617c5 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -122,7 +122,7 @@ jobs: - name: Set up Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.4 + ruby-version: '3.1' bundler-cache: false - name: Install gems run: | From 5df17d5645e689a044458428f70ba9389c287a85 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 2 Jan 2026 14:31:23 -0500 Subject: [PATCH 77/81] Debug --- .github/workflows/plugins.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 5555617c5..3f34cbae1 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -123,6 +123,7 @@ jobs: uses: ruby/setup-ruby@v1 with: ruby-version: '3.1' + rubygems: latest bundler-cache: false - name: Install gems run: | From c22e3105184644b6066afe536502e0c6adca3509 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Fri, 2 Jan 2026 16:43:17 -0500 Subject: [PATCH 78/81] Drop incorrect rbs collection use in spec --- .github/workflows/plugins.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/plugins.yml b/.github/workflows/plugins.yml index 3f34cbae1..edaebe3eb 100644 --- a/.github/workflows/plugins.yml +++ b/.github/workflows/plugins.yml @@ -150,10 +150,12 @@ jobs: run: | cd ../solargraph-rspec cp .solargraph.yml.example .solargraph.yml - - name: Solargraph generate RSpec gems YARD and RBS pins + - name: Solargraph generate RSpec gems YARD pins run: | cd ../solargraph-rspec - bundle exec appraisal rbs collection update + # solargraph-rspec's specs don't pass a workspace, so it + # doesn't know where to look for the RBS collection - let's + # not load one so that the solargraph gems command below works rspec_gems=$(bundle exec appraisal ruby -r './lib/solargraph-rspec' -e 'puts Solargraph::Rspec::Gems.gem_names.join(" ")' 2>/dev/null | tail -n1) bundle exec appraisal solargraph gems $rspec_gems - name: Run specs From c4a91f4149256225999d6de9fce7334e4a6523c4 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 10 Jan 2026 13:12:16 -0500 Subject: [PATCH 79/81] Fix issues resolving cgi escape functions --- lib/solargraph/rbs_map.rb | 24 +++++++++++++++--------- lib/solargraph/rbs_map/stdlib_map.rb | 7 +++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/lib/solargraph/rbs_map.rb b/lib/solargraph/rbs_map.rb index a5b998ff0..170100e9f 100644 --- a/lib/solargraph/rbs_map.rb +++ b/lib/solargraph/rbs_map.rb @@ -109,19 +109,19 @@ def cache_key # @param rbs_collection_config_path [String, Pathname, nil] # @return [RbsMap] def self.from_gemspec gemspec, rbs_collection_path, rbs_collection_config_path - rbs_map = RbsMap.new(gemspec.name, gemspec.version, - rbs_collection_paths: [rbs_collection_path].compact, - rbs_collection_config_path: rbs_collection_config_path) + # prefers stdlib RBS if available + rbs_map = RbsMap::StdlibMap.new(gemspec.name) return rbs_map if rbs_map.resolved? - # try any version of the gem in the collection - rbs_map = RbsMap.new(gemspec.name, nil, + rbs_map = RbsMap.new(gemspec.name, gemspec.version, rbs_collection_paths: [rbs_collection_path].compact, rbs_collection_config_path: rbs_collection_config_path) - return rbs_map if rbs_map.resolved? - StdlibMap.new(gemspec.name) + # try any version of the gem in the collection + RbsMap.new(gemspec.name, nil, + rbs_collection_paths: [rbs_collection_path].compact, + rbs_collection_config_path: rbs_collection_config_path) end # @param out [IO, nil] where to log messages @@ -187,6 +187,13 @@ def conversions # @return [void] def log_caching lib, out:; end + def resolve_dependencies? + # we need to resolve dependencies via gemfile.lock manually for + # YARD regardless, so use same mechanism here so we don't + # duplicate work generating pins from dependencies + false + end + # @param loader [RBS::EnvironmentLoader] # @param library [String] # @param version [String, nil] the version of the library to load, or nil for any @@ -194,8 +201,7 @@ def log_caching lib, out:; end # @return [Boolean] true if adding the library succeeded def add_library loader, library, version, out: $stderr @resolved = if loader.has_library?(library: library, version: version) - # we find our own dependencies from gemfile.lock - loader.add library: library, version: version, resolve_dependencies: false + loader.add library: library, version: version, resolve_dependencies: resolve_dependencies? logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" } true else diff --git a/lib/solargraph/rbs_map/stdlib_map.rb b/lib/solargraph/rbs_map/stdlib_map.rb index e7891bfe3..6c008954e 100644 --- a/lib/solargraph/rbs_map/stdlib_map.rb +++ b/lib/solargraph/rbs_map/stdlib_map.rb @@ -54,6 +54,13 @@ def self.stdlib_dependencies name, version = nil end end + def resolve_dependencies? + # there are 'virtual' dependencies for stdlib gems in RBS that + # aren't represented in the actual gemspecs that we'd + # otherwise use + true + end + # @param library [String] # @return [StdlibMap] def self.load library From 02151a52d49659aa3fe919b35cc143bf9ddc1d76 Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 10 Jan 2026 13:33:30 -0500 Subject: [PATCH 80/81] Be more careful marking things as stdlib --- lib/solargraph/rbs_map.rb | 8 ++++---- lib/solargraph/rbs_map/stdlib_map.rb | 2 +- spec/pin_cache_spec.rb | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/solargraph/rbs_map.rb b/lib/solargraph/rbs_map.rb index 170100e9f..a42f984ad 100644 --- a/lib/solargraph/rbs_map.rb +++ b/lib/solargraph/rbs_map.rb @@ -204,10 +204,10 @@ def add_library loader, library, version, out: $stderr loader.add library: library, version: version, resolve_dependencies: resolve_dependencies? logger.debug { "#{short_name} successfully loaded library #{library}:#{version}" } true - else - logger.info { "#{short_name} did not find data for library #{library}:#{version}" } - false - end + else + logger.info { "#{short_name} did not find data for library #{library}:#{version}" } + false + end end # @return [String] diff --git a/lib/solargraph/rbs_map/stdlib_map.rb b/lib/solargraph/rbs_map/stdlib_map.rb index 6c008954e..c2cfcabb6 100644 --- a/lib/solargraph/rbs_map/stdlib_map.rb +++ b/lib/solargraph/rbs_map/stdlib_map.rb @@ -25,7 +25,7 @@ def initialize library, out: $stderr @resolved = true @loaded = true logger.debug { "Deserialized #{cached_pins.length} cached pins for stdlib require #{library.inspect}" } - else + elsif self.class.source.has? library, nil super unless resolved? @pins = [] diff --git a/spec/pin_cache_spec.rb b/spec/pin_cache_spec.rb index 0a11686f5..0f766117a 100644 --- a/spec/pin_cache_spec.rb +++ b/spec/pin_cache_spec.rb @@ -136,8 +136,8 @@ end end - context 'with gem packaged with its own RBS gem' do - let(:gem_name) { 'base64' } + context 'with gem packaged with its own RBS' do + let(:gem_name) { 'rubocop-yard' } before do Solargraph::Shell.new.uncache(gem_name) @@ -150,7 +150,7 @@ pin_cache.cache_gem(gemspec: yaml_gemspec, out: nil) # match arguments with regexp using rspec-matchers syntax - expect(File).to have_received(:write).with(%r{combined/.*/base64-.*-export.ser$}, any_args, mode: 'wb').once + expect(File).to have_received(:write).with(%r{combined/.*/rubocop-yard-.*-export.ser$}, any_args, mode: 'wb').once end end end From 14a84689739ec6b0547d4a5586411d71fa4f434b Mon Sep 17 00:00:00 2001 From: Vince Broz Date: Sat, 10 Jan 2026 13:45:13 -0500 Subject: [PATCH 81/81] Reclassify rbs gem --- spec/rbs_map/stdlib_map_spec.rb | 24 ------------------------ spec/rbs_map_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/spec/rbs_map/stdlib_map_spec.rb b/spec/rbs_map/stdlib_map_spec.rb index 03f0b547f..c9db9bb48 100644 --- a/spec/rbs_map/stdlib_map_spec.rb +++ b/spec/rbs_map/stdlib_map_spec.rb @@ -11,30 +11,6 @@ expect(pin).to be_a(Solargraph::Pin::Base) end - it 'processes RBS class variables' do - map = Solargraph::RbsMap::StdlibMap.load('rbs') - store = Solargraph::ApiMap::Store.new(map.pins) - class_variable_pins = store.pins_by_class(Solargraph::Pin::ClassVariable) - count_pins = class_variable_pins.select do |pin| - pin.name.to_s == '@@count' && pin.context.to_s == 'Class' - end - expect(count_pins.length).to eq(1) - count_pin = count_pins.first - expect(count_pin.return_type.to_s).to eq('Integer') - end - - it 'processes RBS class instance variables' do - map = Solargraph::RbsMap::StdlibMap.load('rbs') - store = Solargraph::ApiMap::Store.new(map.pins) - instance_variable_pins = store.pins_by_class(Solargraph::Pin::InstanceVariable) - root_pins = instance_variable_pins.select do |pin| - pin.name.to_s == '@root' && pin.context.to_s == 'Class' && pin.scope == :class - end - expect(root_pins.length).to eq(1) - root_pin = root_pins.first - expect(root_pin.return_type.to_s).to eq('RBS::Namespace, nil') - end - it 'processes RBS module aliases' do map = Solargraph::RbsMap::StdlibMap.load('yaml') store = Solargraph::ApiMap::Store.new(map.pins) diff --git a/spec/rbs_map_spec.rb b/spec/rbs_map_spec.rb index f3ca90a36..4631c9ca5 100644 --- a/spec/rbs_map_spec.rb +++ b/spec/rbs_map_spec.rb @@ -25,4 +25,30 @@ pin = rbs_map.path_pin('RBS::EnvironmentWalker::InstanceNode') expect(pin.return_type.tag).to eq('Class') end + + it 'processes RBS class variables' do + spec = Gem::Specification.find_by_name('rbs') + rbs_map = Solargraph::RbsMap.from_gemspec(spec, nil, nil) + store = Solargraph::ApiMap::Store.new(rbs_map.pins) + class_variable_pins = store.pins_by_class(Solargraph::Pin::ClassVariable) + count_pins = class_variable_pins.select do |pin| + pin.name.to_s == '@@count' && pin.context.to_s == 'Class' + end + expect(count_pins.length).to eq(1) + count_pin = count_pins.first + expect(count_pin.return_type.to_s).to eq('Integer') + end + + it 'processes RBS class instance variables' do + spec = Gem::Specification.find_by_name('rbs') + rbs_map = Solargraph::RbsMap.from_gemspec(spec, nil, nil) + store = Solargraph::ApiMap::Store.new(rbs_map.pins) + instance_variable_pins = store.pins_by_class(Solargraph::Pin::InstanceVariable) + root_pins = instance_variable_pins.select do |pin| + pin.name.to_s == '@root' && pin.context.to_s == 'Class' && pin.scope == :class + end + expect(root_pins.length).to eq(1) + root_pin = root_pins.first + expect(root_pin.return_type.to_s).to eq('RBS::Namespace, nil') + end end