Require Elixir 1.14 (#1342)

This commit is contained in:
Jonatan Kłosko 2022-08-11 20:13:57 +02:00 committed by GitHub
parent eac93a47ec
commit 3d5c7c3fad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 52 additions and 128 deletions

View file

@ -8,7 +8,7 @@ main() {
wxwidgets_ref="v3.1.7" wxwidgets_ref="v3.1.7"
otp_repo="wojtekmach/otp" otp_repo="wojtekmach/otp"
otp_ref="wm-WX_MACOS_NON_GUI_APP" otp_ref="wm-WX_MACOS_NON_GUI_APP"
elixir_vsn="1.13.4" elixir_vsn="1.14.0-rc.0"
target=$(target) target=$(target)

View file

@ -4,7 +4,10 @@ on:
branches: branches:
- main - main
tags: tags:
- 'v*.*.*' - "v*.*.*"
env:
otp: "25.0"
elixir: "1.14.0-rc.0"
jobs: jobs:
assets: assets:
outputs: outputs:
@ -15,24 +18,24 @@ jobs:
- name: Install Erlang & Elixir - name: Install Erlang & Elixir
uses: erlef/setup-beam@v1 uses: erlef/setup-beam@v1
with: with:
otp-version: '24.0' otp-version: ${{ env.otp }}
elixir-version: '1.13.4' elixir-version: ${{ env.elixir }}
- name: Cache Mix - name: Cache Mix
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: |
deps deps
_build _build
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} key: ${{ runner.os }}-mix-${{ env.elixir }}-${{ env.otp }}-${{ hashFiles('**/mix.lock') }}
restore-keys: | restore-keys: |
${{ runner.os }}-mix- ${{ runner.os }}-mix-${{ env.elixir }}-${{ env.otp }}-
# Note: we need to get Phoenix and LV because package.json points to them directly # Note: we need to get Phoenix and LV because package.json points to them directly
- name: Install mix dependencies - name: Install mix dependencies
run: mix deps.get run: mix deps.get
- name: Install Node - name: Install Node
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: '14.x' node-version: "14.x"
- name: Cache npm dependencies - name: Cache npm dependencies
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
@ -59,8 +62,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
# The output is set only if there was a commit, otherwise # The output is set only if there was a commit, otherwise
# we pass an empty ref and and the default is used # we pass an empty ref and and the default is used
ref: ${{ needs.assets.outputs.sha }} ref: ${{ needs.assets.outputs.sha }}
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1

View file

@ -4,6 +4,9 @@ on:
push: push:
branches: branches:
- main - main
env:
otp: "25.0"
elixir: "1.14.0-rc.0"
jobs: jobs:
main: main:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -14,21 +17,22 @@ jobs:
- name: Install Erlang & Elixir - name: Install Erlang & Elixir
uses: erlef/setup-beam@v1 uses: erlef/setup-beam@v1
with: with:
otp-version: '24.0' otp-version: ${{ env.otp }}
elixir-version: '1.13.4' elixir-version: ${{ env.elixir }}
- name: Cache Mix - name: Cache Mix
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: | path: |
deps deps
_build _build
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} key: ${{ runner.os }}-mix-${{ env.elixir }}-${{ env.otp }}-${{ hashFiles('**/mix.lock') }}
restore-keys: | restore-keys: |
${{ runner.os }}-mix- ${{ runner.os }}-mix-${{ env.elixir }}-${{ env.otp }}-
- name: Install mix dependencies - name: Install mix dependencies
run: mix deps.get run: mix deps.get
- name: Check formatting - name: Check formatting
run: mix format --check-formatted # TODO: remove deps.compile on Elixir > 1.14.0-rc.0
run: mix do deps.compile, format --check-formatted
- name: Check warnings - name: Check warnings
run: mix compile --warnings-as-errors run: mix compile --warnings-as-errors
- name: Run tests - name: Run tests
@ -36,7 +40,7 @@ jobs:
- name: Install Node - name: Install Node
uses: actions/setup-node@v2 uses: actions/setup-node@v2
with: with:
node-version: '14.x' node-version: "14.x"
- name: Cache npm dependencies - name: Cache npm dependencies
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
@ -63,11 +67,11 @@ jobs:
uses: erlef/setup-beam@v1 uses: erlef/setup-beam@v1
with: with:
version-type: strict version-type: strict
otp-version: '24.2' otp-version: ${{ env.otp }}
elixir-version: '1.13.4' elixir-version: ${{ env.elixir }}
- name: Start epmd - name: Start epmd
run: cmd /c "START /b epmd" run: cmd /c "START /b epmd"
working-directory: ${{ env.INSTALL_DIR_FOR_OTP }}/erts-12.2/bin working-directory: ${{ env.INSTALL_DIR_FOR_OTP }}/erts-13.0/bin
# Add tar that supports symlinks, see https://github.com/actions/virtual-environments/issues/4679 # Add tar that supports symlinks, see https://github.com/actions/virtual-environments/issues/4679
- name: Add tar.exe - name: Add tar.exe
run: | run: |
@ -78,15 +82,11 @@ jobs:
path: | path: |
deps deps
_build _build
key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} key: ${{ runner.os }}-mix-${{ env.elixir }}-${{ env.otp }}-${{ hashFiles('**/mix.lock') }}
restore-keys: | restore-keys: |
${{ runner.os }}-mix- ${{ runner.os }}-mix-${{ env.elixir }}-${{ env.otp }}-
- name: Install mix dependencies - name: Install mix dependencies
run: mix deps.get run: mix deps.get
- name: Check formatting
run: mix format --check-formatted
- name: Check warnings
run: mix compile --warnings-as-errors
- name: Run tests - name: Run tests
run: mix test run: mix test
- name: Build the app - name: Build the app

