diff --git a/lib/elixir/lib/code/fragment.ex b/lib/elixir/lib/code/fragment.ex index ff7c46e6afe..ab7b13a5d2c 100644 --- a/lib/elixir/lib/code/fragment.ex +++ b/lib/elixir/lib/code/fragment.ex @@ -178,6 +178,7 @@ defmodule Code.Fragment do @operators ++ @starter_punctuation ++ @non_starter_punctuation ++ @space @textual_operators ~w(when not and or in)c + @keywords ~w(do end after else catch rescue fn true false nil)c defp codepoint_cursor_context(reverse, _opts) do {stripped, spaces} = strip_spaces(reverse, 0) @@ -481,6 +482,8 @@ defmodule Code.Fragment do * This function never returns empty sigils `{:sigil, ''}` or empty structs `{:struct, ''}` as context + * This function returns keywords as `{:keyword, 'do'}` + * This function never returns `:expr` """ @@ -497,7 +500,8 @@ defmodule Code.Fragment do | {:operator, charlist} | {:sigil, charlist} | {:struct, charlist} - | {:unquoted_atom, charlist}, + | {:unquoted_atom, charlist} + | {:keyword, charlist}, inside_dot: {:alias, charlist} | {:dot, inside_dot, charlist} @@ -557,7 +561,10 @@ defmodule Code.Fragment do {{:local_or_var, acc}, offset} when acc in @textual_operators -> build_surround({:operator, acc}, reversed, line, offset) - {{:local_or_var, acc}, offset} when acc not in ~w(do end after else catch rescue)c -> + {{:local_or_var, acc}, offset} when acc in @keywords -> + build_surround({:keyword, acc}, reversed, line, offset) + + {{:local_or_var, acc}, offset} -> build_surround({:local_or_var, acc}, reversed, line, offset) {{:module_attribute, ''}, offset} -> diff --git a/lib/elixir/test/elixir/code_fragment_test.exs b/lib/elixir/test/elixir/code_fragment_test.exs index 07de062421d..176585c4e9c 100644 --- a/lib/elixir/test/elixir/code_fragment_test.exs +++ b/lib/elixir/test/elixir/code_fragment_test.exs @@ -327,8 +327,14 @@ defmodule CodeFragmentTest do assert CF.surround_context("μ•ˆλ…•_세상", {1, 6}) == :none # Keywords are not local or var - for keyword <- ~w(do end after catch else rescue) do - assert CF.surround_context(keyword, {1, 1}) == :none + for keyword <- ~w(do end after catch else rescue fn true false nil)c do + keyword_length = length(keyword) + 1 + + assert %{ + context: {:keyword, ^keyword}, + begin: {1, 1}, + end: {1, ^keyword_length} + } = CF.surround_context(keyword, {1, 1}) end end