Skip to content

Commit

Permalink
Elixir 1.15 (#898)
Browse files Browse the repository at this point in the history
* bump elixir_sense to 1.15 compatible version

* update dialyxir to 1.3.0

* Add support for def cli in debugger

* fix warnings

* pass root option correctly

* make sure debug info is preserved

* add debugger dep to extra apps

I'm not sure this is needed

* add todo

* temporary workaround for broken logger registrations

* add workarounds for prunning code paths

* fix typo

* add missing app

apply change from upstream

* make hover work with new elixir_sense version

* readd dir param

* change dialyzer sha

* test valid formatter config

* fix infocation

* fix test

* make sure doc chunks are generated

* remove not needed tests

* fix test

* add logger handler

* fix tests

* insert needed requires as additional text edits

skip completions that would need to alter imports

* reinstall log handler after loading config

* resolve todo

* address todo

* fix logger format

* run formatter

* drop support for elixir 1.12

* remove pre 1.13 code

* add missing app

* fix function invocation

* remove unused code

* logger registration in tests

* Revert "remove unused code"

This reverts commit b0a3bb0.

* Revert "remove pre 1.13 code"

This partially reverts commit 5164b2b.

* port elixir changes related to multiletter sigils

* address todo

* fix flaky test

* fix flaky tests

fix logger config reset in build

* format

* fix crash in completions

* fix crash in hover

* remove sourceror dependency

it proved to be problematic

* do not start erlang debugger

* add version check

* do not call mix local on 1.15

* run formatter
  • Loading branch information
lukaszsamson authored Jun 15, 2023
1 parent cb2bbf0 commit bd3d3bb
Show file tree
Hide file tree
Showing 44 changed files with 580 additions and 364 deletions.
8 changes: 0 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ jobs:
fail-fast: false
matrix:
include:
- elixir: 1.12.x
otp: 22.x
- elixir: 1.12.x
otp: 23.x
- elixir: 1.13.x
otp: 22.x
- elixir: 1.13.x
Expand Down Expand Up @@ -56,10 +52,6 @@ jobs:
fail-fast: false
matrix:
include:
- elixir: 1.12.x
otp: 22.x
- elixir: 1.12.x
otp: 23.x
- elixir: 1.13.x
otp: 22.x
- elixir: 1.13.x
Expand Down
6 changes: 0 additions & 6 deletions .github/workflows/release-asset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ jobs:
otp-version: '23.3'
- elixir-version: '1.13'
otp-version: '22.3'
- elixir-version: '1.12'
otp-version: '24.3'
- elixir-version: '1.12'
otp-version: '23.3'
- elixir-version: '1.12'
otp-version: '22.3'
default: true

steps:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.14.6
0.15.0
8 changes: 8 additions & 0 deletions apps/elixir_ls_debugger/lib/debugger/cli.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@ defmodule ElixirLS.Debugger.CLI do
alias ElixirLS.Debugger.{Output, Server}

def main do
Application.put_env(:elixir, :ansi_enabled, false)
WireProtocol.intercept_output(&Output.debuggee_out/1, &Output.debuggee_err/1)
Launch.start_mix()

if Version.match?(System.version(), ">= 1.15.0-dev") do
# make sue that debugger modules are in code path
# without starting the app
Mix.ensure_application!(:debugger)
end

{:ok, _} = Application.ensure_all_started(:elixir_ls_debugger, :permanent)

Output.debugger_console("Started ElixirLS Debugger v#{Launch.debugger_version()}")
Expand Down
26 changes: 23 additions & 3 deletions apps/elixir_ls_debugger/lib/debugger/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -939,14 +939,34 @@ defmodule ElixirLS.Debugger.Server do
# https://github.com/elixir-lang/elixir/blob/v1.14.4/lib/mix/lib/mix/cli.ex#L158
# we assume that mix is already started and has archives and tasks loaded
Launch.reload_mix_env_and_target()
Launch.load_mix_exs()
{task, task_args} = Launch.get_task(List.wrap(task) ++ task_args)
Launch.maybe_change_env_and_target(task)

Mix.ProjectStack.post_config(build_path: ".elixir_ls/debugger/build")

Mix.ProjectStack.post_config(
test_elixirc_options: [
docs: true,
debug_info: true
]
)

Mix.ProjectStack.post_config(prune_code_paths: false)

Code.put_compiler_option(:docs, true)
Code.put_compiler_option(:debug_info, true)

args = List.wrap(task) ++ task_args
Launch.load_mix_exs(args)
project = Mix.Project.get()
{task, task_args} = Launch.get_task(args, project)
Launch.maybe_change_env_and_target(task, project)

Output.debugger_console("Running with MIX_ENV: #{Mix.env()} MIX_TARGET: #{Mix.target()}\n")

Mix.Task.run("loadconfig")

# make sure ANSI is disabled
Application.put_env(:elixir, :ansi_enabled, false)

unless is_list(task_args) and "--no-compile" in task_args do
case Mix.Task.run("compile", ["--ignore-module-conflict"]) do
{:error, _} ->
Expand Down
17 changes: 11 additions & 6 deletions apps/elixir_ls_debugger/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ defmodule ElixirLS.Debugger.Mixfile do
|> File.read!()
|> String.trim()

@dep_versions __DIR__
|> Path.join("../../dep_versions.exs")
|> Code.eval_file()
|> elem(0)

def project do
[
app: :elixir_ls_debugger,
Expand All @@ -14,7 +19,7 @@ defmodule ElixirLS.Debugger.Mixfile do
config_path: "../../config/config.exs",
deps_path: "../../deps",
lockfile: "../../mix.lock",
elixir: ">= 1.12.0",
elixir: ">= 1.13.0",
build_embedded: false,
start_permanent: true,
build_per_environment: false,
Expand All @@ -27,16 +32,16 @@ defmodule ElixirLS.Debugger.Mixfile do
end

def application do
[mod: {ElixirLS.Debugger, []}, extra_applications: [:mix]]
[mod: {ElixirLS.Debugger, []}, extra_applications: []]
end

defp deps do
[
{:elixir_sense,
github: "elixir-lsp/elixir_sense", ref: "71efd1e2efbac43e6c98c525cc879ddd747ac62e"},
{:elixir_sense, github: "elixir-lsp/elixir_sense", ref: @dep_versions[:elixir_sense]},
{:elixir_ls_utils, in_umbrella: true},
{:jason_v, github: "elixir-lsp/jason", ref: "c81537e2a5e1acacb915cf339fe400357e3c2aaa"},
{:dialyxir_vendored, github: "elixir-lsp/dialyxir", ref: "896fa45817c6a1be8ec408577c88ab52c27f6851", runtime: false}
{:jason_v, github: "elixir-lsp/jason", ref: @dep_versions[:jason_v]},
{:dialyxir_vendored,
github: "elixir-lsp/dialyxir", ref: @dep_versions[:dialyxir_vendored], runtime: false}
]
end
end
9 changes: 7 additions & 2 deletions apps/elixir_ls_debugger/test/debugger_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -1729,8 +1729,13 @@ defmodule ElixirLS.Debugger.ServerTest do
Server.receive_packet(server, request(6, "threads", %{}))
assert_receive(response(_, 6, "threads", %{"threads" => threads}), 1_000)

assert Enum.find(threads, &(&1["id"] == thread_id))["name"] ==
":proc_lib.init_p/5 #{:erlang.pid_to_list(pid)}"
if Version.match?(System.version(), ">= 1.15.0-dev") do
assert Enum.find(threads, &(&1["id"] == thread_id))["name"] ==
"Task.Supervised.noreply/4 #{:erlang.pid_to_list(pid)}"
else
assert Enum.find(threads, &(&1["id"] == thread_id))["name"] ==
":proc_lib.init_p/5 #{:erlang.pid_to_list(pid)}"
end

send(pid, :done)

Expand Down
6 changes: 6 additions & 0 deletions apps/elixir_ls_debugger/test/test_helper.exs
Original file line number Diff line number Diff line change
@@ -1,2 +1,8 @@
Application.put_env(:elixir_ls_debugger, :test_mode, true)
ExUnit.start(exclude: [pending: true])

if Version.match?(System.version(), ">= 1.15.0-dev") do
# make sue that debugger modules are in code path
# without starting the app
Mix.ensure_application!(:debugger)
end
108 changes: 77 additions & 31 deletions apps/elixir_ls_utils/lib/launch.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ defmodule ElixirLS.Utils.Launch do
@compiled_otp_version System.otp_release()

def start_mix do
if Version.match?(System.version(), "< 1.15.0-dev") do
# since 1.15 Mix.start() calls append_archives() and append_paths()
Mix.Local.append_archives()
Mix.Local.append_paths()
end

Mix.start()
Mix.Local.append_archives()
Mix.Local.append_paths()

true = Mix.Hex.ensure_installed?(false)
# when running via mix install script mix starts and stops hex
# we need to make sure it's started
Expand All @@ -23,7 +28,7 @@ defmodule ElixirLS.Utils.Launch do

load_dot_config()

# as of 1.14 mix supports two environment variables MIX_QUIET and MIX_DEBUG
# as of 1.15 mix supports two environment variables MIX_QUIET and MIX_DEBUG
# that are not important for our use cases

:ok
Expand Down Expand Up @@ -71,25 +76,23 @@ defmodule ElixirLS.Utils.Launch do
end
end

def load_mix_exs() do
def load_mix_exs(args) do
file = ElixirLS.Utils.MixfileHelpers.mix_exs()

if File.regular?(file) do
# TODO elixir 1.15 calls
# Mix.ProjectStack.post_config(state_loader: {:cli, List.first(args)})
# added in https://github.com/elixir-lang/elixir/commit/9e07da862784ac7d18a1884141c49ab049e61691
# def cli
# do we need that?
if Version.match?(System.version(), ">= 1.15.0-dev") do
Mix.ProjectStack.post_config(state_loader: {:cli, List.first(args)})
end

old_undefined = Code.get_compiler_option(:no_warn_undefined)
Code.put_compiler_option(:no_warn_undefined, :all)
Code.compile_file(file)
Code.put_compiler_option(:no_warn_undefined, old_undefined)
end
end

# TODO add support for def cli
def get_task(["-" <> _ | _]) do
task = "mix #{Mix.Project.config()[:default_task]}"
def get_task(["-" <> _ | _], project) do
task = "mix #{default_task(project)}"

Mix.shell().error(
"** (Mix) Mix only recognizes the options --help and --version.\n" <>
Expand All @@ -100,31 +103,38 @@ defmodule ElixirLS.Utils.Launch do
exit({:shutdown, 1})
end

def get_task([h | t]) do
def get_task([h | t], _project) do
{h, t}
end

def get_task([]) do
case Mix.Project.get() do
nil ->
Mix.shell().error(
"** (Mix) \"mix\" with no arguments must be executed in a directory with a mix.exs file"
)
def get_task([], nil) do
Mix.shell().error(
"** (Mix) \"mix\" with no arguments must be executed in a directory with a mix.exs file"
)

display_usage()
exit({:shutdown, 1})
display_usage()
exit({:shutdown, 1})
end

_ ->
{Mix.Project.config()[:default_task], []}
def get_task([], project) do
{default_task(project), []}
end

defp default_task(project) do
if function_exported?(project, :cli, 0) do
project.cli()[:default_task] || "run"
else
# TODO: Deprecate default_task in v1.19
Mix.Project.config()[:default_task] || "run"
end
end

def maybe_change_env_and_target(task) do
def maybe_change_env_and_target(task, project) do
task = String.to_atom(task)
config = Mix.Project.config()

env = preferred_cli_env(task, config)
target = preferred_cli_target(task, config)
env = preferred_cli_env(project, task, config)
target = preferred_cli_target(project, task, config)
env && Mix.env(env)
target && Mix.target(target)

Expand All @@ -133,23 +143,59 @@ defmodule ElixirLS.Utils.Launch do
end
end

def preferred_cli_env(task) when is_atom(task) or is_binary(task) do
case Mix.Task.get(task) do
nil ->
nil

module ->
case List.keyfind(module.__info__(:attributes), :preferred_cli_env, 0) do
{:preferred_cli_env, [setting]} ->
IO.warn(
"""
setting @preferred_cli_env is deprecated inside Mix tasks.
Please remove it from #{inspect(module)} and set your preferred environment in mix.exs instead:
def cli do
[
preferred_envs: [docs: "docs"]
]
end
""",
[]
)

setting

_ ->
nil
end
end
end

defp reload_project() do
if project = Mix.Project.pop() do
%{name: name, file: file} = project
Mix.Project.push(name, file)
end
end

defp preferred_cli_env(task, config) do
if System.get_env("MIX_ENV") do
# TODO: Deprecate preferred_cli_env in v1.19
defp preferred_cli_env(project, task, config) do
if function_exported?(project, :cli, 0) || System.get_env("MIX_ENV") do
nil
else
config[:preferred_cli_env][task] || Mix.Task.preferred_cli_env(task)
config[:preferred_cli_env][task] || preferred_cli_env(task)
end
end

defp preferred_cli_target(task, config) do
config[:preferred_cli_target][task]
# TODO: Deprecate preferred_cli_target in v1.19
defp preferred_cli_target(project, task, config) do
if function_exported?(project, :cli, 0) || System.get_env("MIX_TARGET") do
nil
else
config[:preferred_cli_target][task]
end
end

defp display_usage do
Expand Down
14 changes: 3 additions & 11 deletions apps/elixir_ls_utils/lib/minimum_version.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,11 @@ defmodule ElixirLS.Utils.MinimumVersion do
end

def check_elixir_version do
if Version.match?(System.version(), ">= 1.12.0") do
otp_release = String.to_integer(System.otp_release())

if Version.match?(System.version(), "< 1.13.0") and otp_release == 24 do
# see https://github.com/elixir-lang/elixir/pull/11158#issuecomment-981583298
{:error,
"Elixir 1.12 is not supported on OTP 24. (Currently running v#{System.version()} on OTP #{otp_release})"}
else
:ok
end
if Version.match?(System.version(), ">= 1.13.0") do
:ok
else
{:error,
"Elixir versions below 1.12.0 are not supported. (Currently running v#{System.version()})"}
"Elixir versions below 1.13.0 are not supported. (Currently running v#{System.version()})"}
end
end
end
Loading

0 comments on commit bd3d3bb

Please sign in to comment.