Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: spitfire #368

Merged
merged 4 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 33 additions & 25 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,90 +7,97 @@ on:
jobs:
tests:
runs-on: ${{matrix.os}}
name: Test (${{matrix.os}})
name: Test (${{matrix.os}}) - spitfire=${{matrix.spitfire}}

strategy:
matrix:
spitfire: [0, 1]
os:
- ubuntu-latest
- macos-14

steps:
- uses: actions/checkout@v4
- uses: jdx/mise-action@v2
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main

- uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ matrix.os }}-mix-${{ hashFiles('**/.mise.toml') }}-${{ hashFiles('**/mix.lock') }}
key: ${{ matrix.os }}-mix-${{ hashFiles('**/flake.nix') }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ matrix.os }}-mix-${{ hashFiles('**/.mise.toml') }}-
${{ matrix.os }}-mix-${{ hashFiles('**/flake.nix') }}-

- name: Install Dependencies
run: mix deps.get
run: nix develop --command bash -c 'mix deps.get'

- name: Start EPMD
run: epmd -daemon
run: nix develop --command bash -c 'epmd -daemon'

- name: Compile
env:
MIX_ENV: test
run: mix compile
run: nix develop --command bash -c 'mix compile'

- name: remove tmp dir
run: rm -rf tmp

- name: Run Tests
run: elixir --erl '-kernel prevent_overlapping_partitions false' -S mix test --max-cases 1
env:
NEXTLS_SPITFIRE_ENABLED: ${{ matrix.spitfire }}
run: nix develop --command bash -c "elixir --erl '-kernel prevent_overlapping_partitions false' -S mix test --max-cases 1"

formatter:
runs-on: ubuntu-latest
name: Formatter

steps:
- uses: actions/checkout@v4
- uses: jdx/mise-action@v2
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- uses: actions/cache@v4
with:
path: |
deps
_build
key: ${{ runner.os }}-mix-${{ hashFiles('**/.mise.toml') }}-${{ hashFiles('**/mix.lock') }}
key: ${{ runner.os }}-mix-${{ hashFiles('**/flake.nix') }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-${{ hashFiles('**/.mise.toml') }}-
${{ runner.os }}-mix-${{ hashFiles('**/flake.nix') }}-

- name: Install Dependencies
run: mix deps.get
run: nix develop --command bash -c 'mix deps.get'

- name: Run Formatter
run: mix format --check-formatted
run: nix develop --command bash -c 'mix format --check-formatted'

dialyzer:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: jdx/mise-action@v2
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main

# Don't cache PLTs based on mix.lock hash, as Dialyzer can incrementally update even old ones
# Cache key based on Elixir & Erlang version (also useful when running in matrix)
- name: Restore PLT cache
uses: actions/cache/restore@v4
id: plt_cache
with:
key: ${{ runner.os }}-mix-${{ hashFiles('**/.mise.toml') }}-${{ hashFiles('**/mix.lock') }}
key: ${{ runner.os }}-mix-${{ hashFiles('**/flake.nix') }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ runner.os }}-mix-${{ hashFiles('**/.mise.toml') }}-
${{ runner.os }}-mix-${{ hashFiles('**/flake.nix') }}-
path: |
priv/plts

- name: Install Dependencies
run: mix deps.get
run: nix develop --command bash -c 'mix deps.get'

# Create PLTs if no cache was found
- name: Create PLTs
if: steps.plt_cache.outputs.cache-hit != 'true'
run: mix dialyzer --plt
run: nix develop --command bash -c 'mix dialyzer --plt'

# By default, the GitHub Cache action will only save the cache if all steps in the job succeed,
# so we separate the cache restore and save steps in case running dialyzer fails.
Expand All @@ -99,12 +106,12 @@ jobs:
if: steps.plt_cache.outputs.cache-hit != 'true'
id: plt_cache_save
with:
key: ${{ runner.os }}-mix-${{ hashFiles('**/.mise.toml') }}-${{ hashFiles('**/mix.lock') }}
key: ${{ runner.os }}-mix-${{ hashFiles('**/flake.nix') }}-${{ hashFiles('**/mix.lock') }}
path: |
priv/plts

