Commit Graph
3497 Commits
Author SHA1 Message Date
José Valim a211223810 Keep struct fields ordered in types
Closes https://github.com/elixir-lang/ex_doc/issues/1016
2019-06-11 13:50:07 +02:00
José Valim 9b2e7892ca Do not crash formatter on false positive sigils, closes #9123
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
2019-06-10 11:19:09 +02:00
José Valim e1b68261b3 Raise on recursive macros (#9111)
Closes #9101.
2019-06-03 17:34:15 +02:00
José Valim 7e1d1650b3 Support unary functions in String.replace/4 (#9073)
We also deprecate the :insert_replaced option since the
anonymous functions is strictly superior.

Closes #9023.
2019-05-30 11:09:27 +02:00
Aleksei Matiushkin bb0e8a8850 Inspect.Opts.custom_options (#9096) 2019-05-30 10:10:48 +02:00
Eksperimental d4f8d419e4 Use https instead of http when servers are redirecting (#9094)
The servers are automatically redirecting from http:// to https://
2019-05-29 07:37:54 +02:00
José Valim dd17800b86 Do not expand ~ when not followed by a path separator 2019-05-27 00:16:39 +02:00
Fernando Tapia Rico 2490cc8e6a Add possible Windows errors to File.cd!/1 tests 2019-05-21 18:47:32 +02:00
Daniil Fedotov 145b7019ae Make regexes fall back to binary matching on incompatible runtime version (#9040)
Regexes are precompiled to binary values during code compilation.
These binary values may be incompatible between different PCRE versions
and OS endianness. This makes code less portable to achieve slight
performance improvement.

PCRE version and endianness are parts of Regex structure and may be
checked in runtime.

This commit adds this check and makes regex execution fall back 
to binary matching if versions are incompatible.

This slightly reduces performance (around 5% for simple regexes) for
compatible versions because there is an additional version read.
Also for incompatible versions it's as fast as binary matching.
2019-05-21 09:34:55 +02:00
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