Repository: phoenixframework/phoenix
Pull request #3013 (2018-08-12 15:08:39)

Update doc and errors of Phoenix.Router.* modules


Patch:
diff --git a/guides/deployment/deployment.md b/guides/deployment/deployment.md
index 2f5e08eea..668f6ac46 100644
--- a/guides/deployment/deployment.md
+++ b/guides/deployment/deployment.md
@@ -8,7 +8,7 @@ When preparing an application for deployment, there are three main steps:
   * Compiling your application assets
   * Starting your server in production
 
-How those are exactly handled depends on your deployment infrastructure. We have included a guide specific to [Heroku](heroku.html), and for anyone not using Heroku, we recommend using [Distillery](https://github.com/bitwalker/distillery) ([guide for using Distillery with Phoenix](https://hexdocs.pm/distillery/use-with-phoenix.html)).
+How those are exactly handled depends on your deployment infrastructure. We have included a guide specific to [Heroku](heroku.html), and for anyone not using Heroku, we recommend using [Distillery](https://github.com/bitwalker/distillery) ([guide for using Distillery with Phoenix](https://hexdocs.pm/distillery/guides/phoenix_walkthrough.html)).
 
 In any case, this chapter provides a general overview of the deployment steps, which will be useful regardless of your infrastructure or if you want to run in production locally.
 
diff --git a/guides/introduction/community.md b/guides/introduction/community.md
index c032f0bef..fe325c967 100644
--- a/guides/introduction/community.md
+++ b/guides/introduction/community.md
@@ -9,7 +9,5 @@ There are a number of places to connect with community members at all experience
 * Read about [bug reports](https://github.com/phoenixframework/phoenix/blob/master/CONTRIBUTING.md#bug-reports) or open an issue in the Phoenix [issue tracker](https://github.com/phoenixframework/phoenix/issues).
 * Ask or answer questions about Phoenix on [Elixir Forum](https://elixirforum.com/c/phoenix-forum) or [Stack Overflow](http://stackoverflow.com/questions/tagged/phoenix-framework).
 * To discuss new features in the framework, email the [phoenix-core mailing list](https://groups.google.com/group/phoenix-core).
-* Read about [bug reports](https://github.com/phoenixframework/phoenix/blob/master/CONTRIBUTING.md#bug-reports) or open an issue in the Phoenix [issue tracker](https://github.com/phoenixframework/phoenix/issues).
-* Ask or answer questions about Phoenix on [Stack Overflow](https://stackoverflow.com/questions/tagged/phoenix-framework).
 * Follow the Phoenix Framework on [Twitter](https://twitter.com/elixirphoenix).
 * The source for these guides is [on GitHub](https://github.com/phoenixframework/phoenix_guides). To help improve the guides, please report an [issue](https://github.com/phoenixframework/phoenix_guides/issues) or open a [pull request](https://github.com/phoenixframework/phoenix_guides/pulls).
diff --git a/installer/lib/mix/tasks/phx.new.ex b/installer/lib/mix/tasks/phx.new.ex
index b31eb948c..a69b202e2 100644
--- a/installer/lib/mix/tasks/phx.new.ex
+++ b/installer/lib/mix/tasks/phx.new.ex
@@ -12,7 +12,7 @@ defmodule Mix.Tasks.Phx.New do
 
   ## Options
 
-    * `--umbrella` - generate an umbrella application,
+    * `--umbrella` - generate an umbrella project,
       with one application for your domain, and
       a second application for the web interface.
 
diff --git a/lib/mix/phoenix.ex b/lib/mix/phoenix.ex
index d804046c2..6c426d4e2 100644
--- a/lib/mix/phoenix.ex
+++ b/lib/mix/phoenix.ex
@@ -55,7 +55,9 @@ defmodule Mix.Phoenix do
     do: Application.app_dir(app, source_dir)
 
   @doc """
-  Inflect path, scope, alias and more from the given name.
+  Inflects path, scope, alias and more from the given name.
+
+  ## Examples
 
       iex> Mix.Phoenix.inflect("user")
       [alias: "User",
@@ -86,6 +88,7 @@ defmodule Mix.Phoenix do
        scoped: "Admin.SuperUser",
        singular: "super_user",
        path: "admin/super_user"]
+
   """
   def inflect(singular) do
     base       = Mix.Phoenix.base
@@ -147,7 +150,7 @@ defmodule Mix.Phoenix do
   end
 
   @doc """
-  Returns the otp app from the Mix project configuration.
+  Returns the OTP app from the Mix project configuration.
   """
   def otp_app do
     Mix.Project.config |> Keyword.fetch!(:app)
@@ -170,8 +173,8 @@ defmodule Mix.Phoenix do
   @doc """
   The paths to look for template files for generators.
 
-  Defaults to checking the current app's priv directory,
-  and falls back to phoenix's priv directory.
+  Defaults to checking the current app's `priv` directory,
+  and falls back to Phoenix's `priv` directory.
   """
   def generator_paths do
     [".", :phoenix]
@@ -233,7 +236,7 @@ defmodule Mix.Phoenix do
   end
 
   @doc """
-  Returns the otp context app.
+  Returns the OTP context app.
   """
   def context_app do
     this_app = otp_app()
@@ -307,6 +310,7 @@ defmodule Mix.Phoenix do
         Existing deps:
 
             #{inspect Map.keys(deps)}
+
         """
     end
   end
diff --git a/lib/mix/tasks/phx.digest.clean.ex b/lib/mix/tasks/phx.digest.clean.ex
index 4703275ff..55ac8b09a 100644
--- a/lib/mix/tasks/phx.digest.clean.ex
+++ b/lib/mix/tasks/phx.digest.clean.ex
@@ -21,14 +21,14 @@ defmodule Mix.Tasks.Phx.Digest.Clean do
   ## Options
 
     * `-o, --output` - indicates the path to your compiled
-      assets directory. Defaults to `priv/static`.
+      assets directory. Defaults to `priv/static`
 
     * `--age` - specifies a maximum age (in seconds) for assets.
       Files older than age that are not in the last `--keep` versions
-      will be removed. Defaults to 3600 (1 hour).
+      will be removed. Defaults to 3600 (1 hour)
 
     * `--keep` - specifies how many previous versions of assets to keep.
-      Defaults to 2 previous version.
+      Defaults to 2 previous versions
 
   """
 
diff --git a/lib/mix/tasks/phx.digest.ex b/lib/mix/tasks/phx.digest.ex
index ed536267c..c0f8d3062 100644
--- a/lib/mix/tasks/phx.digest.ex
+++ b/lib/mix/tasks/phx.digest.ex
@@ -32,6 +32,7 @@ defmodule Mix.Tasks.Phx.Digest do
     * app-eb0a5b9302e8d32828d8a73f137cc8f0.js
     * app-eb0a5b9302e8d32828d8a73f137cc8f0.js.gz
     * cache_manifest.json
+
   """
 
   @doc false
diff --git a/lib/mix/tasks/phx.gen.channel.ex b/lib/mix/tasks/phx.gen.channel.ex
index fa2b5155b..5179f5ab6 100644
--- a/lib/mix/tasks/phx.gen.channel.ex
+++ b/lib/mix/tasks/phx.gen.channel.ex
@@ -12,13 +12,14 @@ defmodule Mix.Tasks.Phx.Gen.Channel do
 
   For a regular application:
 
-    * a channel in lib/my_app_web/channels
-    * a channel_test in test/my_app_web/channels
+    * a channel in `lib/my_app_web/channels`
+    * a channel test in `test/my_app_web/channels`
 
   For an umbrella application:
 
-    * a channel in apps/my_app_web/lib/app_name_web/channels
-    * a channel_test in apps/my_app_web/test/my_app_web/channels
+    * a channel in `apps/my_app_web/lib/app_name_web/channels`
+    * a channel test in `apps/my_app_web/test/my_app_web/channels`
+
   """
   use Mix.Task
 
@@ -55,6 +56,7 @@ defmodule Mix.Tasks.Phx.Gen.Channel do
     mix phx.gen.channel expects just the module name:
 
         mix phx.gen.channel Room
+
     """
   end
 
diff --git a/lib/mix/tasks/phx.gen.context.ex b/lib/mix/tasks/phx.gen.context.ex
index 8096e8245..083bd90dc 100644
--- a/lib/mix/tasks/phx.gen.context.ex
+++ b/lib/mix/tasks/phx.gen.context.ex
@@ -20,10 +20,10 @@ defmodule Mix.Tasks.Phx.Gen.Context do
   The schema is responsible for mapping the database fields into an
   Elixir struct.
 
-  Overall, this generator will add the following files to lib/your_app:
+  Overall, this generator will add the following files to `lib/your_app`:
 
-    * a context module in accounts/accounts.ex, serving as the API boundary
-    * a schema in accounts/user.ex, with a `users` table
+    * a context module in `accounts/accounts.ex`, serving as the API boundary
+    * a schema in `accounts/user.ex`, with a `users` table
 
   A migration file for the repository and test files for the context
   will also be generated.
diff --git a/lib/mix/tasks/phx.gen.embedded.ex b/lib/mix/tasks/phx.gen.embedded.ex
index bee8dd79d..42c742414 100644
--- a/lib/mix/tasks/phx.gen.embedded.ex
+++ b/lib/mix/tasks/phx.gen.embedded.ex
@@ -6,11 +6,11 @@ defmodule Mix.Tasks.Phx.Gen.Embedded do
 
       mix phx.gen.embedded Blog.Post title:string views:integer
 
-  The first argument is the schema module followed by the schema attributes
+  The first argument is the schema module followed by the schema attributes.
 
   The generated schema above will contain:
 
-    * an embedded schema file in lib/my_app/blog/post.ex.
+    * an embedded schema file in `lib/my_app/blog/post.ex`
 
   ## Attributes
 
diff --git a/lib/mix/tasks/phx.gen.html.ex b/lib/mix/tasks/phx.gen.html.ex
index 9bf7083c2..35398f17d 100644
--- a/lib/mix/tasks/phx.gen.html.ex
+++ b/lib/mix/tasks/phx.gen.html.ex
@@ -12,21 +12,21 @@ defmodule Mix.Tasks.Phx.Gen.Html do
   The context is an Elixir module that serves as an API boundary for
   the given resource. A context often holds many related resources.
   Therefore, if the context already exists, it will be augmented with
-  functions for the given resource. 
+  functions for the given resource.
 
   > Note: A resource may also be split
-  > over distinct contexts (such as Accounts.User and Payments.User).
+  > over distinct contexts (such as `Accounts.User` and `Payments.User`).
 
   The schema is responsible for mapping the database fields into an
   Elixir struct.
 
   Overall, this generator will add the following files to `lib/`:
 
-    * a context module in lib/app/accounts/accounts.ex for the accounts API
-    * a schema in lib/app/accounts/user.ex, with an `users` table
-    * a view in lib/app_web/views/user_view.ex
-    * a controller in lib/app_web/controllers/user_controller.ex
-    * default CRUD templates in lib/app_web/templates/user
+    * a context module in `lib/app/accounts/accounts.ex` for the accounts API
+    * a schema in `lib/app/accounts/user.ex`, with an `users` table
+    * a view in `lib/app_web/views/user_view.ex`
+    * a controller in `lib/app_web/controllers/user_controller.ex`
+    * default CRUD templates in `lib/app_web/templates/user`
 
   A migration file for the repository and test files for the context and
   controller features will also be generated.
diff --git a/lib/mix/tasks/phx.gen.json.ex b/lib/mix/tasks/phx.gen.json.ex
index 28ecd79b8..33245a448 100644
--- a/lib/mix/tasks/phx.gen.json.ex
+++ b/lib/mix/tasks/phx.gen.json.ex
@@ -12,20 +12,20 @@ defmodule Mix.Tasks.Phx.Gen.Json do
   The context is an Elixir module that serves as an API boundary for
   the given resource. A context often holds many related resources.
   Therefore, if the context already exists, it will be augmented with
-  functions for the given resource. 
+  functions for the given resource.
 
   > Note: A resource may also be split
-  > over distinct contexts (such as Accounts.User and Payments.User).
+  > over distinct contexts (such as `Accounts.User` and `Payments.User`).
 
   The schema is responsible for mapping the database fields into an
   Elixir struct.
 
   Overall, this generator will add the following files to `lib/`:
 
-    * a context module in lib/app/accounts/accounts.ex for the accounts API
-    * a schema in lib/app/accounts/user.ex, with an `users` table
-    * a view in lib/app_web/views/user_view.ex
-    * a controller in lib/app_web/controllers/user_controller.ex
+    * a context module in `lib/app/accounts/accounts.ex` for the accounts API
+    * a schema in `lib/app/accounts/user.ex`, with an `users` table
+    * a view in `lib/app_web/views/user_view.ex`
+    * a controller in `lib/app_web/controllers/user_controller.ex`
 
   A migration file for the repository and test files for the context and
   controller features will also be generated.
diff --git a/lib/mix/tasks/phx.gen.presence.ex b/lib/mix/tasks/phx.gen.presence.ex
index 0acf69c48..6483821d5 100644
--- a/lib/mix/tasks/phx.gen.presence.ex
+++ b/lib/mix/tasks/phx.gen.presence.ex
@@ -11,11 +11,8 @@ defmodule Mix.Tasks.Phx.Gen.Presence do
   The only argument is the module name of the Presence tracker,
   which defaults to Presence.
 
-  A new file will be generated in:
-
-    * lib/my_app_web/channels/presence.ex
-
-  Where `my_app_web` is the snake cased version of the module name provided.
+  A new file will be generated in `lib/my_app_web/channels/presence.ex`,
+  where `my_app_web` is the snake cased version of the module name provided.
   """
   use Mix.Task
 
diff --git a/lib/mix/tasks/phx.gen.schema.ex b/lib/mix/tasks/phx.gen.schema.ex
index e572e1436..ec422e594 100644
--- a/lib/mix/tasks/phx.gen.schema.ex
+++ b/lib/mix/tasks/phx.gen.schema.ex
@@ -11,15 +11,17 @@ defmodule Mix.Tasks.Phx.Gen.Schema do
 
   The generated schema above will contain:
 
-    * a schema file in lib/my_app/blog/post.ex, with a `blog_posts` table.
+    * a schema file in `lib/my_app/blog/post.ex`, with a `blog_posts` table
     * a migration file for the repository
 
   The generated migration can be skipped with `--no-migration`.
 
   ## Contexts
 
-  Your schemas can be generated and added to a separate OTP app. Make sure your configuration is
-  properly setup or manually specify the context app with the `--context-app` option with the CLI.
+  Your schemas can be generated and added to a separate OTP app.
+  Make sure your configuration is properly setup or manually
+  specify the context app with the `--context-app` option with
+  the CLI.
 
       # Via config
       config :marketing_web, :generators, context_app: :marketing
diff --git a/lib/phoenix.ex b/lib/phoenix.ex
index 57af75552..db3f127f7 100644
--- a/lib/phoenix.ex
+++ b/lib/phoenix.ex
@@ -65,6 +65,7 @@ defmodule Phoenix do
   in your `config/config.exs`:
 
       config :phoenix, :json_library, Jason
+
   """
   def json_library do
     Application.get_env(:phoenix, :json_library, Poison)
@@ -78,14 +79,15 @@ defmodule Phoenix do
 
   defp warn_on_missing_json_library do
     module = json_library()
-    Code.ensure_loaded?(module) || IO.write :stderr, """
-    failed to load #{inspect(module)} for Phoenix JSON encoding.
-    (module #{inspect(module)} is not available)
+    Code.ensure_loaded?(module) || IO.warn """
+    failed to load #{inspect(module)} for Phoenix JSON encoding
+    (module #{inspect(module)} is not available).
 
     Ensure #{inspect(module)} is loaded from your deps in mix.exs, or
-    configure an existing encoder in your mix config using:
+    configure an existing encoder in your Mix config using:
 
         config :phoenix, :json_library, MyJSONLibrary
+
     """
   end
 end
diff --git a/lib/phoenix/channel.ex b/lib/phoenix/channel.ex
index 4b38b09a2..6e528f1f5 100644
--- a/lib/phoenix/channel.ex
+++ b/lib/phoenix/channel.ex
@@ -195,7 +195,6 @@ defmodule Phoenix.Channel do
       restarts in transient mode, and linked processes exit with the same reason
       unless they're trapping exits
 
-
   ## Subscribing to external topics
 
   Sometimes you may need to programmatically subscribe a socket to external
@@ -485,7 +484,7 @@ defmodule Phoenix.Channel do
   end
   def socket_ref(_socket) do
     raise ArgumentError, """
-    Socket refs can only be generated for a socket that has joined with a push ref
+    socket refs can only be generated for a socket that has joined with a push ref
     """
   end
 
@@ -495,8 +494,8 @@ defmodule Phoenix.Channel do
 
   defp assert_joined!(%Socket{joined: false}) do
     raise """
-    `push`, `reply`, and `broadcast` can only be called after the socket has finished joining.
-    To push a message on join, send to self and handle in handle_info/2, ie:
+    push/3, reply/2, and broadcast/3 can only be called after the socket has finished joining.
+    To push a message on join, send to self and handle in handle_info/2. For example:
 
         def join(topic, auth_msg, socket) do
           ...
@@ -508,6 +507,7 @@ defmodule Phoenix.Channel do
           push(socket, "feed", %{list: feed_items(socket)})
           {:noreply, socket}
         end
+
     """
   end
 end
diff --git a/lib/phoenix/channel/server.ex b/lib/phoenix/channel/server.ex
index bc73b6a5f..7d4ce3d9d 100644
--- a/lib/phoenix/channel/server.ex
+++ b/lib/phoenix/channel/server.ex
@@ -230,6 +230,7 @@ defmodule Phoenix.Channel.Server do
       topic: #{inspect topic}
       event: #{inspect event}
       payload: #{inspect payload}
+
     """
   end
 
@@ -398,7 +399,7 @@ defmodule Phoenix.Channel.Server do
 
   defp handle_result(result, :handle_in) do
     raise """
-    Expected `handle_in/3` to return one of:
+    Expected handle_in/3 to return one of:
 
         {:noreply, Socket.t} |
         {:noreply, Socket.t, timeout | :hibernate} |
@@ -414,7 +415,7 @@ defmodule Phoenix.Channel.Server do
 
   defp handle_result(result, callback) do
     raise """
-    Expected `#{callback}` to return one of:
+    Expected #{callback} to return one of:
 
         {:noreply, Socket.t} |
         {:noreply, Socket.t, timeout | :hibernate} |
@@ -458,7 +459,7 @@ defmodule Phoenix.Channel.Server do
 
   defp handle_reply(_socket, reply) do
     raise """
-    Channel replies from `handle_in/3` are expected to be one of:
+    Channel replies from handle_in/3 are expected to be one of:
 
         status :: atom
         {status :: atom, response :: map}
diff --git a/lib/phoenix/code_reloader/server.ex b/lib/phoenix/code_reloader/server.ex
index 3275a8ae6..9f89e0c57 100644
--- a/lib/phoenix/code_reloader/server.ex
+++ b/lib/phoenix/code_reloader/server.ex
@@ -155,7 +155,7 @@ defmodule Phoenix.CodeReloader.Server do
         mix_compile_unless_stale_config(compilers)
       end
     end
-    
+
     :ok
   end
 
@@ -183,6 +183,7 @@ defmodule Phoenix.CodeReloader.Server do
         You must restart your server after changing the following config or lib files:
 
           * #{Enum.map_join(files, "\n  * ", &Path.relative_to_cwd/1)}
+
         """
      end
    end
diff --git a/lib/phoenix/controller.ex b/lib/phoenix/controller.ex
index e40ed4d09..beba8dce3 100644
--- a/lib/phoenix/controller.ex
+++ b/lib/phoenix/controller.ex
@@ -425,7 +425,7 @@ defmodule Phoenix.Controller do
   @doc """
   Stores the view for rendering.
 
-  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
+  Raises `Plug.Conn.AlreadySentError` if `conn` is already sent.
   """
   @spec put_view(Plug.Conn.t, atom) :: Plug.Conn.t
   def put_view(%Plug.Conn{state: state} = conn, module) when state in @unsent do
@@ -437,7 +437,7 @@ defmodule Phoenix.Controller do
   @doc """
   Stores the view for rendering if one was not stored yet.
 
-  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
+  Raises `Plug.Conn.AlreadySentError` if `conn` is already sent.
   """
   @spec put_new_view(Plug.Conn.t, atom) :: Plug.Conn.t
   def put_new_view(%Plug.Conn{state: state} = conn, module)
@@ -483,7 +483,7 @@ defmodule Phoenix.Controller do
       iex> layout(conn)
       {AppView, :print}
 
-  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
+  Raises `Plug.Conn.AlreadySentError` if `conn` is already sent.
   """
   @spec put_layout(Plug.Conn.t, {atom, binary | atom} | binary | false) :: Plug.Conn.t
   def put_layout(%Plug.Conn{state: state} = conn, layout) do
@@ -514,7 +514,7 @@ defmodule Phoenix.Controller do
   @doc """
   Stores the layout for rendering if one was not stored yet.
 
-  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
+  Raises `Plug.Conn.AlreadySentError` if `conn` is already sent.
   """
   @spec put_new_layout(Plug.Conn.t, {atom, binary | atom} | false) :: Plug.Conn.t
   def put_new_layout(%Plug.Conn{state: state} = conn, layout)
@@ -538,7 +538,7 @@ defmodule Phoenix.Controller do
       iex> layout_formats(conn)
       ["html", "mobile"]
 
-  Raises `Plug.Conn.AlreadySentError` if the conn was already sent.
+  Raises `Plug.Conn.AlreadySentError` if `conn` is already sent.
   """
   @spec put_layout_formats(Plug.Conn.t, [String.t]) :: Plug.Conn.t
   def put_layout_formats(%Plug.Conn{state: state} = conn, formats)
@@ -867,9 +867,9 @@ defmodule Phoenix.Controller do
       sent as download. It is automatically inferred from the
       filename extension
     * `:charset` - the charset of the file, such as "utf-8".
-      Defaults to none.
-    * `:offset` - the bytes to offset when reading. Defualts to `0`.
-    * `:length` - the total bytes to read. Defaults to `:all`.
+      Defaults to none
+    * `:offset` - the bytes to offset when reading. Defaults to `0`
+    * `:length` - the total bytes to read. Defaults to `:all`
 
   ## Examples
 
@@ -1002,19 +1002,19 @@ defmodule Phoenix.Controller do
 
   It sets the following headers:
 
-      * x-frame-options - set to SAMEORIGIN to avoid clickjacking
+      * `x-frame-options` - set to SAMEORIGIN to avoid clickjacking
         through iframes unless in the same origin
-      * x-content-type-options - set to nosniff. This requires
+      * `x-content-type-options` - set to nosniff. This requires
         script and style tags to be sent with proper content type
-      * x-xss-protection - set to "1; mode=block" to improve XSS
+      * `x-xss-protection` - set to "1; mode=block" to improve XSS
         protection on both Chrome and IE
-      * x-download-options - set to noopen to instruct the browser
+      * `x-download-options` - set to noopen to instruct the browser
         not to open a download directly in the browser, to avoid
         HTML files rendering inline and accessing the security
         context of the application (like critical domain cookies)
-      * x-permitted-cross-domain-policies - set to none to restrict
+      * `x-permitted-cross-domain-policies` - set to none to restrict
         Adobe Flash Player’s access to data
-      * cross-origin-window-policy - set to deny to avoid window
+      * `cross-origin-window-policy` - set to deny to avoid window
         control attacks
 
   A custom headers map may also be given to be merged with defaults.
@@ -1110,6 +1110,7 @@ defmodule Phoenix.Controller do
   And now you can use it in accepts too:
 
       plug :accepts, ["html", "json-api"]
+
   """
   @spec accepts(Plug.Conn.t, [binary]) :: Plug.Conn.t | no_return()
   def accepts(conn, [_|_] = accepted) do
@@ -1217,7 +1218,7 @@ defmodule Phoenix.Controller do
               inspect(header) <> " with extensions: " <> inspect(exts)
             end)}
 
-      To accept custom formats, register them under the `:mime` library
+      To accept custom formats, register them under the :mime library
       in your config/config.exs file:
 
           config :mime, :types, %{
@@ -1285,7 +1286,7 @@ defmodule Phoenix.Controller do
   end
 
   @doc """
-  Returns a message from flash by key.
+  Returns a message from flash by `key`.
 
   ## Examples
 
@@ -1354,6 +1355,7 @@ defmodule Phoenix.Controller do
 
       iex> current_path(conn, %{})
       "/users/123"
+
   """
   def current_path(%Plug.Conn{query_string: ""} = conn) do
     conn.request_path
diff --git a/lib/phoenix/endpoint.ex b/lib/phoenix/endpoint.ex
index da0654256..dc052dcab 100644
--- a/lib/phoenix/endpoint.ex
+++ b/lib/phoenix/endpoint.ex
@@ -9,13 +9,13 @@ defmodule Phoenix.Endpoint do
   Overall, an endpoint has three responsibilities:
 
     * to provide a wrapper for starting and stopping the
-      endpoint as part of a supervision tree;
+      endpoint as part of a supervision tree
 
     * to define an initial plug pipeline for requests
-      to pass through;
+      to pass through
 
     * to host web specific configuration for your
-      application.
+      application
 
   ## Endpoints
 
@@ -74,12 +74,12 @@ defmodule Phoenix.Endpoint do
 
     * `:code_reloader` - when `true`, enables code reloading functionality.
       For code the list of code reloader configuration options see
-      `Phoenix.CodeReloader.reload!/1`.
+      `Phoenix.CodeReloader.reload!/1`
 
     * `:debug_errors` - when `true`, uses `Plug.Debugger` functionality for
       debugging failures in the application. Recommended to be set to `true`
       only in development as it allows listing of the application source
-      code during debugging. Defaults to `false`.
+      code during debugging. Defaults to `false`
 
     * `:render_errors` - responsible for rendering templates whenever there
       is a failure in the application. For example, if the application crashes
@@ -88,18 +88,18 @@ defmodule Phoenix.Endpoint do
 
           [view: MyApp.ErrorView, accepts: ~w(html), layout: false]
 
-      The default format is used when none is set in the connection.
+      The default format is used when none is set in the connection
 
     * `:instrumenters` - a list of instrumenter modules whose callbacks will
       be fired on instrumentation events. Read more on instrumentation in the
-      "Instrumentation" section below.
+      "Instrumentation" section below
 
   ### Runtime configuration
 
     * `:cache_static_manifest` - a path to a json manifest file that contains
       static files and their digested version. This is typically set to
       "priv/static/cache_manifest.json" which is the file automatically generated
-      by `mix phx.digest`.
+      by `mix phx.digest`
 
     * `:check_origin` - configure transports to check origins or not. May
       be `false`, `true`, a list of hosts that are allowed, or a function provided as
@@ -114,17 +114,17 @@ defmodule Phoenix.Endpoint do
           check_origin: {MyAppWeb.Auth, :my_check_origin?, []}
 
       The MFA is invoked with the request `%URI{}` as the first argument,
-      followed by arguments in the MFA list.
+      followed by arguments in the MFA list
 
     * `:http` - the configuration for the HTTP server. Currently uses
       Cowboy and accepts all options as defined by
       [`Plug.Adapters.Cowboy`](https://hexdocs.pm/plug/Plug.Adapters.Cowboy.html).
-      Defaults to `false`.
+      Defaults to `false`
 
     * `:https` - the configuration for the HTTPS server. Currently uses
       Cowboy and accepts all options as defined by
       [`Plug.Adapters.Cowboy`](https://hexdocs.pm/plug/Plug.Adapters.Cowboy.html).
-      Defaults to `false`.
+      Defaults to `false`
 
     * `:force_ssl` - ensures no data is ever sent via HTTP, always redirecting
       to HTTPS. It expects a list of options which are forwarded to `Plug.SSL`.
@@ -132,16 +132,16 @@ defmodule Phoenix.Endpoint do
       forcing browsers to always use HTTPS. If an unsafe request (HTTP) is sent,
       it redirects to the HTTPS version using the `:host` specified in the `:url`
       configuration. To dynamically redirect to the `host` of the current request,
-      set `:host` in the `:force_ssl` configuration to `nil`.
+      set `:host` in the `:force_ssl` configuration to `nil`
 
     * `:secret_key_base` - a secret key used as a base to generate secrets
       for encrypting and signing data. For example, cookies and tokens
       are signed by default, but they may also be encrypted if desired.
-      Defaults to `nil` as it must be set per application.
+      Defaults to `nil` as it must be set per application
 
     * `:server` - when `true`, starts the web server when the endpoint
       supervision tree starts. Defaults to `false`. The `mix phx.server`
-      task automatically sets this to `true`.
+      task automatically sets this to `true`
 
     * `:url` - configuration for generating URLs throughout the app.
       Accepts the `:host`, `:scheme`, `:path` and `:port` options. All
@@ -165,11 +165,11 @@ defmodule Phoenix.Endpoint do
       terminating SSL there.
 
       The `:path` option can be used to override root path. Useful when hosting
-      Phoenix behind a reverse proxy with URL rewrite rules.
+      Phoenix behind a reverse proxy with URL rewrite rules
 
     * `:static_url` - configuration for generating URLs for static files.
       It will fallback to `url` if no option is provided. Accepts the same
-      options as `url`.
+      options as `url`
 
     * `:watchers` - a set of watchers to run alongside your server. It
       expects a list of tuples containing the executable and its arguments.
@@ -225,13 +225,13 @@ defmodule Phoenix.Endpoint do
   that are automatically defined in your endpoint:
 
     * for handling paths and URLs: `c:struct_url/0`, `c:url/0`, `c:path/1`,
-      `c:static_url/0`, and `c:static_path/1`;
-    * for handling channel subscriptions: `c:subscribe/2` and `c:unsubscribe/1`;
+      `c:static_url/0`, and `c:static_path/1`
+    * for handling channel subscriptions: `c:subscribe/2` and `c:unsubscribe/1`
     * for broadcasting to channels: `c:broadcast/3`, `c:broadcast!/3`,
       `c:broadcast_from/4`, and `c:broadcast_from!/4`
-    * for configuration: `c:start_link/0`, `c:config/2`, and `c:config_change/2`;
-    * for instrumentation: `c:instrument/3`;
-    * as required by the `Plug` behaviour: `c:Plug.init/1` and `c:Plug.call/2`.
+    * for configuration: `c:start_link/0`, `c:config/2`, and `c:config_change/2`
+    * for instrumentation: `c:instrument/3`
+    * as required by the `Plug` behaviour: `c:Plug.init/1` and `c:Plug.call/2`
 
   ## Instrumentation
 
@@ -255,10 +255,10 @@ defmodule Phoenix.Endpoint do
 
     1. The event callback is called *before* the event happens (in this case,
        before the view is rendered) with the atom `:start` as the first
-       argument; see the "Before clause" section below.
-    2. The event occurs (in this case, the view is rendered).
+       argument; see the "Before clause" section below
+    2. The event occurs (in this case, the view is rendered)
     3. The same event callback is called again, this time with the atom `:stop`
-       as the first argument; see the "After clause" section below.
+       as the first argument; see the "After clause" section below
 
   The second and third argument that each event callback takes depends on the
   callback being an "after" or a "before" callback i.e. it depends on the
@@ -287,13 +287,13 @@ defmodule Phoenix.Endpoint do
       instrumentation is happening (under the `:module` key), the file and line
       (`:file` and `:line`), and the function inside which the instrumentation
       is happening (under `:function`). This information can be used arbitrarily
-      by the callback.
+      by the callback
     * `runtime_metadata` is a map of runtime data that the instrumentation
       passes to the callbacks. This can be used for any purposes: for example,
       when instrumenting the rendering of a view, the name of the view could be
       passed in these runtime data so that instrumenters know which view is
       being rendered (`instrument(:view_render, %{view: "index.html"}, fn
-      ...)`).
+      ...)`)
 
   #### "After" clause
 
@@ -305,11 +305,11 @@ defmodule Phoenix.Endpoint do
   where:
 
     * `time_diff` is an integer representing the time it took to execute the
-      instrumented function **in native units**.
+      instrumented function **in native units**
 
     * `result_of_before_callback` is the return value of the "before" clause of
       the same `event_callback`. This is a means of passing data from the
-      "before" clause to the "after" clause when instrumenting.
+      "before" clause to the "after" clause when instrumenting
 
   The return value of each "before" event callback will be stored and passed to
   the corresponding "after" callback.
@@ -332,23 +332,23 @@ defmodule Phoenix.Endpoint do
   By default, Phoenix instruments the following events:
 
     * `:phoenix_controller_call` - the entire controller pipeline.
-      The `%Plug.Conn{}` is passed as runtime metadata.
+      The `%Plug.Conn{}` is passed as runtime metadata
     * `:phoenix_controller_render` - the rendering of a view from a
       controller. The map of runtime metadata passed to instrumentation
       callbacks has the `:view` key - for the name of the view, e.g. `HexWeb.ErrorView`,
       the `:template` key - for the name of the template, e.g.,
       `"index.html"`, the `:format` key - for the format of the template, and
-      the `:conn` key - containing the `%Plug.Conn{}`.
+      the `:conn` key - containing the `%Plug.Conn{}`
     * `:phoenix_error_render` - the rendering of an error view when an exception,
       throw, or exit is caught. The map of runtime metadata contains the `:status`
       key of the error's HTTP status code, the `:conn` key containg the
       `%Plug.Conn{}`, as well as the `:kind`, `:reason`, and `:stacktrace` of
-      the caught error.
+      the caught error
     * `:phoenix_channel_join` - the joining of a channel. The `%Phoenix.Socket{}`
-      and join params are passed as runtime metadata via `:socket` and `:params`.
+      and join params are passed as runtime metadata via `:socket` and `:params`
     * `:phoenix_channel_receive` - the receipt of an incoming message over a
       channel. The `%Phoenix.Socket{}`, payload, event, and ref are passed as
-      runtime metadata via `:socket`, `:params`, `:event`, and `:ref`.
+      runtime metadata via `:socket`, `:params`, `:event`, and `:ref`
 
   ### Dynamic instrumentation
 
@@ -357,7 +357,6 @@ defmodule Phoenix.Endpoint do
   is not known at compile time, only at runtime, you can use the
   `Phoenix.Endpoint.instrument/4` macro. Refer to its documentation for more
   information.
-
   """
 
   @type topic :: String.t
@@ -369,7 +368,7 @@ defmodule Phoenix.Endpoint do
   # Configuration
 
   @doc """
-  Starts the Endpoint supervision tree.
+  Starts the endpoint supervision tree.
 
   Starts endpoint's configuration cache and possibly the servers for
   handling requests.
@@ -417,7 +416,7 @@ defmodule Phoenix.Endpoint do
   @callback static_url() :: String.t
 
   @doc """
-  Generates a route to a static file in `priv/static`
+  Generates a route to a static file in `priv/static`.
   """
   @callback static_path(path :: String.t) :: String.t
 
@@ -506,7 +505,7 @@ defmodule Phoenix.Endpoint do
       server
     else
       raise ArgumentError, """
-      No pubsub server configured, please setup pubsub in your config.
+      no :pubsub server configured, please setup :pubsub in your config.
 
       By default this looks like:
 
@@ -514,6 +513,7 @@ defmodule Phoenix.Endpoint do
             ...,
             pubsub: [name: MyApp.PubSub,
             adapter: Phoenix.PubSub.PG2]
+
       """
     end
   end
@@ -815,16 +815,16 @@ defmodule Phoenix.Endpoint do
     * `:websocket` - controls the websocket configuration.
       Defaults to `true`. May be false or a keyword list
       of options. See "Shared configuration" and
-      "WebSocket configuration" for the whole list.
+      "WebSocket configuration" for the whole list
 
     * `:longpoll` - controls the longpoll configuration.
       Defaults to `false`. May be true or a keyword list
       of options. See "Shared configuration" and
-      "Longpoll configuration" for the whole list.
+      "Longpoll configuration" for the whole list
 
     * `:shutdown` - the maximum shutdown time of each channel
       when the endpoint is shutting down. Applies only to
-      channel-based sockets.
+      channel-based sockets
 
   ## Examples
 
@@ -835,12 +835,12 @@ defmodule Phoenix.Endpoint do
         websocket: [compress: true]
 
   ## Shared configuration
-  
+
   The configuration below can be given to both `:websocket` and
   `:longpoll` keys:
 
     * `:serializer` - a list of serializers for messages. See
-      `Phoenix.Socket` for more information.
+      `Phoenix.Socket` for more information
 
     * `:transport_log` - if the transport layer itself should log and,
       if so, the level
@@ -860,14 +860,14 @@ defmodule Phoenix.Endpoint do
     * `:code_reloader` - enable or disable the code reloader. Defaults to your
       endpoint configuration
 
-    * `connect_info` - a list of keys that represent data to be copied from
-      the transport to be made available in the user socket `connect/3` callback.
-      
+    * `:connect_info` - a list of keys that represent data to be copied from
+      the transport to be made available in the user socket `connect/3` callback
+
       The valid keys are:
 
-        * `:peer_data` - the result of `Plug.Conn.get_peer_data/1`.
-        * `:x_headers` - all request headers that have an "x-" prefix.
-        * `:uri` - a `%URI{}` with information from the conn.
+        * `:peer_data` - the result of `Plug.Conn.get_peer_data/1`
+        * `:x_headers` - all request headers that have an "x-" prefix
+        * `:uri` - a `%URI{}` with information from the conn
 
       For example:
 
@@ -882,7 +882,7 @@ defmodule Phoenix.Endpoint do
 
   ## Longpoll configuration
 
-  The following configuration applies only to `:longpoll`.
+  The following configuration applies only to `:longpoll`:
 
     * `:window_ms` - how long the client can wait for new messages
       in its poll request
@@ -946,13 +946,14 @@ defmodule Phoenix.Endpoint do
   @doc """
   Checks if Endpoint's web server has been configured to start.
 
-    * `otp_app` - The otp app running the endpoint, for example `:my_app`
+    * `otp_app` - The OTP app running the endpoint, for example `:my_app`
     * `endpoint` - The endpoint module, for example `MyApp.Endpoint`
 
   ## Examples
 
       iex> Phoenix.Endpoint.server?(:my_app, MyApp.Endpoint)
       true
+
   """
   def server?(otp_app, endpoint) when is_atom(otp_app) and is_atom(endpoint) do
     Phoenix.Endpoint.Supervisor.server?(otp_app, endpoint)
diff --git a/lib/phoenix/endpoint/supervisor.ex b/lib/phoenix/endpoint/supervisor.ex
index f22405739..94154e069 100644
--- a/lib/phoenix/endpoint/supervisor.ex
+++ b/lib/phoenix/endpoint/supervisor.ex
@@ -214,7 +214,7 @@ defmodule Phoenix.Endpoint.Supervisor do
   Builds the endpoint url from its configuration.
 
   The result is wrapped in a `{:cache, value}` tuple so
-  the Phoenix.Config layer knows how to cache it.
+  the `Phoenix.Config` layer knows how to cache it.
   """
   def url(endpoint) do
     {:cache, build_url(endpoint, endpoint.config(:url)) |> String.Chars.URI.to_string()}
@@ -245,7 +245,7 @@ defmodule Phoenix.Endpoint.Supervisor do
   Builds the static url from its configuration.
 
   The result is wrapped in a `{:cache, value}` tuple so
-  the Phoenix.Config layer knows how to cache it.
+  the `Phoenix.Config` layer knows how to cache it.
   """
   def static_url(endpoint) do
     url = endpoint.config(:static_url) || endpoint.config(:url)
@@ -256,7 +256,7 @@ defmodule Phoenix.Endpoint.Supervisor do
   Builds a struct url for user processing.
 
   The result is wrapped in a `{:cache, value}` tuple so
-  the Phoenix.Config layer knows how to cache it.
+  the `Phoenix.Config` layer knows how to cache it.
   """
   def struct_url(endpoint) do
     url    = endpoint.config(:url)
@@ -308,7 +308,7 @@ defmodule Phoenix.Endpoint.Supervisor do
   just the static path is returned.
 
   The result is wrapped in a `{:cache | :nocache, value}` tuple so
-  the Phoenix.Config layer knows how to cache it.
+  the `Phoenix.Config` layer knows how to cache it.
   """
   @invalid_local_url_chars ["\\"]
 
diff --git a/lib/phoenix/router.ex b/lib/phoenix/router.ex
index de362aa80..8df6867a4 100644
--- a/lib/phoenix/router.ex
+++ b/lib/phoenix/router.ex
@@ -419,6 +419,7 @@ defmodule Phoenix.Router do
       match(:move, "/events/:id", EventController, :move)
 
       match(:*, "/any", SomeController, :any)
+
   """
   defmacro match(verb, path, plug, plug_opts, options \\ []) do
     add_route(:match, verb, path, plug, plug_opts, options)
diff --git a/lib/phoenix/router/helpers.ex b/lib/phoenix/router/helpers.ex
index 8454ab2a5..c43be25cf 100644
--- a/lib/phoenix/router/helpers.ex
+++ b/lib/phoenix/router/helpers.ex
@@ -7,7 +7,7 @@ defmodule Phoenix.Router.Helpers do
   alias Plug.Conn
 
   @doc """
-  Callback invoked by url generated in each helper module.
+  Callback invoked by the url generated in each helper module.
   """
   def url(router, %Conn{private: private}) do
     case private do
diff --git a/lib/phoenix/router/resource.ex b/lib/phoenix/router/resource.ex
index 500825b7f..043d2ddf3 100644
--- a/lib/phoenix/router/resource.ex
+++ b/lib/phoenix/router/resource.ex
@@ -12,13 +12,13 @@ defmodule Phoenix.Router.Resource do
   @doc """
   The `Phoenix.Router.Resource` struct. It stores:
 
-    * :path - the path as string (not normalized)
-    * :param - the param to be used in routes (not normalized)
-    * :controller - the controller as an atom
-    * :actions - a list of actions as atoms
-    * :route - the context for resource routes
-    * :member - the context for member routes
-    * :collection - the context for collection routes
+    * `:path` - the path as string (not normalized)
+    * `:param` - the param to be used in routes (not normalized)
+    * `:controller` - the controller as an atom
+    * `:actions` - a list of actions as atoms
+    * `:route` - the context for resource routes
+    * `:member` - the context for member routes
+    * `:collection` - the context for collection routes
 
   """
   defstruct [:path, :actions, :param, :route, :controller, :route, :member, :collection, :singleton]
diff --git a/lib/phoenix/router/route.ex b/lib/phoenix/router/route.ex
index 0a04d33d4..1a27a4ddd 100644
--- a/lib/phoenix/router/route.ex
+++ b/lib/phoenix/router/route.ex
@@ -9,17 +9,17 @@ defmodule Phoenix.Router.Route do
   @doc """
   The `Phoenix.Router.Route` struct. It stores:
 
-    * :verb - the HTTP verb as an upcased string
-    * :line - the line the route was defined
-    * :kind - the kind of route, one of `:match`, `:forward`
-    * :path - the normalized path as string
-    * :host - the request host or host prefix
-    * :plug - the plug module
-    * :opts - the plug options
-    * :helper - the name of the helper as a string (may be nil)
-    * :private - the private route info
-    * :assigns - the route info
-    * :pipe_through - the pipeline names as a list of atoms
+    * `:verb` - the HTTP verb as an upcased string
+    * `:line` - the line the route was defined
+    * `:kind` - the kind of route, one of `:match`, `:forward`
+    * `:path` - the normalized path as string
+    * `:host` - the request host or host prefix
+    * `:plug` - the plug module
+    * `:opts` - the plug options
+    * `:helper` - the name of the helper as a string (may be nil)
+    * `:private` - the private route info
+    * `:assigns` - the route info
+    * `:pipe_through` - the pipeline names as a list of atoms
 
   """
 
@@ -153,18 +153,18 @@ defmodule Phoenix.Router.Route do
   @doc """
   Validates and returns the list of forward path segments.
 
-  Raises RuntimeError plug is already forwarded or path contains
-  a dynamic segment.
+  Raises `RuntimeError` if the `plug` is already forwarded or the
+  `path` contains a dynamic segment.
   """
   def forward_path_segments(path, plug, phoenix_forwards) do
     case build_path_match(path) do
       {[], path_segments} ->
         if phoenix_forwards[plug] do
-          raise ArgumentError, "`#{inspect plug}` has already been forwarded to. A module can only be forwarded a single time."
+          raise ArgumentError, "#{inspect plug} has already been forwarded to. A module can only be forwarded a single time."
         end
         path_segments
       _ ->
-        raise ArgumentError, "Dynamic segment `\"#{path}\"` not allowed when forwarding. Use a static path instead."
+        raise ArgumentError, "dynamic segment \"#{path}\" not allowed when forwarding. Use a static path instead."
     end
   end
 
diff --git a/lib/phoenix/router/scope.ex b/lib/phoenix/router/scope.ex
index b801507b4..47e4fef38 100644
--- a/lib/phoenix/router/scope.ex
+++ b/lib/phoenix/router/scope.ex
@@ -32,11 +32,10 @@ defmodule Phoenix.Router.Scope do
   @doc """
   Validates a path is a string and contains a leading prefix.
   """
-
   def validate_path("/" <> _ = path), do: path
   def validate_path(path) when is_binary(path) do
-    IO.write :stderr, """
-    warning: router paths should begin with a forward slash, got: #{inspect path}
+    IO.warn """
+    router paths should begin with a forward slash, got: #{inspect path}
     #{Exception.format_stacktrace}
     """
 
@@ -113,7 +112,7 @@ defmodule Phoenix.Router.Scope do
   end
 
   @doc """
-  Returns true if the module's definition is currently within a scope block
+  Returns true if the module's definition is currently within a scope block.
   """
   def inside_scope?(module), do: length(get_stack(module)) > 1
 
diff --git a/lib/phoenix/socket.ex b/lib/phoenix/socket.ex
index b9c5a25b0..c86d568f4 100644
--- a/lib/phoenix/socket.ex
+++ b/lib/phoenix/socket.ex
@@ -26,13 +26,13 @@ defmodule Phoenix.Socket do
 
   Socket handlers are mounted in Endpoints and must define two callbacks:
 
-    * `connect/3` - receives the socket params, connection info if any, and 
-      authenticates the connection. Must return a `Phoenix.Socket` struct, 
-      often with custom assigns. 
+    * `connect/3` - receives the socket params, connection info if any, and
+      authenticates the connection. Must return a `Phoenix.Socket` struct,
+      often with custom assigns
     * `id/1` - receives the socket returned by `connect/3` and returns the
       id of this connection as a string. The `id` is used to identify socket
       connections, often to a particular user, allowing us to force disconnections.
-      For sockets requiring no authentication, `nil` can be returned.
+      For sockets requiring no authentication, `nil` can be returned
 
   ## Examples
 
@@ -53,20 +53,20 @@ defmodule Phoenix.Socket do
 
   ## Socket fields
 
-    * `id` - The string id of the socket
-    * `assigns` - The map of socket assigns, default: `%{}`
-    * `channel` - The current channel module
-    * `channel_pid` - The channel pid
-    * `endpoint` - The endpoint module where this socket originated, for example: `MyApp.Endpoint`
-    * `handler` - The socket module where this socket originated, for example: `MyApp.UserSocket`
-    * `joined` - If the socket has effectively joined the channel
-    * `join_ref` - The ref sent by the client when joining
-    * `ref` - The latest ref sent by the client
-    * `pubsub_server` - The registered name of the socket's pubsub server
-    * `topic` - The string topic, for example `"room:123"`
-    * `transport` - An identifier for the transport, used for logging
-    * `transport_pid` - The pid of the socket's transport process
-    * `serializer` - The serializer for socket messages
+    * `:id` - The string id of the socket
+    * `:assigns` - The map of socket assigns, default: `%{}`
+    * `:channel` - The current channel module
+    * `:channel_pid` - The channel pid
+    * `:endpoint` - The endpoint module where this socket originated, for example: `MyApp.Endpoint`
+    * `:handler` - The socket module where this socket originated, for example: `MyApp.UserSocket`
+    * `:joined` - If the socket has effectively joined the channel
+    * `:join_ref` - The ref sent by the client when joining
+    * `:ref` - The latest ref sent by the client
+    * `:pubsub_server` - The registered name of the socket's pubsub server
+    * `:topic` - The string topic, for example `"room:123"`
+    * `:transport` - An identifier for the transport, used for logging
+    * `:transport_pid` - The pid of the socket's transport process
+    * `:serializer` - The serializer for socket messages
 
   ## Client-server communication
 
@@ -117,6 +117,7 @@ defmodule Phoenix.Socket do
   run:
 
       send(socket.transport_pid, :garbage_collect)
+
   """
 
   require Logger
@@ -240,7 +241,7 @@ defmodule Phoenix.Socket do
   ## USER API
 
   @doc """
-  Adds key/value pair to socket assigns.
+  Adds a key/value pair to socket assigns.
 
   ## Examples
 
@@ -264,7 +265,7 @@ defmodule Phoenix.Socket do
 
   ## Options
 
-    * `:assigns` - the map of socket assigns to merge into the socket on join.
+    * `:assigns` - the map of socket assigns to merge into the socket on join
 
   ## Examples
 
@@ -331,9 +332,9 @@ defmodule Phoenix.Socket do
           longpoll: [key1: value1, key2: value2, key3: value3]
 
     Note the websocket/longpoll configuration given to socket/3
-    will only apply after you remove all `transport/3` calls from
+    will only apply after you remove all transport/3 calls from
     your socket definition. If you have explicitly upgraded to
-    Cowboy 2, any transport defined with the `transport/3` macro
+    Cowboy 2, any transport defined with the transport/3 macro
     will be ignored.
     """
 
@@ -380,6 +381,7 @@ defmodule Phoenix.Socket do
 
         transport :#{name}, #{inspect transport_mod},
           serializer: [{#{inspect serializer}, "~> 1.0.0"}]
+
     """
   end
 
diff --git a/lib/phoenix/socket/message.ex b/lib/phoenix/socket/message.ex
index 5c6410e89..584d63e9d 100644
--- a/lib/phoenix/socket/message.ex
+++ b/lib/phoenix/socket/message.ex
@@ -4,12 +4,12 @@ defmodule Phoenix.Socket.Message do
 
   The message format requires the following keys:
 
-    * `topic` - The string topic or topic:subtopic pair namespace, for
+    * `:topic` - The string topic or topic:subtopic pair namespace, for
       example "messages", "messages:123"
-    * `event`- The string event name, for example "phx_join"
-    * `payload` - The message payload
-    * `ref` - The unique string ref
-    * `join_ref` - The unique string ref when joining
+    * `:event`- The string event name, for example "phx_join"
+    * `:payload` - The message payload
+    * `:ref` - The unique string ref
+    * `:join_ref` - The unique string ref when joining
 
   """
 
@@ -43,11 +43,11 @@ defmodule Phoenix.Socket.Reply do
 
   The message format requires the following keys:
 
-    * `topic` - The string topic or topic:subtopic pair namespace, for example "messages", "messages:123"
-    * `status` - The reply status as an atom
-    * `payload` - The reply payload
-    * `ref` - The unique string ref
-    * `join_ref` - The unique string ref when joining
+    * `:topic` - The string topic or topic:subtopic pair namespace, for example "messages", "messages:123"
+    * `:status` - The reply status as an atom
+    * `:payload` - The reply payload
+    * `:ref` - The unique string ref
+    * `:join_ref` - The unique string ref when joining
 
   """
 
@@ -61,9 +61,9 @@ defmodule Phoenix.Socket.Broadcast do
 
   The message format requires the following keys:
 
-    * `topic` - The string topic or topic:subtopic pair namespace, for example "messages", "messages:123"
-    * `event`- The string event name, for example "phx_join"
-    * `payload` - The message payload
+    * `:topic` - The string topic or topic:subtopic pair namespace, for example "messages", "messages:123"
+    * `:event`- The string event name, for example "phx_join"
+    * `:payload` - The message payload
 
   """
 
diff --git a/lib/phoenix/socket/transport.ex b/lib/phoenix/socket/transport.ex
index 5cc24b0cb..f2219d661 100644
--- a/lib/phoenix/socket/transport.ex
+++ b/lib/phoenix/socket/transport.ex
@@ -129,10 +129,10 @@ defmodule Phoenix.Socket.Transport do
   In the default `Phoenix.Socket` implementation, the
   metadata expects the following keys:
 
-    * endpoint - the application endpoint
-    * transport - the transport name
-    * params - the connection parameters
-    * options - a keyword list of transport options, often
+    * `:endpoint` - the application endpoint
+    * `:transport` - the transport name
+    * `:params` - the connection parameters
+    * `:options` - a keyword list of transport options, often
       given by developers when configuring the transport.
       It must include a `:serializer` field with the list of
       serializers and their requirements
@@ -381,6 +381,7 @@ defmodule Phoenix.Socket.Transport do
 
                 check_origin: ["https://example.com",
                                "//another.com:888", "//other.com"]
+
         """
         resp(conn, :forbidden, "")
         |> sender.()
@@ -397,9 +398,9 @@ defmodule Phoenix.Socket.Transport do
 
   The supported keys are:
 
-    * `:peer_data` - the result of `Plug.Conn.get_peer_data/1`.
-    * `:x_headers` - a list of all request headers that have an "x-" prefix.
-    * `:uri` - a `%URI{}` derived from the conn.
+    * `:peer_data` - the result of `Plug.Conn.get_peer_data/1`
+    * `:x_headers` - a list of all request headers that have an "x-" prefix
+    * `:uri` - a `%URI{}` derived from the conn
 
   """
   def connect_info(conn, keys) do
@@ -415,7 +416,7 @@ defmodule Phoenix.Socket.Transport do
           {:uri, fetch_uri(conn)}
 
         _ ->
-          raise ArgumentError, "connection info keys are expected to be one of [:peer_data, :x_headers, :uri], got: #{inspect(key)}"
+          raise ArgumentError, ":connect_info keys are expected to be one of :peer_data, :x_headers, or :uri, got: #{inspect(key)}"
       end
     end
   end
@@ -451,7 +452,7 @@ defmodule Phoenix.Socket.Transport do
             {module, function, arguments}
 
           invalid ->
-            raise ArgumentError, "check_origin expects a boolean, list of hosts, or MFA tuple, got: #{inspect(invalid)}"
+            raise ArgumentError, ":check_origin expects a boolean, list of hosts, or MFA tuple, got: #{inspect(invalid)}"
         end
 
       {:cache, check_origin}
@@ -462,7 +463,7 @@ defmodule Phoenix.Socket.Transport do
     case URI.parse(origin) do
       %{host: nil} ->
         raise ArgumentError,
-          "invalid check_origin: #{inspect origin}. " <>
+          "invalid :check_origin option: #{inspect origin}. " <>
           "Expected an origin with a host that is parsable by URI.parse/1. For example: " <>
           "[\"https://example.com\", \"//another.com:888\", \"//other.com\"]"
 
diff --git a/lib/phoenix/template.ex b/lib/phoenix/template.ex
index 445f7cd14..6941de6bd 100644
--- a/lib/phoenix/template.ex
+++ b/lib/phoenix/template.ex
@@ -54,7 +54,7 @@ defmodule Phoenix.Template do
     * template root - the directory where templates are defined
 
     * template engine - a module that receives a template path
-      and transforms its source code into Elixir quoted expressions.
+      and transforms its source code into Elixir quoted expressions
 
   ## Custom Template Engines
 
diff --git a/lib/phoenix/template/eex_engine.ex b/lib/phoenix/template/eex_engine.ex
index 2af9016d1..cd6ddaff9 100644
--- a/lib/phoenix/template/eex_engine.ex
+++ b/lib/phoenix/template/eex_engine.ex
@@ -13,7 +13,7 @@ defmodule Phoenix.Template.EExEngine do
     case Phoenix.Template.format_encoder(name) do
       Phoenix.Template.HTML ->
         unless Code.ensure_loaded?(Phoenix.HTML.Engine) do
-          raise "Could not load Phoenix.HTML.Engine to use with .html.eex templates. " <>
+          raise "could not load Phoenix.HTML.Engine to use with .html.eex templates. " <>
                 "You can configure your own format encoder for HTML but we recommend " <>
                 "adding phoenix_html as a dependency as it provides XSS protection."
         end
diff --git a/lib/phoenix/token.ex b/lib/phoenix/token.ex
index a8d2a07c1..d10568238 100644
--- a/lib/phoenix/token.ex
+++ b/lib/phoenix/token.ex
@@ -34,7 +34,7 @@ defmodule Phoenix.Token do
       the endpoint stored in the socket
     * a string, representing the secret key base itself. A key base
       with at least 20 randomly generated characters should be used
-      to provide adequate entropy.
+      to provide adequate entropy
 
   The second argument is a [cryptographic salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
   which must be the same in both calls to `sign/4` and `verify/4`.
@@ -104,6 +104,7 @@ defmodule Phoenix.Token do
       when generating the encryption and signing keys. Defaults to `:sha256`
     * `:signed_at` - set the timestamp of the token in seconds.
       Defaults to `System.system_time(:second)`
+
   """
   def sign(context, salt, data, opts \\ []) when is_binary(salt) do
     {signed_at_seconds, key_opts} = Keyword.pop(opts, :signed_at)
@@ -122,8 +123,8 @@ defmodule Phoenix.Token do
 
   In this scenario we will create a token, sign it, then provide it to a client
   application. The client will then use this token to authenticate requests for
-  resources from the server. (See `Phoenix.Token` summary for more info about
-  creating tokens.)
+  resources from the server. See `Phoenix.Token` summary for more info about
+  creating tokens.
 
       iex> user_id    = 99
       iex> secret     = "kjoy3o1zeidquwy1398juxzldjlksahdk3"
@@ -156,7 +157,7 @@ defmodule Phoenix.Token do
   ## Options
 
     * `:max_age` - verifies the token only if it has been generated
-      "max age" ago in seconds. A reasonable value is 1 day (`86400`
+      "max age" ago in seconds. A reasonable value is 1 day (86400
       seconds)
     * `:key_iterations` - option passed to `Plug.Crypto.KeyGenerator`
       when generating the encryption and signing keys. Defaults to 1000
@@ -205,6 +206,7 @@ defmodule Phoenix.Token do
 
         config :my_app, MyApp.Endpoint,
             secret_key_base: ...
+
     """
   end
 
diff --git a/lib/phoenix/view.ex b/lib/phoenix/view.ex
index c947ac923..e52636abd 100644
--- a/lib/phoenix/view.ex
+++ b/lib/phoenix/view.ex
@@ -18,13 +18,13 @@ defmodule Phoenix.View do
         def view do
           quote do
             use Phoenix.View, root: "lib/your_app_web/templates", namespace: "web"
-            
+
             # Import convenience functions from controllers
             import Phoenix.Controller, only: [get_flash: 1, get_flash: 2, view_module: 1]
 
             # Use all HTML functionality (forms, tags, etc)
             use Phoenix.HTML
-          
+
             import YourAppWeb.ErrorHelpers
             import YourAppWeb.Gettext
 
@@ -110,7 +110,7 @@ defmodule Phoenix.View do
     * `:root` - the template root to find templates
     * `:path` - the optional path to search for templates within the `:root`.
       Defaults to the underscored view module name. A blank string may
-      be provided to use the `:root` path directly as the template lookup path.
+      be provided to use the `:root` path directly as the template lookup path
     * `:namespace` - the namespace to consider when calculating view paths
     * `:pattern` - the wildcard pattern to apply to the root
       when finding templates. Default `"*"`
@@ -215,7 +215,7 @@ defmodule Phoenix.View do
   Phoenix, they are:
 
     * `:layout` - tells Phoenix to wrap the rendered result in the
-      given layout. See next section.
+      given layout. See next section
 
   The following assigns are reserved, and cannot be set directly:
 


Test patch:
diff --git a/lib/phoenix/test/conn_test.ex b/lib/phoenix/test/conn_test.ex
index b9675931d..b333bf215 100644
--- a/lib/phoenix/test/conn_test.ex
+++ b/lib/phoenix/test/conn_test.ex
@@ -1,26 +1,33 @@
 defmodule Phoenix.ConnTest do
   @moduledoc """
-  Conveniences for testing Phoenix endpoints and
-  connection related helpers.
+  Conveniences for testing Phoenix endpoints and connection related helpers.
 
-  You likely want to use this module or make it part of
-  your `ExUnit.CaseTemplate`. Once used, this module
-  automatically imports all functions defined here as
+  You likely want to use this module or make it part of your `ExUnit.CaseTemplate`.
+  Once used, this module automatically imports all functions defined here as
   well as the functions in `Plug.Conn`.
 
   ## Endpoint testing
 
-  `Phoenix.ConnTest` typically works against endpoints. That's
-  the preferred way to test anything that your router dispatches
-  to.
+  `Phoenix.ConnTest` typically works against endpoints. That's the preferred way
+  to test anything that your router dispatches to:
+  
+      @endpoint MyAppWeb.Endpoint
+      
+      test "says welcome on the home page" do
+        conn = get(build_conn(), "/")
+        assert conn.resp_body =~ "Welcome!"
+      end
 
-      conn = get(build_conn(), "/")
-      assert conn.resp_body =~ "Welcome!"
+      test "logs in" do
+        conn = post(build_conn(), "/login", [username: "john", password: "doe"])
+        assert conn.resp_body =~ "Logged in!"
+      end
 
-      conn = post(build_conn(), "/login", [username: "john", password: "doe"])
-      assert conn.resp_body =~ "Logged in!"
+  The `@endpoint` module attribute contains the endpoint under testing,
+  most commonly your application endpoint itself. If you are using the
+  MyApp.ConnCase generated by Phoenix, it is automatically set for you.
 
-  As in your application, the connection is also the main abstraction
+  As in your router and controllers, the connection is the main abstraction
   in testing. `build_conn()` returns a new connection and functions in this
   module can be used to manipulate the connection before dispatching
   to the endpoint.
@@ -32,51 +39,57 @@ defmodule Phoenix.ConnTest do
       |> put_req_header("accept", "application/json")
       |> get("/")
 
-  The endpoint being tested is accessed via the `@endpoint` module
-  attribute.
+  You can also created your own helpers, such as `json_conn()` that uses
+  `build_conn/0` and `put_req_header/3`, so you avoid repeating the connection
+  setup throughout your tests.
 
   ## Controller testing
 
-  The functions in this module can also be used for controller
-  testing. While endpoint testing is preferred over controller
-  testing as a controller often depends on the pipelines invoked
-  in the router and before, unit testing controllers may be helpful
-  in some situations.
+  The functions in this module can also be used for controller testing.
+  While endpoint testing is preferred over controller testing, especially
+  since the controller in Phoenix plays an integration role between your
+  domain and your views, unit testing controllers may be helpful in some
+  situations.
 
-  For such cases, just pass an atom representing the action
-  to dispatch:
+  For such cases, you need to set the `@endpoint` attribute to your controller
+  and pass an atom representing the action to dispatch:
 
+    @endpoint MyAppWeb.HomeController
+    
+    test "says welcome on the home page" do
       conn = get(build_conn(), :index)
       assert conn.resp_body =~ "Welcome!"
+    end
+
+  Keep in mind that, once the `@endpoint` variable is set, all tests after
+  setting it will be affected.
 
   ## Views testing
 
-  Under other circumstances, you may be testing a view or
-  another layer that requires a connection for processing.
-  For such cases, a connection can be created using the
-  `conn/3` helper:
+  Under other circumstances, you may be testing a view or another layer that
+  requires a connection for processing. For such cases, a connection can be
+  created using the `conn/3` helper:
+
+      MyApp.UserView.render("hello.html", conn: build_conn(:get, "/"))
 
-      MyApp.UserView.render("hello.html",
-                             conn: conn(:get, "/"))
+  While `build_conn/0` returns a connection with no request information to it,
+  `build_conn/2` returns a connection with the given request information already
+  filled in.
 
   ## Recycling
 
-  Browsers implement a storage by using cookies. When a cookie
-  is set in the response, the browser stores it and sends it in
-  the next request.
+  Browsers implement a storage by using cookies. When a cookie is set in the
+  response, the browser stores it and sends it in the next request.
 
-  To emulate this behaviour, this module provides the idea of
-  recycling. The `recycle/1` function receives a connection and
-  returns a new connection, similar to the one returned by
-  `conn/0` with all the response cookies from the previous
-  connection defined as request headers. This is useful when
-  testing multiple routes that require cookies or session to
-  work.
+  To emulate this behaviour, this module provides the idea of recycling.
+  The `recycle/1` function receives a connection and returns a new connection,
+  similar to the one returned by `build_conn/0` with all the response cookies
+  from the previous connection defined as request headers. This is useful when
+  testing multiple routes that require cookies or session to work.
 
-  Keep in mind Phoenix will automatically recycle the connection
-  between dispatches. This usually works out well most times, but
-  it may discard information if you are modifying the connection
-  before the next dispatch:
+  Keep in mind Phoenix will automatically recycle the connection between
+  dispatches. This usually works out well most times, but it may discard
+  information if you are modifying the connection before the next dispatch:
 
       # No recycling as the connection is fresh
       conn = get(build_conn(), "/")
@@ -93,7 +106,8 @@ defmodule Phoenix.ConnTest do
       # No recycling as we did it explicitly
       conn = delete(conn, "/logout")
 
-  Recycling also recycles the "accept" header.
+  Recycling also recycles the "accept" and "authorization" headers,
+  as well as peer data information.
   """
 
   @doc false
@@ -116,7 +130,7 @@ defmodule Phoenix.ConnTest do
   end
 
   @doc """
-  Deprecated version of conn/0. Use build_conn/0 instead
+  Deprecated version of `conn/0`. Use `build_conn/0` instead.
   """
   @spec conn() :: Conn.t
   def conn() do
@@ -139,12 +153,12 @@ defmodule Phoenix.ConnTest do
   end
 
   @doc """
-  Deprecated version of conn/3. Use build_conn/3 instead
+  Deprecated version of `conn/3`. Use `build_conn/3` instead.
   """
   @spec conn(atom | binary, binary, binary | list | map | nil) :: Conn.t
   def conn(method, path, params_or_body \\ nil) do
-    IO.write :stderr, """
-    warning: using conn/3 to build a connection is deprecated. Use build_conn/3 instead.
+    IO.warn """
+    using conn/3 to build a connection is deprecated. Use build_conn/3 instead.
     #{Exception.format_stacktrace}
     """
     build_conn(method, path, params_or_body)
diff --git a/test/phoenix/integration/websocket_channels_test.exs b/test/phoenix/integration/websocket_channels_test.exs
index d8beb881e..9e4f7ddd0 100644
--- a/test/phoenix/integration/websocket_channels_test.exs
+++ b/test/phoenix/integration/websocket_channels_test.exs
@@ -19,6 +19,10 @@ defmodule Phoenix.Integration.WebSocketChannelsTest do
     pubsub: [adapter: Phoenix.PubSub.PG2, name: __MODULE__]
   ])
 
+  defp lobby do
+    "room:lobby#{System.unique_integer()}"
+  end
+
   defmodule RoomChannel do
     use Phoenix.Channel
 
@@ -151,37 +155,38 @@ defmodule Phoenix.Integration.WebSocketChannelsTest do
 
       test "join, leave, and event messages" do
         {:ok, sock} = WebsocketClient.start_link(self(), @vsn_path, @serializer)
-        WebsocketClient.join(sock, "room:lobby1", %{})
+        lobby = lobby()
+        WebsocketClient.join(sock, lobby, %{})
 
         assert_receive %Message{event: "phx_reply",
                                 join_ref: @join_ref,
                                 payload: %{"response" => %{}, "status" => "ok"},
-                                ref: "1", topic: "room:lobby1"}
+                                ref: "1", topic: ^lobby}
 
         assert_receive %Message{event: "joined",
                                 payload: %{"status" => "connected", "user_id" => nil}}
         assert_receive %Message{event: "user_entered",
                                 payload: %{"user" => nil},
-                                ref: nil, topic: "room:lobby1"}
+                                ref: nil, topic: ^lobby}
 
-        channel_pid = Process.whereis(:"room:lobby1")
+        channel_pid = Process.whereis(String.to_atom(lobby))
         assert channel_pid
         assert Process.alive?(channel_pid)
 
-        WebsocketClient.send_event(sock, "room:lobby1", "new_msg", %{body: "hi!"})
+        WebsocketClient.send_event(sock, lobby, "new_msg", %{body: "hi!"})
         assert_receive %Message{event: "new_msg", payload: %{"transport" => ":websocket", "body" => "hi!"}}
 
-        WebsocketClient.leave(sock, "room:lobby1", %{})
+        WebsocketClient.leave(sock, lobby, %{})
         assert_receive %Message{event: "you_left", payload: %{"message" => "bye!"}}
         assert_receive %Message{event: "phx_reply", payload: %{"status" => "ok"}}
         assert_receive %Message{event: "phx_close", payload: %{}}
         refute Process.alive?(channel_pid)
 
-        WebsocketClient.send_event(sock, "room:lobby1", "new_msg", %{body: "Should ignore"})
+        WebsocketClient.send_event(sock, lobby, "new_msg", %{body: "Should ignore"})
         refute_receive %Message{event: "new_msg"}
         assert_receive %Message{event: "phx_reply", payload: %{"response" => %{"reason" => "unmatched topic"}}}
 
-        WebsocketClient.send_event(sock, "room:lobby1", "new_msg", %{body: "Should ignore"})
+        WebsocketClient.send_event(sock, lobby, "new_msg", %{body: "Should ignore"})
         refute_receive %Message{event: "new_msg"}
       end
 
@@ -195,7 +200,7 @@ defmodule Phoenix.Integration.WebSocketChannelsTest do
             extra_headers
           )
 
-        WebsocketClient.join(sock, "room:lobby1", %{})
+        WebsocketClient.join(sock, lobby(), %{})
 
         assert_receive %Message{event: "joined",
                                 payload: %{"connect_info" =>
@@ -211,7 +216,7 @@ defmodule Phoenix.Integration.WebSocketChannelsTest do
             @serializer
           )
 
-        WebsocketClient.join(sock, "room:lobby1", %{})
+        WebsocketClient.join(sock, lobby(), %{})
 
         assert_receive %Message{event: "joined",
                                 payload: %{"connect_info" =>
@@ -228,7 +233,7 @@ defmodule Phoenix.Integration.WebSocketChannelsTest do
             "ws://127.0.0.1:#{@port}/ws/connect_info/websocket?vsn=#{@vsn}",
             @serializer
           )
-        WebsocketClient.join(sock, "room:lobby1", %{})
+        WebsocketClient.join(sock, lobby(), %{})
 
         assert_receive %Message{event: "joined",
                                 payload: %{"connect_info" =>
@@ -262,24 +267,27 @@ defmodule Phoenix.Integration.WebSocketChannelsTest do
       test "sends phx_error if a channel server abnormally exits" do
         {:ok, sock} = WebsocketClient.start_link(self(), @vsn_path, @serializer)
 
-        WebsocketClient.join(sock, "room:lobby", %{})
+        lobby = lobby()
+        WebsocketClient.join(sock, lobby, %{})
         assert_receive %Message{event: "phx_reply", ref: "1", payload: %{"response" => %{}, "status" => "ok"}}
         assert_receive %Message{event: "joined"}
         assert_receive %Message{event: "user_entered"}
 
         capture_log fn ->
-          WebsocketClient.send_event(sock, "room:lobby", "boom", %{})
-          assert_receive %Message{event: "phx_error", payload: %{}, topic: "room:lobby"}
+          WebsocketClient.send_event(sock, lobby, "boom", %{})
+          assert_receive %Message{event: "phx_error", payload: %{}, topic: ^lobby}
         end
       end
 
       test "channels are terminated if transport normally exits" do
         {:ok, sock} = WebsocketClient.start_link(self(), @vsn_path, @serializer)
 
-        WebsocketClient.join(sock, "room:lobby2", %{})
+        lobby = lobby()
+        WebsocketClient.join(sock, lobby, %{})
         assert_receive %Message{event: "phx_reply", ref: "1", payload: %{"response" => %{}, "status" => "ok"}}
         assert_receive %Message{event: "joined"}
-        channel = Process.whereis(:"room:lobby2")
+
+        channel = Process.whereis(String.to_atom(lobby))
         assert channel
         Process.monitor(channel)
         WebsocketClient.close(sock)
@@ -290,11 +298,11 @@ defmodule Phoenix.Integration.WebSocketChannelsTest do
       test "refuses websocket events that haven't joined" do
         {:ok, sock} = WebsocketClient.start_link(self(), @vsn_path, @serializer)
 
-        WebsocketClient.send_event(sock, "room:lobby", "new_msg", %{body: "hi!"})
+        WebsocketClient.send_event(sock, lobby(), "new_msg", %{body: "hi!"})
         refute_receive %Message{event: "new_msg"}
         assert_receive %Message{event: "phx_reply", payload: %{"response" => %{"reason" => "unmatched topic"}}}
 
-        WebsocketClient.send_event(sock, "room:lobby1", "new_msg", %{body: "Should ignore"})
+        WebsocketClient.send_event(sock, lobby(), "new_msg", %{body: "Should ignore"})
         refute_receive %Message{event: "new_msg"}
       end
 
diff --git a/test/phoenix/router/forward_test.exs b/test/phoenix/router/forward_test.exs
index 443f1473b..84869b3c5 100644
--- a/test/phoenix/router/forward_test.exs
+++ b/test/phoenix/router/forward_test.exs
@@ -85,7 +85,7 @@ defmodule Phoenix.Router.ForwardTest do
       end
     end
 
-    assert_raise ArgumentError, ~r{Dynamic segment `"/api/:version"` not allowed}, fn ->
+    assert_raise ArgumentError, ~r{dynamic segment "/api/:version" not allowed}, fn ->
       Code.eval_quoted(router)
     end
   end
@@ -99,7 +99,7 @@ defmodule Phoenix.Router.ForwardTest do
       end
     end
 
-    assert_raise ArgumentError, ~r{`Phoenix.Router.ForwardTest.ApiRouter` has already been forwarded}, fn ->
+    assert_raise ArgumentError, ~r{Phoenix.Router.ForwardTest.ApiRouter has already been forwarded}, fn ->
       Code.eval_quoted(router)
     end
   end