- name: Run dialyzer
run: mix dialyzer --format github
run: nix develop --command bash -c 'mix dialyzer --format github'

release-test:
runs-on: ${{matrix.os.name}}
Expand All @@ -122,23 +129,24 @@ jobs:

steps:
- uses: actions/checkout@v4
- uses: jdx/mise-action@v2
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- uses: actions/cache@v4
with:
path: |
deps
key: ${{ matrix.os.name }}-mix-prod-${{ hashFiles('**/.mise.toml') }}-${{ hashFiles('**/mix.lock') }}
key: ${{ matrix.os.name }}-mix-prod-${{ hashFiles('**/flake.nix') }}-${{ hashFiles('**/mix.lock') }}
restore-keys: |
${{ matrix.os.name }}-mix-prod-${{ hashFiles('**/.mise.toml') }}-
${{ matrix.os.name }}-mix-prod-${{ hashFiles('**/flake.nix') }}-

- name: Install Dependencies
run: mix deps.get --only prod
run: nix develop --command bash -c 'mix deps.get --only prod'

- name: Release
env:
MIX_ENV: prod
BURRITO_TARGET: ${{ matrix.os.target }}
run: mix release
run: nix develop --command bash -c 'mix release'

nix-build:
strategy:
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: jdx/mise-action@v2
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main
- run: chmod +x "$PWD/bin/7z"
- run: brew install 7zip
- run: mix local.hex --force
Expand Down
5 changes: 2 additions & 3 deletions .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
KERL_BUILD_DOCS = "yes"

[tools]
erlang = "26.1.2"
elixir = "1.15.7-otp-26"
erlang = "26.2.2"
elixir = "ref:52eaf1456182d5d6cce22a4f5c3f6ec9f4dcbfd9"
zig = "0.11.0"

31 changes: 27 additions & 4 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
inputs = {nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";};
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};

nixConfig = {
extra-substituters = ["https://elixir-tools.cachix.org"];
Expand All @@ -19,10 +21,23 @@
lib.genAttrs (builtins.attrNames burritoExe) (system: let
pkgs = nixpkgs.legacyPackages.${system};
beamPackages = pkgs.beam_minimal.packages.erlang_26;
elixir = beamPackages.elixir_1_15;
beam = fetchTarball beams.${system};
rawmusl = musls.${system};
musl = lib.optionals nixpkgs.legacyPackages.${system}.stdenv.isLinux (builtins.fetchurl (nixpkgs.lib.attrsets.getAttrs ["url" "sha256"] musls.${system}));
otp = (pkgs.beam.packagesWith beamPackages.erlang).extend (final: prev: {
elixir_1_17 = prev.elixir_1_16.override {
rev = "52eaf1456182d5d6cce22a4f5c3f6ec9f4dcbfd9";
# You can discover this using Trust On First Use by filling in `lib.fakeHash`
sha256 = "sha256-fOsV+jVIzsa38hQDvAjhUqee36nt8kG6AOpOQJnSZ74=";
version = "1.17.0-dev";
};

elixir = final.elixir_1_17;
# This will get upstreamed into nix-beam-flakes at some point
rebar = prev.rebar.overrideAttrs (_old: {doCheck = false;});
rebar3 = prev.rebar3.overrideAttrs (_old: {doCheck = false;});
});
elixir = otp.elixir;
in
f {inherit system pkgs beamPackages elixir beam rawmusl musl;});

Expand Down Expand Up @@ -100,7 +115,7 @@
src = self.outPath;
inherit version elixir;
pname = "next-ls-deps";
hash = "sha256-U5d8DftG0i1c4JiutUentNlRsefFgR4Mfc3eKqnKR3U=";
hash = "sha256-RYPweYD1GD0D6A7ZkrtD3h7arCVimdStcOhrrlHFrnw=";
mixEnv = "prod";
};

