Shopify / ruby-lsp

An opinionated language server for Ruby
https://shopify.github.io/ruby-lsp/
MIT License
1.52k stars 144 forks source link

uninitialized constant RubyLsp::Requests::SemanticHighlighting::Bundler #559

Closed icnagy closed 1 year ago

icnagy commented 1 year ago

Hey,

Really great project! After seeing the conference talk I wanted to try it in SublimeText. Interesting that not all features are documented/enabled by default but it's not hard to figure out how to enable them. Here's the SublimeLSP setting I ended up with:

# ...
    "ruby-lsp": {
      "enabled": true,
      "command": [
        "ruby-lsp"
      ],
      "initializationOptions": {
        "enabledFeatures": [
          "completion",
          "hover",
          "documentHighlights",
          "documentSymbols",
          "codeActions",
          "documentLink",
          "formatting",
          "onTypeFormatting",
          "foldingRanges",
          "selectionRanges",
          "semanticHighlighting",
          "inlayHint",
          "diagnostics"
        ],
        "telemetryEnabled": true
      },
      "selector": "source.ruby | text.html.ruby"
    },
# ...

When semanticHighlighting is enabled ruby-lsp throws a #<NameError: uninitialized constant RubyLsp::Requests::SemanticHighlighting::Bundler> on initialize: (sorry for the wall of text, formatted for readability)

