Commit Graph
3488 Commits
Author SHA1 Message Date
kw7oe f44adfbeb0 Improve heredoc error message (#9048) 2019-05-19 10:10:11 +02:00
mguimas d63a7a46a7 Support default value when reading inexistent module attribute (#9041)
The private function Module.put_attribute/4 has been renamed to
Module.__put_attribute__/4 for consistency.
2019-05-15 09:28:35 +02:00
Eksperimental c8e700bec1 Improve List.duplicate/2 (#9044) 2019-05-15 09:17:10 +02:00
Eksperimental 341a2d1da8 Improve List.flatten/1,2 (#9045) 2019-05-15 09:16:31 +02:00
Eksperimental 30ab4ad968 Revert #8777 (#9042)
Revert "Remove Integer.to_string/1 and Integer.to_charlist/1 (#8777)"

This reverts commit 2622fd6b0a.
2019-05-15 09:15:55 +02:00
Eksperimental 3038401b09 Improve List.delete/2 (#9043) 2019-05-15 09:14:38 +02:00
Victor Rodrigues 7e6bac3450 Do not allow defmodule with special atoms (#9032)
Fixes #9030
2019-05-10 20:47:36 +02:00
José Valim 0229358f88 Ensure third element in location tuple is either nil or an integer 2019-05-09 10:59:13 +02:00
José Valim dc154f5db7 Allow developers to choose between sname and name in releases (#9024)
We default to --sname which provides safer security defaults.
2019-05-08 11:14:28 +02:00
Wojtek Mach 9a75975769 Add inspect_fun to Inspect.Opts (#8980)
Let's see some use cases. First we configure IEx to use our custom
function:

    iex> IEx.configure(inspect: [inspect_fun: &Pretty.inspect/2])
    :ok

1. Pretty-printing integers

    iex> :math.pow(2, 32) |> trunc()
    4_294_967_296

2. Inspect tuples as records

    iex> {:foo, :bar}
    {:foo, :bar}

    iex> {:person, "Alice", 30}
    #person(name: "Alice", age: 30)

3. Overwrite struct's Inspect implementation

    iex> URI.parse("https://elixir-lang.org")
    #URI<https://elixir-lang.org>

---

Code for the `Pretty.inspect/2` function:

    defmodule Pretty do
      def inspect(integer, opts) when is_integer(integer) do
        PrettyIntegers.inspect(integer, opts)
      end

      def inspect(tuple, opts) when is_tuple(tuple) do
        records = %{
          {:person, 2} => [:name, :age]
        }

        PrettyTuples.inspect(tuple, records, opts)
      end

      def inspect(%URI{} = uri, _opts) do
        Inspect.Algebra.concat(["#URI<", URI.to_string(uri), ">"])
      end

      def inspect(term, opts) do
        Inspect.inspect(term, opts)
      end
    end

    defmodule PrettyIntegers do
      def inspect(term, %Inspect.Opts{base: :decimal}) do
        pretty_decimal(term, "_")
      end

      def inspect(term, %Inspect.Opts{base: base}) do
        Integer.to_string(term, base_to_value(base))
        |> prepend_prefix(base)
      end

      def pretty_decimal(n, separator) when n < 0 do
        "-" <> pretty_decimal(abs(n), separator)
      end

      def pretty_decimal(n, separator) when n >= 1000 do
        left = div(n, 1_000)
        right = rem(n, 1_000)
        right_str = :io_lib.format("~3..0B", [right]) |> IO.iodata_to_binary
        pretty_decimal(left, separator) <> separator <> right_str
      end

      def pretty_decimal(n, _) do
        Integer.to_string(n)
      end

      defp base_to_value(base) do
        case base do
          :binary  -> 2
          :octal   -> 8
          :hex     -> 16
        end
      end

      defp prepend_prefix(value, base) do
        prefix = case base do
          :binary -> "0b"
          :octal  -> "0o"
          :hex    -> "0x"
        end
        prefix <> value
      end
    end

    defmodule PrettyTuples do
      import Inspect.Algebra

      def inspect({}, _records, opts), do: inspect_tuple([], opts)

      def inspect(tuple, records, opts) do
        list = Tuple.to_list(tuple)
        [record_name | values] = list

        case record_fields(records, record_name, tuple) do
          {:ok, fields} ->
            inspect_record(record_name, fields, values, opts)

          _ ->
            inspect_tuple(list, opts)
        end
      end

      defp record_fields(records, record_name, tuple) do
        fields_size = tuple_size(tuple) - 1
        Map.fetch(records, {record_name, fields_size})
      end

      defp inspect_tuple(list, opts) do
        inspect("{", list, "}", &to_doc/2, :flex, opts)
      end

      defp inspect_record(record_name, fields, values, opts) do
        kwlist = Enum.zip(fields, values)
        inspect("##{record_name}(", kwlist, ")", &Inspect.List.keyword/2, :strict, opts)
      end

      defp inspect(open, list, close, fun, break, opts) do
        open = color(open, :tuple, opts)
        sep = color(",", :tuple, opts)
        close = color(close, :tuple, opts)
        container_opts = [separator: sep, break: break]
        container_doc(open, list, close, opts, fun, container_opts)
      end
    end
2019-05-03 17:42:58 +02:00
José Valim 141915625d Consider @file attribute on undefined locals, closes #9005 2019-05-02 20:20:21 +02:00
José Valim 59fcce0b92 Unify error handling and compiler deadlock checking (#9009) 2019-05-02 16:27:13 +02:00
José Valim 89216bbe06 Do not raise on deadlock on ensure_compiled 2019-04-30 12:52:56 +02:00
Andrea Leopardi b3fb4bd7f7 Deprecate Enumerable keys in Map.{take|drop|split} (#8999)
"Keyword.{take|drop|split}" don't offer support for an Enumerable of
keys to take/drop/split based on. However, the "Map" counterparts do.
With this commit, we hard-deprecate support for Enumerables of keys in
"Map.{take|drop|split}". Only lists of keys are allowed.
2019-04-30 09:58:07 +02:00
Tomáš Janoušek 8d079862dc Fix columns in tokenize of dot_call_op (#8995)
handle_dot already gets the column of `(` from strip_dot_space.
2019-04-29 23:34:08 +02:00
José Valim 44fae5cc7a Support :force_do_end_blocks in formatter (#8978) 2019-04-24 09:27:59 +02:00
Frank Hunleth 649339aa95 Fix ETS leak in Registry.register
This fixes an issue where a registry's PIDPartition table would gain an
entry each time after the first call to Registry.register on a unique
registry.

We also guarantee unregistered works generally with "tricky keys".

Closes #8611.

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2019-04-23 12:34:51 +02:00
Johanna Larsson e261b42413 Add Registry.select/2 (#8963) 2019-04-22 17:43:07 +02:00
José Valim 459319fb75 Improve warning for duplicate behaviours, closes #8965 2019-04-19 12:52:24 +02:00
Fernando Tapia Rico 075339a342 Optimize &super/arity and &super(&1) (#8962)
The previous implementation was generating an unnecessary
intermediate function when using `&super/arity`.

In addition, capture expressions using `super` with sequential
value placeholders (`&n`) were not optimized like other functions.
For example, the capture expression `&foo(&1, &2, &3)` is
optimized to `&foo/3` because the value placeholders (`&n`) are
sequential `&1, &2, &3`.
2019-04-18 19:22:04 +02:00
José Valim 8faa40ebff Add config providers (#8957) 2019-04-18 16:34:50 +02:00
Arjan Scherpenisse cef19c9365 Implement static_atom_encoder tokenizer option (#8956) 2019-04-14 19:44:17 +02:00
Glauber Campinho 382d363254 Check that the first letter of alias is upcase (#8947)
The current approach discards the __aliases__ tuple and
do a simple check that allows some strange behavior like:

```elixir
iex(1)> alias :lists, as: :"Elixir.foobar"
:lists
iex(2)> :"Elixir.foobar"
:"Elixir.foobar"
iex(3)> alias :"Elixir.foobar", as: Baz
:"Elixir.foobar"
iex(3)> Baz
:lists
```
2019-04-13 16:54:04 +02:00
José Valim 391e4f6c56 Improve invalid interpolation error message 2019-04-11 12:53:09 +02:00
Eksperimental 333ebbe13b Fix bug in Kernel.in/2 when right is [] (#8946)
Bug was introduced in 08829b3709
2019-04-09 08:37:29 +02:00
eksperimental 08829b3709 Improvents to Kernel.in/2
1) Keep order of elements in Kernel.in/2:

The order of elements was not being kept (not doing as it was said in the docs).
Now it is guaranteed that the elements are compared in the same order they were given.

previously:

    iex> quote do 1 in [1, 2, 3] end |> Macro.expand(Map.put(__ENV__, :context, :guard)) |> Macro.to_string()
    ":erlang.orelse(:erlang.\"=:=\"(1, 2), :erlang.orelse(:erlang.\"=:=\"(1, 3), :erlang.\"=:=\"(1, 1)))"

now:

    iex>  quote do 1 in [1, 2, 3] end |> Macro.expand(Map.put(__ENV__, :context, :guard)) |> Macro.to_string()
    ":erlang.orelse(:erlang.orelse(:erlang.\"=:=\"(1, 1), :erlang.\"=:=\"(1, 2)), :erlang.\"=:=\"(1, 3))"

2) Error message improved from: invalid args for operator "in"...
to: invalid right argument for operator "in"...

3) More tests added to check for generated code

Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2019-04-07 11:36:38 +02:00
José Valim bcac90e3a6 Ensure the first equal entry is returned by min/max
Closes #8936
Closes #8935
2019-04-05 08:35:47 +02:00
José Valim e809326d81 Allow Code.ensure_compiled/2 to not raise on deadlocks
This is important when you may want to check if a module
is available but if that module is running a similar check
on you, you don't want the compiler to fail.
2019-04-01 13:04:00 +02:00
José Valim 0a9fa19b50 Move protocol consolidation tests to its own file 2019-03-31 11:14:49 +02:00
José Valim 4286138123 Move DebugInfo test into its own sync case 2019-03-31 11:10:52 +02:00
José Valim 22bcddfa1b Ensure debug_info is kept in protocols, closes #8923 2019-03-31 10:57:55 +02:00
Fernando Tapia Rico ae6666f0d6 Ensure the struct name matches the given module
This change fixes inconsistencies when building structs: if the
struct was built using the map syntax the `:__struct__` key
was overridden by the given module name; however, if the struct
was built using `struct/1,2` the `:__struct__` key was kept.

For example:

    defmodule X do
      defstruct [:x]
    end

    defmodule Y do
      defdelegate __struct__, to: X
      defdelegate __struct__(args), to: X
    end

    iex> %Y{}
    %Y{x: nil}

    iex> struct(Y)
    %X{x: nil}

Closes #8800
2019-03-31 09:52:58 +02:00
Eksperimental 5a7e6c0778 List.to_string/1 improve error message and docs (#8913) 2019-03-28 09:30:40 +01:00
Edison Yap 8d28d77301 Raise when retrieving capitalized module attribute (#8908) 2019-03-24 15:55:27 +01:00
Fernando Tapia Rico 861ba87db4 Ensure guard checks when expanding string interpolations (#8905)
During the bitstring expansion, guard checks were avoided due to
a special case for inlining binaries during interpolation. These
changes ensure guards are checked.
2019-03-22 11:26:02 +01:00
Tobias Pfeiffer fa64e8c78c Add struct examples to put_in/2, get_in/2 and get_and_update_in/2 (#8899) 2019-03-18 10:19:58 +01:00
Guillermo Iguaran ecf36adfc2 Add support for a default value in System.get_env/1 (#3798) 2019-03-17 11:02:58 +01:00
Fernando Tapia Rico 94c2ffa3a4 Warn if underscored type variable is used more than once (#8894)
The meaning of underscored variables in type specifications 
seems to be the same as regular underscored variables: values 
that are not meant to be used. This behavior can be seen in the
`singleton_typevar` error, in which underscored type variables
are ignored.
2019-03-15 09:37:10 +01:00
José Valim a3c5820d12 Properly track files instead of modules in mix integration with lexical tracker 2019-03-15 00:06:41 +01:00
slepher 12dbdbec86 Handle underscore variables (_, _foo) in typespecs (#8891)
Type variables starting with an underscore (_foo) should not raise compile errors.

Underscore variables (_) cannot be used as type variables.

Fixes #8888
2019-03-14 20:22:35 +01:00
José Valim d48b16cf54 Quote :: to avoid ambiguity (#8890) 2019-03-14 17:08:04 +01:00
Eksperimental f401c954e0 Force System.build_info()[:revision] to be 7 char long (#8879)
Use "git rev-parse --short=7 HEAD" in System.build_info/0 since Git is not always consistent with the length of their short hashes (for example, repos with large histories will have longer hashes) and users can override the size of short hashes. This change attempts to make it more consistent.
2019-03-12 16:55:35 -07:00
Eksperimental 84f9128825 Replace use of "item(s)" with "element(s)" in Enum module (#8885) 2019-03-12 23:24:22 +01:00
Fernando Tapia Rico 0903ad17bc Ensure inspect returns valid ~r// expressions (#8872)
Inspecting regular expressions that contain backslashes (\)
followed by slashes (/) result in invalid ~r// expressions:

    iex(1)> Regex.compile("a\\/b")
    {:ok, ~r/a\\/b/}
    iex(2)> Regex.match?(~r/a\\/b/, "a/b")
    ** (SyntaxError) iex:2: syntax error before: ','
2019-03-11 13:57:43 +01:00
Fernando Tapia Rico b88cd49d8d Validate __struct__ key in map returned by __struct__/0,1 (#8864) 2019-03-07 12:12:30 +01:00
Eksperimental 23b2a09079 Improve error message on invalid @doc (#8852) 2019-03-03 18:22:15 -08:00
SpaceEEC 33d484231b Ensure :name is given in Registry.start_link/1 (#8850) 2019-03-03 17:07:01 -08:00
Andrea Leopardi 3680e85355 Add System.fetch_env/1 and System.fetch_env!/1 (#8846)
This commit adds the System.fetch_env/1 and System.fetch_env!/1 
functions as per the discussion in 
https://groups.google.com/forum/#!topic/elixir-lang-core/QGxEibK4y7Q.

I chose to keep using the same underlying implementation for fetch_env/1 
as the one for get_env/1 because the number of lines would have been the 
same but we would have added one function call.
2019-03-01 12:32:31 -08:00
Carlo Colombo fc039770b4 Enable Access.at/1 to handle negative index (#8843)
Enabling negative index as Enum.at/2 to keep it consistent.
2019-03-01 10:03:10 -08:00
Andrea Leopardi 12953fe8da Remove StreamData-related stuff from the formatter configuration (#8833)
We're not including StreamData (https://github.com/whatyouhide/stream_data) in the standard library anymore. It doesn't make sense that we have StreamData functions in the default locals without parens of the formatter. Instead, we solve the problem on the StreamData side with https://github.com/whatyouhide/stream_data/pull/124.
2019-02-28 23:34:39 +01:00