View file

@ -1,6 +1,6 @@
# Stage 1 # Stage 1
# Builds the Livebook release # Builds the Livebook release
FROM hexpm/elixir:1.13.4-erlang-24.3.4.2-debian-bullseye-20210902-slim AS build FROM hexpm/elixir:1.14.0-rc.0-erlang-24.3.4.2-debian-bullseye-20210902-slim AS build
RUN apt-get update && apt-get upgrade -y && \ RUN apt-get update && apt-get upgrade -y && \
apt-get install --no-install-recommends -y \ apt-get install --no-install-recommends -y \
@ -38,7 +38,7 @@ RUN mix do compile, release livebook
# We use the same base image, because we need Erlang, Elixir and Mix # We use the same base image, because we need Erlang, Elixir and Mix
# during runtime to spawn the Livebook standalone runtimes. # during runtime to spawn the Livebook standalone runtimes.
# Consequently the release doesn't include ERTS as we have it anyway. # Consequently the release doesn't include ERTS as we have it anyway.
FROM hexpm/elixir:1.13.4-erlang-24.3.4.2-debian-bullseye-20210902-slim FROM hexpm/elixir:1.14.0-rc.0-erlang-24.3.4.2-debian-bullseye-20210902-slim
RUN apt-get update && apt-get upgrade -y && \ RUN apt-get update && apt-get upgrade -y && \
apt-get install --no-install-recommends -y \ apt-get install --no-install-recommends -y \

View file

@ -480,7 +480,7 @@ defmodule Livebook.Intellisense.IdentifierMatcher do
defp valid_alias_rest?(rest), do: valid_alias_piece?(rest) defp valid_alias_rest?(rest), do: valid_alias_piece?(rest)
defp usable_as_unquoted_module?(mod) do defp usable_as_unquoted_module?(mod) do
macro_classify_atom(mod) in [:identifier, :unquoted] Macro.classify_atom(mod) in [:identifier, :unquoted]
end end
defp get_matching_modules(hint, ctx) do defp get_matching_modules(hint, ctx) do
@ -641,70 +641,4 @@ defmodule Livebook.Intellisense.IdentifierMatcher do
documentation: {"text/markdown", info.doc} documentation: {"text/markdown", info.doc}
} }
end end
# ---
# TODO: use Macro.classify_atom/1 on Elixir 1.14
def macro_classify_atom(atom) do
case macro_inner_classify(atom) do
:alias -> :alias
:identifier -> :identifier
type when type in [:unquoted_operator, :not_callable] -> :unquoted
_ -> :quoted
end
end
defp macro_inner_classify(atom) when is_atom(atom) do
cond do
atom in [:%, :%{}, :{}, :<<>>, :..., :.., :., :"..//", :->] ->
:not_callable
atom in [:"::"] ->
:quoted_operator
Macro.operator?(atom, 1) or Macro.operator?(atom, 2) ->
:unquoted_operator
true ->
charlist = Atom.to_charlist(atom)
if macro_valid_alias?(charlist) do
:alias
else
case :elixir_config.identifier_tokenizer().tokenize(charlist) do
{kind, _acc, [], _, _, special} ->
if kind == :identifier and not :lists.member(?@, special) do
:identifier
else
:not_callable
end
_ ->
:other
end
end
end
end
defp macro_valid_alias?('Elixir' ++ rest), do: macro_valid_alias_piece?(rest)
defp macro_valid_alias?(_other), do: false
defp macro_valid_alias_piece?([?., char | rest]) when char >= ?A and char <= ?Z,
do: macro_valid_alias_piece?(macro_trim_leading_while_valid_identifier(rest))
defp macro_valid_alias_piece?([]), do: true
defp macro_valid_alias_piece?(_other), do: false
defp macro_trim_leading_while_valid_identifier([char | rest])
when char >= ?a and char <= ?z
when char >= ?A and char <= ?Z
when char >= ?0 and char <= ?9
when char == ?_ do
macro_trim_leading_while_valid_identifier(rest)
end
defp macro_trim_leading_while_valid_identifier(other) do
other
end
end end

