   See `pipeline/2` for more information.
   """
   defmacro plug(plug, opts \\ []) do
-    runtime? = Phoenix.plug_init_mode() == :runtime
-
-    plug =
-      if runtime? do
-        expand_alias(plug, __CALLER__)
-      else
-        plug
-      end
-
-    opts =
-      if runtime? and Macro.quoted_literal?(opts) do
-        Macro.prewalk(opts, &expand_alias(&1, __CALLER__))
-      else
-        opts
-      end
+    {plug, opts} = expand_plug_and_opts(plug, opts, __CALLER__)
 
     quote do
       if pipeline = @phoenix_pipeline do


  """
  defmacro scope(path, options, do: context) do
    options = Macro.expand(options, %{__CALLER__ | function: {:init, 1}})

    options = quote do
      path = unquote(path)
      case unquote(options) do
        alias when is_atom(alias) -> [path: path, alias: alias]
        options when is_list(options) -> Keyword.put(options, :path, path)
      end
    end
    do_scope(options, context)
  end


        raise "cannot define plug at the router level, plug must be defined inside a pipeline"
      end
    end
  end

  defp expand_plug_and_opts(plug, opts, caller) do
    runtime? = Phoenix.plug_init_mode() == :runtime

    plug =
      if runtime? do
        expand_alias(plug, caller)
      else
        plug
      end

    opts =
      if runtime? and Macro.quoted_literal?(opts) do
        Macro.prewalk(opts, &expand_alias(&1, caller))
      else
        opts
      end

    {plug, opts}
  end

  defp expand_alias({:__aliases__, _, _} = alias, env),