Expand Down Expand Up @@ -149,7 +164,15 @@
beamPackages,
elixir,
...
}: {
}: let
aliased_7zz = pkgs.symlinkJoin {
name = "7zz-aliased";
paths = [pkgs._7zz];
postBuild = ''
ln -s ${pkgs._7zz}/bin/7zz $out/bin/7z
'';
};
in {
default = pkgs.mkShell {
# The Nix packages provided in the environment
packages = [
Expand Down
42 changes: 27 additions & 15 deletions lib/next_ls/document_symbol.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,35 @@ defmodule NextLS.DocumentSymbol do
alias GenLSP.Structures.Position
alias GenLSP.Structures.Range

# we set the literal encoder so that we can know when atoms and strings start and end
# this makes it useful for knowing the exact locations of struct field definitions
@spec fetch(text :: String.t()) :: list(DocumentSymbol.t())
def fetch(text) do
text
|> Code.string_to_quoted!(
literal_encoder: fn literal, meta ->
if is_atom(literal) or is_binary(literal) do
{:ok, {:__literal__, meta, [literal]}}
else
{:ok, literal}
end
end,
unescape: false,
token_metadata: true,
columns: true
)
ast =
case NextLS.Parser.parse(
text,
# we set the literal encoder so that we can know when atoms and strings start and end
# this makes it useful for knowing the exact locations of struct field definitions
literal_encoder: fn literal, meta ->
if is_atom(literal) or is_binary(literal) do
{:ok, {:__literal__, meta, [literal]}}
else
{:ok, literal}
end
end,
unescape: false,
token_metadata: true,
columns: true
) do
{:error, ast, _errors} ->
ast

{:error, _} ->
raise "Failed to parse!"

{:ok, ast} ->
ast
end

ast
|> walker(nil)
|> List.wrap()
end
Expand Down
84 changes: 44 additions & 40 deletions lib/next_ls/helpers/ast_helpers.ex
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ defmodule NextLS.ASTHelpers do
defp postwalk(ast, acc, _module), do: {ast, acc}

defp ast_from_file(file) do
file |> File.read!() |> Code.string_to_quoted!(columns: true)
file |> File.read!() |> NextLS.Parser.parse!(columns: true)
end
end

Expand All @@ -99,53 +99,57 @@ defmodule NextLS.ASTHelpers do
"""

def extract_alias_range(code, {start, stop}, ale) do
lines =
code
|> String.split("\n")
|> Enum.map(&String.split(&1, ""))
|> Enum.slice((start.line - 1)..(stop.line - 1))

code =
if start.line == stop.line do
[line] = lines

line
|> Enum.slice(start.col..stop.col)
|> Enum.join()
else
[first | rest] = lines
first = Enum.drop(first, start.col)

[last | rest] = Enum.reverse(rest)

length = Enum.count(last)
last = Enum.drop(last, -(length - stop.col - 1))

Enum.map_join([first | Enum.reverse([last | rest])], "\n", &Enum.join(&1, ""))
end

{_, range} =
code
|> Code.string_to_quoted!(columns: true, column: start.col, token_metadata: true)
|> Macro.prewalk(nil, fn ast, range ->
range =
case ast do
{:__aliases__, meta, aliases} ->
if ale == List.last(aliases) do
{{meta[:line] + start.line - 1, meta[:column]},
{meta[:last][:line] + start.line - 1, meta[:last][:column] + String.length(to_string(ale)) - 1}}
else
|> NextLS.Parser.parse!(columns: true, token_metadata: true)
|> Macro.prewalk(nil, fn
ast, nil = range ->
range =
case ast do
{:__aliases__, meta, aliases} ->
if ale == List.last(aliases) do
found_range =
{{meta[:line], meta[:column]},
{meta[:last][:line], meta[:last][:column] + String.length(to_string(ale)) - 1}}

if NextLS.ASTHelpers.inside?({{start.line, start.col}, {stop.line, stop.col}}, found_range) do
found_range
else
range
end
else
range
end

_ ->
range
end
end

_ ->
range
end
{ast, range}

{ast, range}
ast, range ->
{ast, range}
end)

range
end
end

def inside?(outer, {{_, _}, {_, _}} = target) do
{{outer_startl, outer_startc}, {outer_endl, outer_endc}} = outer
{target_start, target_end} = target

Enum.all?([target_start, target_end], fn {line, col} ->
if outer_startl <= line and line <= outer_endl do
cond do
outer_startl < line and line < outer_endl -> true
outer_startl == line and outer_startc <= col -> true
outer_endl == line and col <= outer_endc -> true
true -> false
end
else
false
end
end)
end
end
Loading
Loading