:: [11:00:03.967] <?  ruby-lsp telemetry/event: {
"lspVersion": "0.4.1", 
"errorMessage": "uninitialized constant RubyLsp::Requests::SemanticHighlighting::Bundler", 
"backtrace": "/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/requests/semantic_highlighting.rb:75:in `<class:SemanticHighlighting>
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/requests/semantic_highlighting.rb:21:in `<module:Requests>`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/requests/semantic_highlighting.rb:5:in `<module:RubyLsp>`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/requests/semantic_highlighting.rb:4:in `<top (required)>`
<internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:88:in `require`
<internal:/usr/local/lib/ruby/site_ruby/3.2.0/rubygems/core_ext/kernel_require.rb>:88:in `require`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/executor.rb:330:in `initialize_request`
/usr/local/lib/ruby/gems/3.2.0/gems/sorbet-runtime-0.5.10707/lib/types/private/methods/_methods.rb:277:in `bind_call`
/usr/local/lib/ruby/gems/3.2.0/gems/sorbet-runtime-0.5.10707/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/executor.rb:39:in `run`
/usr/local/lib/ruby/gems/3.2.0/gems/sorbet-runtime-0.5.10707/lib/types/private/methods/_methods.rb:277:in `bind_call`
/usr/local/lib/ruby/gems/3.2.0/gems/sorbet-runtime-0.5.10707/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/executor.rb:23:in `block in execute`
/usr/local/Cellar/ruby/3.2.1/lib/ruby/3.2.0/benchmark.rb:311:in `realtime`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/executor.rb:22:in `execute`
/usr/local/lib/ruby/gems/3.2.0/gems/sorbet-runtime-0.5.10707/lib/types/private/methods/_methods.rb:277:in `bind_call`
/usr/local/lib/ruby/gems/3.2.0/gems/sorbet-runtime-0.5.10707/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/server.rb:37:in `block in start`
/usr/local/lib/ruby/gems/3.2.0/gems/language_server-protocol-3.17.0.3/lib/language_server/protocol/transport/io/reader.rb:20:in `read`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/lib/ruby_lsp/server.rb:34:in `start`
/usr/local/lib/ruby/gems/3.2.0/gems/sorbet-runtime-0.5.10707/lib/types/private/methods/_methods.rb:277:in `bind_call`
/usr/local/lib/ruby/gems/3.2.0/gems/sorbet-runtime-0.5.10707/lib/types/private/methods/_methods.rb:277:in `block in _on_method_added`
/usr/local/lib/ruby/gems/3.2.0/gems/ruby-lsp-0.4.1/exe/ruby-lsp:22:in `<top (required)>`
/usr/local/opt/ruby/bin/ruby-lsp:25:in `load`
/usr/local/opt/ruby/bin/ruby-lsp:25:in `<main>`", 
  "errorClass": "NameError",
  "requestTime": 0.006876999999803957,
  "request": "initialize",
  "params": {
    "capabilities": {
      "general": {
        "markdown": {
          "parser": "Python-Markdown",
          "version": "3.2.2"
        },
        "regularExpressions": {
          "engine": "ECMAScript"
        }
      },
      "workspace": {
        "workspaceEdit": {
          "failureHandling": "abort",
          "documentChanges": true
        },
        "codeLens": {
          "refreshSupport": true
        },
        "workspaceFolders": true,
        "didChangeConfiguration": {
          "dynamicRegistration": true
        },
        "inlayHint": {
          "refreshSupport": true
        },
        "symbol": {
          "tagSupport": {
            "valueSet": [
              1
            ]
          },
          "dynamicRegistration": true,
          "symbolKind": {
            "valueSet": [
              23,
              12,
              8,
              21,
              6,
              10,
              4,
              11,
              14,
              17,
              20,
              1,
              16,
              26,
              19,
              18,
              24,
              22,
              7,
              13,
              5,
              2,
              9,
              3,
              15,
              25
            ]
          }
        },
        "applyEdit": true,
        "semanticTokens": {
          "refreshSupport": true
        },
        "configuration": true,
        "executeCommand": {}
      },
      "textDocument": {
        "declaration": {
          "linkSupport": true,
          "dynamicRegistration": true
        },
        "callHierarchy": {
          "dynamicRegistration": true
        },
        "colorProvider": {
          "dynamicRegistration": true
        },
        "rangeFormatting": {
          "dynamicRegistration": true
        },
        "selectionRange": {
          "dynamicRegistration": true
        },
        "signatureHelp": {
          "signatureInformation": {
            "parameterInformation": {
              "labelOffsetSupport": true
            },
            "activeParameterSupport": true,
            "documentationFormat": [
              "markdown",
              "plaintext"
            ]
          },
          "dynamicRegistration": true,
          "contextSupport": true
        },
        "documentHighlight": {
          "dynamicRegistration": true
        },
        "inlayHint": {
          "resolveSupport": {
            "properties": [
              "textEdits",
              "label.command"
            ]
          },
          "dynamicRegistration": true
        },
        "rename": {
          "prepareSupport": true,
          "dynamicRegistration": true,
          "prepareSupportDefaultBehavior": 1
        },
        "codeLens": {
          "dynamicRegistration": true
        },
        "formatting": {
          "dynamicRegistration": true
        },
        "definition": {
          "linkSupport": true,
          "dynamicRegistration": true
        },
        "codeAction": {
          "codeActionLiteralSupport": {
            "codeActionKind": {
              "valueSet": [
                "quickfix",
                "refactor",
                "refactor.extract",
                "refactor.inline",
                "refactor.rewrite",
                "source.fixAll",
                "source.organizeImports"
              ]
            }
          },
          "dataSupport": true,
          "resolveSupport": {
            "properties": [
              "edit"
            ]
          },
          "dynamicRegistration": true,
          "isPreferredSupport": true
        },
        "publishDiagnostics": {
          "tagSupport": {
            "valueSet": [
              1,
              2
            ]
          },
          "versionSupport": true,
          "relatedInformation": true,
          "codeDescriptionSupport": true,
          "dataSupport": true
        },
        "references": {
          "dynamicRegistration": true
        },
        "typeHierarchy": {
          "dynamicRegistration": true
        },
        "documentLink": {
          "tooltipSupport": true,
          "dynamicRegistration": true
        },
        "typeDefinition": {
          "linkSupport": true,
          "dynamicRegistration": true
        },
        "documentSymbol": {
          "tagSupport": {
            "valueSet": [
              1
            ]
          },
          "hierarchicalDocumentSymbolSupport": true,
          "dynamicRegistration": true,
          "symbolKind": {
            "valueSet": [
              23,
              12,
              8,
              21,
              6,
              10,
              4,
              11,
              14,
              17,
              20,
              1,
              16,
              26,
              19,
              18,
              24,
              22,
              7,
              13,
              5,
              2,
              9,
              3,
              15,
              25
            ]
          }
        },
        "completion": {
          "completionItemKind": {
            "valueSet": [
              19,
              22,
              3,
              14,
              4,
              2,
              13,
              11,
              8,
              21,
              12,
              17,
              25,
              5,
              23,
              15,
              20,
              10,
              18,
              7,
              16,
              9,
              1,
              6,
              24
            ]
          },
          "completionItem": {
            "insertTextModeSupport": {
              "valueSet": [
                2
              ]
            },
            "snippetSupport": true,
            "documentationFormat": [
              "markdown",
              "plaintext"
            ],
            "tagSupport": {
              "valueSet": [
                1
              ]
            },
            "deprecatedSupport": true,
            "resolveSupport": {
              "properties": [
                "detail",
                "documentation",
                "additionalTextEdits"
              ]
            },
            "insertReplaceSupport": true,
            "labelDetailsSupport": true
          },
          "dynamicRegistration": true,
          "insertTextMode": 2,
          "completionList": {
            "itemDefaults": [
              "editRange",
              "insertTextFormat",
              "data"
            ]
          }
        },
        "hover": {
          "contentFormat": [
            "markdown",
            "plaintext"
          ],
          "dynamicRegistration": true
        },
        "semanticTokens": {
          "augmentsSyntaxTokens": true,
          "overlappingTokenSupport": false,
          "multilineTokenSupport": true,
          "formats": [
            "relative"
          ],
          "requests": {
            "range": true,
            "full": {
              "delta": true
            }
          },
          "tokenTypes": [
            "struct",
            "function",
            "modifier",
            "keyword",
            "variable",
            "property",
            "method",
            "enum",
            "regexp",
            "interface",
            "parameter",
            "macro",
            "number",
            "typeParameter",
            "event",
            "enumMember",
            "comment",
            "class",
            "type",
            "decorator",
            "namespace",
            "string",
            "operator"
          ],
          "tokenModifiers": [
            "modification",
            "declaration",
            "defaultLibrary",
            "abstract",
            "async",
            "readonly",
            "documentation",
            "definition",
            "deprecated",
            "static"
          ],
          "dynamicRegistration": true
        },
        "synchronization": {
          "didSave": true,
          "willSave": true,
          "willSaveWaitUntil": true,
          "dynamicRegistration": true
        },
        "implementation": {
          "linkSupport": true,
          "dynamicRegistration": true
        }
      },
      "window": {
        "showMessage": {
          "messageActionItem": {
            "additionalPropertiesSupport": true
          }
        },
        "showDocument": {
          "support": true
        },
        "workDoneProgress": true
      }
    },
    "processId": 5263,
    "rootPath": "/Users/csaba/work/ruby-lsp-sublime-test",
    "clientInfo": {
      "version": "1.23.0",
      "name": "Sublime Text LSP"
    },
    "initializationOptions": {
      "enabledFeatures": [
        "completion",
        "hover",
        "documentHighlights",
        "documentSymbols",
        "codeActions",
        "documentLink",
        "formatting",
        "onTypeFormatting",
        "foldingRanges",
        "selectionRanges",
        "semanticHighlighting",
        "inlayHint",
        "diagnostics"
      ],
      "telemetryEnabled": true
    },
    "rootUri": "file:///Users/csaba/work/ruby-lsp-sublime-test",
    "workspaceFolders": [
      {
        "uri": "file:///Users/csaba/work/ruby-lsp-sublime-test",
        "name": "ruby-lsp-sublime-test"
      }
    ]
  }
}
ruby-lsp: Shutting down Ruby LSP...

