Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StackOverflowError when annotating Call #1475

Closed
sparta-developers opened this issue May 9, 2019 · 9 comments

Comments

Projects
None yet
3 participants
@sparta-developers
Copy link

commented May 9, 2019

Exception

Message

*** exception class was changed or removed

Stacktrace

StackOverflowError when annotating Call

### Excerpt

use HalfDomeWeb, :controller

 Line(s) 1-1 in /Users/Sparta/Development/half_dome/lib/half_dome_web/controllers/superuser/trial_controller.ex


### Element Class Name

org.elixir_lang.psi.impl.ElixirUnmatchedUnqualifiedNoParenthesesCallImpl



org.elixir_lang.errorreport.Logger.error(Logger.java:51)
org.elixir_lang.errorreport.Logger.error(Logger.java:34)
org.elixir_lang.annotator.Callable$annotate$1.visitPlainCall(Callable.kt:100)
org.elixir_lang.annotator.Callable$annotate$1.visitNonModuleAttributeCall(Callable.kt:87)
org.elixir_lang.annotator.Callable$annotate$1.visitCall(Callable.kt:47)
org.elixir_lang.annotator.Callable$annotate$1.visitElement(Callable.kt:78)
com.intellij.psi.impl.PsiElementBase.accept(PsiElementBase.java:274)
org.elixir_lang.psi.impl.ElixirUnmatchedUnqualifiedNoParenthesesCallImpl.accept(ElixirUnmatchedUnqualifiedNoParenthesesCallImpl.java:38)
org.elixir_lang.annotator.Callable.annotate(Callable.kt:39)
com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.runAnnotators(DefaultHighlightVisitor.java:120)
com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.visit(DefaultHighlightVisitor.java:87)
com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.runVisitors(GeneralHighlightingPass.java:351)
com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.lambda$collectHighlights$5(GeneralHighlightingPass.java:284)
com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.analyzeByVisitors(GeneralHighlightingPass.java:311)
com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.lambda$analyzeByVisitors$6(GeneralHighlightingPass.java:314)
com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.analyze(DefaultHighlightVisitor.java:71)
com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.analyzeByVisitors(GeneralHighlightingPass.java:314)
com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.collectHighlights(GeneralHighlightingPass.java:281)
com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.collectInformationWithProgress(GeneralHighlightingPass.java:225)
com.intellij.codeInsight.daemon.impl.ProgressableTextEditorHighlightingPass.doCollectInformation(ProgressableTextEditorHighlightingPass.java:84)
com.intellij.codeHighlighting.TextEditorHighlightingPass.collectInformation(TextEditorHighlightingPass.java:69)
com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$null$1(PassExecutorService.java:430)
com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1166)
com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$2(PassExecutorService.java:423)
com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:586)
com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:532)
com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:86)
com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.doRun(PassExecutorService.java:422)
com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$run$0(PassExecutorService.java:398)
com.intellij.openapi.application.impl.ReadMostlyRWLock.executeByImpatientReader(ReadMostlyRWLock.java:164)
com.intellij.openapi.application.impl.ApplicationImpl.executeByImpatientReader(ApplicationImpl.java:218)
com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.run(PassExecutorService.java:396)
com.intellij.concurrency.JobLauncherImpl$VoidForkJoinTask$1.exec(JobLauncherImpl.java:174)
java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
@sparta-developers

This comment has been minimized.

Copy link
Author

commented May 9, 2019

We're getting this error when we open any of our Phoenix controllers. When we open any other type of Elixir file, the plugin is fine.

@KronicDeth KronicDeth changed the title [auto-generated] StackOverflowError when annotating Call May 10, 2019

@KronicDeth KronicDeth added the Kind:Bug label May 10, 2019

@a12e

This comment has been minimized.

Copy link

commented May 12, 2019

We have the same issue with our Phoenix controllers, but also our models and views.

Everytime there is one of the

use App.Web, :controller
use App.Web, :model
use App.Web, :view

The syntax highlighting is stuck at the use App.Web, :controller expression, and the CPU is heavily used, as if there was an infinite loop.

@KronicDeth

This comment has been minimized.

Copy link
Owner

commented May 12, 2019

We're getting this error when we open any of our Phoenix controllers. When we open any other type of Elixir file, the plugin is fine.

This will turn out important. The use App.Web is weird in that it uses apply to dispatch on the argument, so there is special handling to follow that statically.

@KronicDeth KronicDeth marked this as a duplicate of #1463 May 12, 2019

@KronicDeth KronicDeth added this to the 10.5.1 milestone May 12, 2019

@KronicDeth KronicDeth closed this May 12, 2019

@KronicDeth

This comment has been minimized.

Copy link
Owner

commented May 12, 2019

@sparta-developers I can't reproduce, so it something more complicated with the setup than a Phoenix project in a controller. Do you have a repo you can add me on that reproduces? We can also do a Zoom screenshare this week if you can't share code otherwise.

@KronicDeth

This comment has been minimized.

Copy link
Owner

commented May 12, 2019

@a12e I can't reproduce with models or views either. Can you share a repository that reproduces the problem for you? If not, could you screenshare on Zoom this week?