View file

@ -566,8 +566,7 @@ defmodule Livebook.Runtime.ErlDist.RuntimeServer do
{:ok, pid} = {:ok, pid} =
Task.Supervisor.start_child(state.task_supervisor, fn -> Task.Supervisor.start_child(state.task_supervisor, fn ->
binding = [] binding = []
# TODO: Use Code.env_for_eval and eval_quoted_with_env on Elixir v1.14+ env = Code.env_for_eval([])
env = :elixir.env_for_eval([])
scan_and_ack.(binding, env) scan_and_ack.(binding, env)
end) end)

View file

@ -182,8 +182,7 @@ defmodule Livebook.Runtime.Evaluator do
""" """
@spec intellisense_context() :: Livebook.Intellisense.intellisense_context() @spec intellisense_context() :: Livebook.Intellisense.intellisense_context()
def intellisense_context() do def intellisense_context() do
# TODO: Use Code.env_for_eval and eval_quoted_with_env on Elixir v1.14+ env = Code.env_for_eval([])
env = :elixir.env_for_eval([])
map_binding = fn fun -> fun.([]) end map_binding = fn fun -> fun.([]) end
%{env: env, map_binding: map_binding} %{env: env, map_binding: map_binding}
end end
@ -304,8 +303,7 @@ defmodule Livebook.Runtime.Evaluator do
end end
defp initial_context() do defp initial_context() do
# TODO: Use Code.env_for_eval and eval_quoted_with_env on Elixir v1.14+ env = Code.env_for_eval([])
env = :elixir.env_for_eval([])
%{binding: [], env: env, id: random_id()} %{binding: [], env: env, id: random_id()}
end end
@ -429,11 +427,7 @@ defmodule Livebook.Runtime.Evaluator do
defp eval(code, binding, env) do defp eval(code, binding, env) do
try do try do
quoted = Code.string_to_quoted!(code, file: env.file) quoted = Code.string_to_quoted!(code, file: env.file)
# TODO: Use Code.eval_quoted_with_env/3 on Elixir v1.14 {value, binding, env} = Code.eval_quoted_with_env(quoted, binding, env)
{value, binding, env} = :elixir.eval_quoted(quoted, binding, env)
# TODO: Remove this line on Elixir v1.14 as binding propagates to env correctly
{_, binding, env} = :elixir.eval_forms(:ok, binding, env)
{:ok, value, binding, env} {:ok, value, binding, env}
catch catch
kind, error -> kind, error ->
@ -475,7 +469,7 @@ defmodule Livebook.Runtime.Evaluator do
# Adapted from https://github.com/elixir-lang/elixir/blob/1c1654c88adfdbef38ff07fc30f6fbd34a542c07/lib/iex/lib/iex/evaluator.ex#L355-L372 # Adapted from https://github.com/elixir-lang/elixir/blob/1c1654c88adfdbef38ff07fc30f6fbd34a542c07/lib/iex/lib/iex/evaluator.ex#L355-L372
# TODO: Remove else branch once we depend on the versions below # TODO: Remove else branch once we depend on the versions below
if System.otp_release() >= "25" and Version.match?(System.version(), "~> 1.14-dev") do if System.otp_release() >= "25" do
defp prune_stacktrace(stack) do defp prune_stacktrace(stack) do
stack stack
|> Enum.reverse() |> Enum.reverse()

View file

@ -466,7 +466,7 @@ defmodule Livebook.Utils do
base_url base_url
|> URI.parse() |> URI.parse()
|> Map.replace!(:path, "/import") |> Map.replace!(:path, "/import")
|> append_query("url=#{URI.encode_www_form(url)}") |> URI.append_query("url=#{URI.encode_www_form(url)}")
|> URI.to_string() |> URI.to_string()
end end
@ -484,19 +484,10 @@ defmodule Livebook.Utils do
base_url base_url
|> URI.parse() |> URI.parse()
|> Map.replace!(:path, "/open") |> Map.replace!(:path, "/open")
|> append_query("path=#{URI.encode_www_form(path)}") |> URI.append_query("path=#{URI.encode_www_form(path)}")
|> URI.to_string() |> URI.to_string()
end end
# TODO: On Elixir v1.14, use URI.append_query/2
def append_query(%URI{query: query} = uri, query_to_add) when query in [nil, ""] do
%{uri | query: query_to_add}
end
def append_query(%URI{} = uri, query) do
%{uri | query: uri.query <> "&" <> query}
end
@doc """ @doc """
Formats the given number of bytes into a human-friendly text. Formats the given number of bytes into a human-friendly text.