The fix is quite simple, just adding a require "bundler" on top of lib/ruby-lsp/requests/semantic_highlighting.rb fixes it. Happy to create a PR, I'm just not sure if that is the best solution?

vinistock commented 1 year ago

Hey! Thank you for the kind words.

Indeed, when you run the Ruby LSP without bundle exec, then you do need to require bundler. Instead of doing it in semantic highlighting, I would say we better do it in internal.rb where we require most of the libraries, std gems and stuff. Please let me know if you want to contribute that.

Interesting that not all features are documented/enabled by default

I'm curious about this and how we can improve. Which features did you find not to be documented? Did you check our supported features?

icnagy commented 1 year ago

Thanks @vinistock for the quick reply.

Yes, it does make more sense to require bundle in internal.rb. Will create a PR shortly, though I'm not familiar enough with the code base to see where and how would one test this?

Sorry for the confusion, I probably should've written that it's interesting that the features are opt-in rather than opt-out. It was really easy to figure out what features are available and how to enable them. Unless I'm mistaken without initializationOptions/enabledFeatures only the diagnostic feature is enabled, which seems a bit conservative. But again, I'm using SublimeText with SublimeLSP which doesn't seem to be compatible with all the features (eg: DocumentLink isn't working).

vinistock commented 1 year ago

I see. Yeah, the decision we made initially to enable features using an array rather than a hash was not a very happy one. We enable features based on their presence in the array.

This works well for VS Code, where we control the default values of each setting, but is not great for any other editor. We'll need to revisit this to allow the server to have better control over what's enabled and make it easier for other editors to configure.

Nakilon commented 4 months ago

it's not hard to figure out how to enable them

I can't figure out how to disable.

{
  "clients": {
    "ruby-lsp": {
      "enabled": true,
      "command": [
        "ruby-lsp"
      ],
      "selector": "source.ruby",
      "initializationOptions": {
        "enabledFeatures": {
          "diagnostics": false,

          "codeActions": false
        },
        "formatter": "none"
      }
    }
  },
  "inhibit_snippet_completions": true
}

but Rubocop is still here.

andyw8 commented 4 months ago

@Nakilon Please create a new issue rather than reporting the same thing in multiple places.