@a12e

This comment has been minimized.

Copy link

commented May 12, 2019

The problematic line seems to be the line 71 of our web.ex (the line use App.Web, :view, when we "recursively" use the Web module)

defmodule App.Web do
  @moduledoc """
  A module that keeps using definitions for controllers,
  views and so on.

  This can be used in your application as:

      use App.Web, :controller
      use App.Web, :view

  The definitions below will be executed for every view,
  controller, etc, so keep them short and clean, focused
  on imports, uses and aliases.

  Do NOT define functions inside the quoted expressions
  below.
  """

  def model do
    quote do
      use Ecto.Schema

      import Ecto
      import Ecto.Changeset
      import Ecto.Query

      @primary_key {:id, :binary_id, autogenerate: true}
      @foreign_key_type :binary_id
      @timestamps_opts [type: :utc_datetime_usec, usec: true]
    end
  end

  def controller do
    quote do
      use Phoenix.Controller, namespace: App.Web

      alias App.Domain
      alias App.Repo

      import Ecto
      import Ecto.Query
      import App.Web.Router.Helpers
      import App.Web.Gettext
    end
  end

  def view do
    quote do
      use Phoenix.View, root: "lib/app/web/templates", namespace: App.Web

      # Import convenience functions from controllers
      import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]

      # Use all HTML functionality (forms, tags, etc)
      use Phoenix.HTML
      import Scrivener.HTML
      require HtmlEntities

      import App.Web.Router.Helpers
      import App.Web.ErrorHelpers
      import App.Web.Gettext
      import App.Web.ViewHelpers

      def render_one(%Ecto.Association.NotLoaded{}), do: nil
      def render_many(%Ecto.Association.NotLoaded{}), do: nil
    end
  end

  def admin_view do
    quote do
      use App.Web, :view   # When commenting this, the plugin doesn't crash anymore
      use App.Web.Admin.ViewHelpers
    end
  end

  @doc """
  When used, dispatch to the appropriate controller/view/etc.
  """
  defmacro __using__(which) when is_atom(which) do
    apply(__MODULE__, which, [])
  end
end
@a12e

This comment has been minimized.

Copy link

commented May 12, 2019

We successfully got around the issue by rewriting the recursion of the use App.Web, :view in another way. Without this recursion of use inside App.Web, the plugin doesn't crash.

  defp base_view do
    quote do
      use Phoenix.View, root: "lib/app/web/templates", namespace: App.Web

      # Import convenience functions from controllers
      import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]

      # Use all HTML functionality (forms, tags, etc)
      use Phoenix.HTML
      import Scrivener.HTML
      require HtmlEntities

      import App.Web.Router.Helpers
      import App.Web.ErrorHelpers
      import App.Web.Gettext
      import App.Web.ViewHelpers

      def render_one(%Ecto.Association.NotLoaded{}), do: nil
      def render_many(%Ecto.Association.NotLoaded{}), do: nil
    end
  end

  def view do
    [
      base_view,
      quote do

      end,
    ]
  end

  def admin_view do
    [
      base_view,
      quote do
        use App.Web.Admin.ViewHelpers
      end,
    ]
  end
@KronicDeth

This comment has been minimized.

Copy link
Owner

commented May 12, 2019

@a12e I can reproduce using #1475 (comment), thanks.

@KronicDeth KronicDeth marked this as a duplicate of #1467 May 20, 2019

@KronicDeth KronicDeth marked this as not a duplicate of #1463 May 20, 2019

@KronicDeth

This comment has been minimized.

Copy link
Owner

commented May 20, 2019

Duplicate of #1467

KronicDeth added a commit that referenced this issue May 20, 2019

Track visited element set in ResolveState to prevent StackOverflowError
Fixes #1467
Fixes #1480
Fixes #1418

Numerous users have reported that annotation can encounter a
`StackOverflowError`.  [A reproduction
case](#1475 (comment))
shows that they are called by Phoenix `Web` modules where one function
containing `quote` block `use`s the same module again, such as an
`admin_view` depending on the base `view` through `use App.Web, :view`.
When the `use App.Web, :view` is resolving, the `defmacro __using__` is
re-entered as is the `admin_view` because there was no tracking of
already visited `PsiElement`s.  The fix is to track the visited elements
and not re-enter the visited elements so that `admin_view` is skipped
and the other call definition clauses can be checked to find `view`.

KronicDeth added a commit that referenced this issue May 20, 2019

Track visited element set in ResolveState to prevent StackOverflowError
Fixes #1467
Fixes #1480
Fixes #1418

Numerous users have reported that annotation can encounter a
`StackOverflowError`.  [A reproduction
case](#1475 (comment))
shows that they are called by Phoenix `Web` modules where one function
containing `quote` block `use`s the same module again, such as an
`admin_view` depending on the base `view` through `use App.Web, :view`.
When the `use App.Web, :view` is resolving, the `defmacro __using__` is
re-entered as is the `admin_view` because there was no tracking of
already visited `PsiElement`s.  The fix is to track the visited elements
and not re-enter the visited elements so that `admin_view` is skipped
and the other call definition clauses can be checked to find `view`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.