View file

@ -290,7 +290,7 @@ defmodule LivebookCLI.Server do
defp update_query(url, params) do defp update_query(url, params) do
url url
|> URI.parse() |> URI.parse()
|> Livebook.Utils.append_query(URI.encode_query(params)) |> URI.append_query(URI.encode_query(params))
|> URI.to_string() |> URI.to_string()
end end

View file

@ -1,7 +1,7 @@
defmodule Livebook.MixProject do defmodule Livebook.MixProject do
use Mix.Project use Mix.Project
@elixir_requirement "~> 1.13" @elixir_requirement "~> 1.14.0-rc.0"
@version "0.6.3" @version "0.6.3"
@description "Interactive and collaborative code notebooks - made with Phoenix LiveView" @description "Interactive and collaborative code notebooks - made with Phoenix LiveView"

View file

@ -9,11 +9,8 @@ defmodule Livebook.IntellisenseTest do
quote do quote do
block = unquote(Macro.escape(block)) block = unquote(Macro.escape(block))
binding = [] binding = []
# TODO: Use Code.env_for_eval and eval_quoted_with_env on Elixir v1.14+ env = Code.env_for_eval([])
env = :elixir.env_for_eval([]) {value, binding, env} = Code.eval_quoted_with_env(block, binding, env)
{_, binding, env} = :elixir.eval_quoted(block, binding, env)
# TODO: Remove this line on Elixir v1.14 as binding propagates to env correctly
{_, binding, env} = :elixir.eval_forms(:ok, binding, env)
%{ %{
env: env, env: env,
@ -162,7 +159,7 @@ defmodule Livebook.IntellisenseTest do
label: "Enum", label: "Enum",
kind: :module, kind: :module,
detail: "module", detail: "module",
documentation: "Provides a set of algorithms to work with enumerables.", documentation: "Functions for working with collections (known as enumerables).",
insert_text: "Enum" insert_text: "Enum"
}, },
%{ %{

View file

@ -97,8 +97,11 @@ defmodule Livebook.Runtime.EvaluatorTest do
Evaluator.evaluate_code(evaluator, code, :code_1, nil, file: "file.ex") Evaluator.evaluate_code(evaluator, code, :code_1, nil, file: "file.ex")
assert_receive {:runtime_evaluation_response, :code_1, assert_receive {:runtime_evaluation_response, :code_1,
{:error, :error, :function_clause, [{List, :first, _arity, _location}]}, {:error, :error, :function_clause,
metadata()} [
{List, :first, _arity, _location1},
{:elixir_eval, :__FILE__, 1, _location2}
]}, metadata()}
end end
test "returns additional metadata when there is a syntax error", %{evaluator: evaluator} do test "returns additional metadata when there is a syntax error", %{evaluator: evaluator} do
@ -138,7 +141,9 @@ defmodule Livebook.Runtime.EvaluatorTest do
Evaluator.evaluate_code(evaluator, code, :code_1, nil, file: "file.ex") Evaluator.evaluate_code(evaluator, code, :code_1, nil, file: "file.ex")
expected_stacktrace = [{Code, :validated_eval_string, 3, [file: 'lib/code.ex', line: 404]}] expected_stacktrace = [
{:elixir_eval, :__FILE__, 1, [file: 'file.ex', line: 1]}
]
assert_receive {:runtime_evaluation_response, :code_1, assert_receive {:runtime_evaluation_response, :code_1,
{:error, :error, %CompileError{}, ^expected_stacktrace}, %{code_error: nil}} {:error, :error, %CompileError{}, ^expected_stacktrace}, %{code_error: nil}}
@ -169,7 +174,8 @@ defmodule Livebook.Runtime.EvaluatorTest do
expected_stacktrace = [ expected_stacktrace = [
{Livebook.EvaluatorTest.Stacktrace.Math, :bad_math, 0, [file: 'nofile', line: 3]}, {Livebook.EvaluatorTest.Stacktrace.Math, :bad_math, 0, [file: 'nofile', line: 3]},
{Livebook.EvaluatorTest.Stacktrace.Cat, :meow, 0, [file: 'nofile', line: 10]} {Livebook.EvaluatorTest.Stacktrace.Cat, :meow, 0, [file: 'nofile', line: 10]},
{:elixir_eval, :__FILE__, 1, [file: 'nofile', line: 15]}
] ]
# Note: evaluating module definitions is relatively slow, so we use a higher wait timeout. # Note: evaluating module definitions is relatively slow, so we use a higher wait timeout.