castwide/solargraph

Autocompletion broken : Infinite loop when checking if a class is a superclass

QuentinLemCode opened this issue · 3 comments

Hello
Currently working on a rails project with engines
There is this actual folder structure

app
--controllers
----application_controller.rb
----admin
------application_controller.rb
--helpers
----admin
------resque_helpers.rb
engines
--platform
----app
------admin
--------application_controller.rb

So here is the class declaration of app/controllers/application_controller.rb

class Admin::ApplicationController < ApplicationController

And here is the class declaration of engines/platform/app/admin/application_controller.rb

class Platform::Admin::ApplicationController < Admin::ApplicationController

So, when working on controller of this engine, trying to call autocompletion on ResqueHelpers broke completely solargraph as it doesn't respond anymore after the first autocomplete call.

I added a bunch of logging to find the issue. I found out it come from super_and_sub? method from ApiMap class.
https://github.com/castwide/solargraph/blob/master/lib/solargraph/api_map.rb#LC460

    def super_and_sub?(sup, sub)
      fqsup = qualify(sup)
      cls = qualify(sub)
      until fqsup.nil? || cls.nil?
        return true if cls == fqsup
        cls = qualify_superclass(cls)
      end
      false
    end

Here is the logging I got :

[WARN] method super_and_sub? called with 'Admin::ResqueHelpers','Platform::Admin::AnotherController'
[WARN] method qualify called with 'Admin::ResqueHelpers',''
[WARN] qualify return cached 'Admin::ResqueHelpers'
[WARN] fqsup : 'Admin::ResqueHelpers'
[WARN] method qualify called with 'Platform::Admin::AnotherController',''
[WARN] qualify return cached 'Platform::Admin::AnotherController'
[WARN] cls : 'Platform::Admin::AnotherController'
[WARN] method qualify called with 'Platform::Admin::ApplicationController','Platform::Admin'
[WARN] qualify return cached 'Platform::Admin::ApplicationController'
[WARN] method qualify called with  'Admin::ApplicationController','Platform::Admin'
[WARN] qualify return cached 'Platform::Admin::ApplicationController'
[WARN] method qualify called with  'Admin::ApplicationController','Platform::Admin'
[WARN] qualify return cached 'Platform::Admin::ApplicationController'
[WARN] method qualify called with  'Admin::ApplicationController','Platform::Admin'
[WARN] qualify return cached 'Platform::Admin::ApplicationController'
... etc infinitely

For now, I have added a limit of 100 on the until.

Can you fix this issue please ? At least add a limit to prevent infinite loops.

Version 0.49.0 includes a change that drops out of super_and_sub? when it encounters a previously tested class. I suspect I need to investigate a lower level root cause for superclasses having circular references, but this should at least avoid infinite loops.

If the problem persists, please let me know.

Great, will try it asap

Issue fixed ! Thanks