Compare commits

..

142 commits

Author SHA1 Message Date
Roberto Aloi
7a4eccf14d Add support for linter-specific excluded_apps
Some checks failed
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / edb (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary:
We may want to disable a linter for a certain set of applications. This diff introduces such a mechanism:

```
[linters.my_linter]
exclude_apps = ["app_a", "app_2"]
```

Reviewed By: alanz

Differential Revision: D89658976

fbshipit-source-id: 78e1cf13ec22f1bf7ed1b6df6892cdad5ca2dfe5
2025-12-23 03:53:02 -08:00
Roberto Aloi
4bba415bc1 Fix diagnostic name
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: Missed during the original rename.

Reviewed By: alanz

Differential Revision: D89460380

fbshipit-source-id: 60446aa3f505d635ad5ddc842b2d420c24f0a9d2
2025-12-22 09:17:24 -08:00
Roberto Aloi
6456f325c3 Ignore buck-out in test_projects
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary: So that version control systems do not try to publish the directory.

Reviewed By: alanz

Differential Revision: D89550389

fbshipit-source-id: d60646ddd4e8f0ae443673dac3c49efbac60dba7
2025-12-19 08:58:10 -08:00
Roberto Aloi
5c7cfae09d Only enable Buck2 project model tests if feature is enabled
Summary:
We already have a feature to understand if Buck2 is enabled or not. Let's use that one instead of a constant.

This change has no effect anyway since the only two use cases are currently marked as "ignored".

Also remove the extra check inside the helper (we already do it in both tests).

Reviewed By: alanz

Differential Revision: D89549782

fbshipit-source-id: 82e5bbf00c463dca3f4937d2d2a12d16aebc3c19
2025-12-19 08:58:10 -08:00
Alan Zimmerman
220acfd4f7 Back out "Allow project discovery for OTP"
Summary: It breaks navigation to stdlib

Reviewed By: TD5

Differential Revision: D89552844

fbshipit-source-id: 676af5f520d9189f98828b4364b0b1665531b245
2025-12-19 08:49:54 -08:00
Roberto Aloi
fc09ff94fd Enable buck2 tests on GitHub
Summary:
The test projects are now standalone, so the Buck2 tests can be enabled in CI.

Two major fixes to the tests:

* Use the project directory to calculate the project root (there's no `.buckconfig` for the ELP crate as a whole in OSS)
* Fix expectations for the Buck2 errors (no URL in OSS)

Reviewed By: alanz

Differential Revision: D89547047

fbshipit-source-id: 76fa8bcc1fadabbeb9ea59245d36d2aacd98a023
2025-12-19 07:43:01 -08:00
Alan Zimmerman
8e82f1cee4 Fix codegen_test test project for new buck root
Summary: As title

Reviewed By: TheGeorge

Differential Revision: D89543670

fbshipit-source-id: 8d4a417a58950ad9f9d8877839561f407d0e9cc0
2025-12-19 04:09:00 -08:00
Facebook Community Bot
8cb6ac7620
Re-sync with internal repository (#144)
The internal and external repositories are out of sync. This Pull Request attempts to brings them back in sync by patching the GitHub repository. Please carefully review this patch. You must disable ShipIt for your project in order to merge this pull request. DO NOT IMPORT this pull request. Instead, merge it directly on GitHub using the MERGE BUTTON. Re-enable ShipIt after merging.

fbshipit-source-id: 39bc64c1a96888b1034f7807ced9b7b2365df04e
2025-12-19 10:51:11 +00:00
Roberto Aloi
8b4c533527 Convert EDoc syntax to plain comments in codegen_test_SUITE
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
Convert old EDoc style syntax (%%% doc, end) in test suite to plain
comments. EDoc documentation is unnecessary in test suites.

Differential Revision: D89526339

fbshipit-source-id: 0111f2ded79a7e802d29b95d6b79889e0a55af32
2025-12-18 23:41:12 -08:00
Roberto Aloi
b12cf72c7e Standalone Buck2 setup for test_projects
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: We want to enable Buck2 tests on GitHub. This requires a bit of groundwork.

Reviewed By: michalmuskala

Differential Revision: D88959148

fbshipit-source-id: e5f88f561e061635aae05c4e3bc22382771a8908
2025-12-18 14:47:07 -08:00
Alan Zimmerman
ce0125dec9 1/n: bound var in match: detect problem
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
In non-test Erlang code, the following is almost always intended as assignment of a value to the LHS variable

```
Var = expr()
```

It is actually a match, and may fail if `Var` is already bound, and the new value differs from the old.

This diff introduces a diagnostic to warn of this case.

Reviewed By: robertoaloi

Differential Revision: D89374198

fbshipit-source-id: 19dcee50ad6e71d0a606a0eb6cf548b7194d61e6
2025-12-18 07:05:33 -08:00
Alan Zimmerman
d7b1c561ad Fix GH CI for OTP 26
Summary: As title.

Reviewed By: robertoaloi

Differential Revision: D89461312

fbshipit-source-id: 3c0c75da6ccd00735d3f444b123b0bab222d0980
2025-12-18 05:36:31 -08:00
Roberto Aloi
3804bd1706 Enable undefined_function linter in CI (prod only)
Summary:
The linter is enabled by default in ELP, and warnings appear in the IDE.
But the same linter is not explicitly added to the CI configuration, so warnings are not reported on diffs or in Contlint.

This diff enables the linter, aligning the IDE and the CI experience. It also makes it possible to track violations via ContLint.

We exclude known false positives via config.

Ideally, we would like to report undefined functions in all files, but there are too many false positives in test files to do so.
This is often due to mocked modules and test suite cleverness. We can revisit this decision in the future. See T249044930 for details.

We disable the linter for tests both in the default value (for the future) and the config (so we don't need to wait for a ELP release to land this change).

Reviewed By: alanz

Differential Revision: D89393641

fbshipit-source-id: bfb9ac760ba79566301087033af95bb805fdeaa0
2025-12-18 03:37:42 -08:00
Roberto Aloi
439ebade1b Rename edoc linter into old_edoc_syntax
Summary: The old name was too generic, and could be mis-interepreted as an EDoc linter (a linter that verifies EDoc syntax). By aligning the name of the linter with the actual diagnostic code, we make the intention more clear. No functional change.

Reviewed By: alanz

Differential Revision: D89374941

fbshipit-source-id: bf8518ed9602bdceca2fcbf3ddb00990f56af529
2025-12-18 03:37:42 -08:00
Roberto Aloi
54dd1089ed Do not run the old_edoc_syntax linter against test files by default
Summary:
Documentation is generally not produced for test files, so do not run the `old_edoc_syntax` linter for tests. If not, edoc references in tests should be converted to plain comments, not to `-moduledoc` or `-doc` attributes.

This behaviour can always be overwritten by setting the `severity` or the `include_tests` properties of the linter via config.

Reviewed By: alanz

Differential Revision: D89374552

fbshipit-source-id: 8a4299fcbd16a82f62efbc14f47fef46cd08fbc0
2025-12-18 03:37:42 -08:00
Alan Zimmerman
fa05043043 Allow project discovery for OTP (#141)
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
Some clients, such as emacs eglot, do their own project discovery when a new file is opened, even from the target of a go to definition.

They then launch a fresh ELP server if they determine a different project root.

In the ELP server setup we preconfigure the OTP project root as known, but with a project manifest of None. This means go to def into an OTP file ends up with an uninitialized project in the new server.

This diff makes it so that if the project root is known, but has no project manifest, we do discovery on that root.

Pull Request resolved: https://github.com/whatsapp/erlang-language-platform/pull/141

Reviewed By: robertoaloi

Differential Revision: D89169465

Pulled By: alanz

fbshipit-source-id: db180d67df98fd1f1fd61a53a93f9adfa9e93ebd
2025-12-17 09:53:03 -08:00
Victor Lanvin
79c33480c5 Support for OTP version specific tests
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
Remove the tag `OTPVersionDependent` which created one expected result per OTP version per snapshot.

Instead, use `OTPXXOnly` (where `XX` is a version number), that skips checks for OTP versions that are not `XX`.

In practice, it's used as `OTP27Only` for now.

Reviewed By: michalmuskala, TD5

Differential Revision: D89378687

fbshipit-source-id: 0421622d825ac4e8f393d32529c01eb17577b5e5
2025-12-17 08:54:32 -08:00
Alan Zimmerman
7057624c73 elp lint: print diagnostics in the case we are not streaming and not applying a fix
Summary:
Fix two bugs for `--no-stream` for `elp lint`

1. args.skip_stream_print() now skips if either the flag is set, or `--apply-fixes` is set
2. When we are not streaming, and also not applyiing fixes, print the diagnostics

Reviewed By: robertoaloi

Differential Revision: D89369072

fbshipit-source-id: 2279aca861fb09c5b33adb0000e3a58821026064
2025-12-17 06:36:56 -08:00
Alan Zimmerman
4a051d1af8 10/n: rename module: in defines RHS
Summary: Add a test demonstrating that the module rename happens in `.hrl` files too

Reviewed By: TheGeorge

Differential Revision: D89053579

fbshipit-source-id: f999484c08a5c33c76986156c10a2f6a7d34fc52
2025-12-17 06:00:04 -08:00
Alan Zimmerman
91a0d968db 9/n: rename module: remote calls in original module
Summary:
Simplify the rename module logic to use the standard approach, find usages, rename each of them.

And in the process ensure that remote calls in the module being renamed are also renamed.

Reviewed By: robertoaloi

Differential Revision: D88947976

fbshipit-source-id: c703be8392b7ac634ced2c45d8553d33882d460b
2025-12-17 06:00:04 -08:00
Alan Zimmerman
cc0a9c26d5 8/n: rename module: well known function arguments
Summary:
Certain functions are known to take a module name as an argument.  We already have a list of those that correspond to referencing a function as an MFA, in `to_def.rs`.  We extend this with some other examples, and check for renaming them too as part of the module rename.

The list is currently incommplete, and can be filled out based on usage. A future diff may look at ways of generating it from `-spec` information.

Reviewed By: robertoaloi

Differential Revision: D88943301

fbshipit-source-id: 05c67a108b1dc5b64f4353872427361fd039171f
2025-12-17 06:00:04 -08:00
Alan Zimmerman
83d5b4dfd0 7/n: rename module: check module name in a call
Summary:
When identifying a call from a reference, we start from the ast token for the module name, and ascend the ast until we find a call.

But up to now we have not checked that the module we started from is the module part of the call MFA.

This diff adds that check.

Reviewed By: robertoaloi

Differential Revision: D88934411

fbshipit-source-id: 81a57520ec834210fcea8fd6920653cc45f9890c
2025-12-17 06:00:04 -08:00
Alan Zimmerman
9015d80659 6/n: rename module: external fun reference
Summary: A module name can occur in an external fun. Rename it too.

Reviewed By: robertoaloi

Differential Revision: D88849514

fbshipit-source-id: e715628a6fbfe419cd56761fe62b43d3b68ecde4
2025-12-17 06:00:04 -08:00
Alan Zimmerman
8997372e1a 5/n: rename module: move original file
Summary:
The final step in renaming a module.  Move the old file, and apply the needed edits to it.

This diff also simplifies the mechanics of the rename, to be more general and in line with other renames, by iterating over usages of the module, rather than ad-hoc checks for things that may be needed.

It is still ad-hoc, in the sense that it only looks for call-like things at the moment (fully qualified calls and types). Other usages will come in later diffs

Reviewed By: robertoaloi

Differential Revision: D87861050

fbshipit-source-id: d393638b310a257f51151fc3caf1b1445c856700
2025-12-17 06:00:04 -08:00
Alan Zimmerman
bef3dd15f2 4/n: rename module: exported type references
Summary: When renaming a module, rename all references to types within it

Reviewed By: robertoaloi

Differential Revision: D87860496

fbshipit-source-id: 2ac6bc52cecaef6802fcf9f181b638f81c556d67
2025-12-17 06:00:04 -08:00
Alan Zimmerman
56e66e2cd5 3/n: rename module: renaming function references
Summary:
Rename references to functions exported from a module when the module is renamed.

This requires fleshing out the infrastructure to deal with deleting files too.

Reviewed By: robertoaloi

Differential Revision: D87860436

fbshipit-source-id: b4d04eb0cfc6448a407fa8c3202ef3e4e088b7e8
2025-12-17 06:00:04 -08:00
Alan Zimmerman
a0e076cb17 2/n: rename module: simple rename works
Summary: First case, just rename the module

Reviewed By: robertoaloi

Differential Revision: D87860412

fbshipit-source-id: 0427f09bd2176778e0280b0f45f9331fa279f778
2025-12-17 06:00:04 -08:00
Alan Zimmerman
8ff602f1c3 1/n rename module, basics
Summary:
This diff stack introduces rename for a module. As this is a complex operation, it will be done in steps.

The first one is to put the basics in place
- check the new name is valid
- Improve rename test fixture to cope with added and renamed files

Reviewed By: robertoaloi

Differential Revision: D87860388

fbshipit-source-id: 1a240a5e0e5e61d5c128bca0423744f001b7b68d
2025-12-17 06:00:04 -08:00
Alan Zimmerman
4a83d0edde BE: extract bound_vars_by_function as a method for sema
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Summary:
The `mutable_variable` diagnostic processed bound variables organised by function.

We intend doing the same for more bound variable diagnostics, so as a precursor extract this a method we can call on `Semantic`

Reviewed By: TD5

Differential Revision: D89270590

fbshipit-source-id: 95a520d45e900c0a5c97fd8163cbaedbc15ca840
2025-12-17 01:32:35 -08:00
Alan Zimmerman
271065da03 BE: for a fold, track the macro definition for ctx.in_macro
Summary:
When folding with visible macros, we keep track of a macro stack, so we can decide how to process diagnostics within the body of a macro expansion.

To date we have simply stored the `HirIdx` of the macro call, so it can be retrieved and examined by anything that needs it.

But the thing we need when processing a macro is in fact what definition was expanded.  This diff adds it to the information stored for easy access.

It will be used in a subsequent diff.

Reviewed By: TD5

Differential Revision: D89269840

fbshipit-source-id: 7ed6212b658de91cdd3e20701edb51161966e8fa
2025-12-17 01:32:35 -08:00
Roberto Aloi
37b7c5e28e Introduce top-level test directory
Reviewed By: michalmuskala

Differential Revision: D89272460

fbshipit-source-id: 91eb93d7df55a1ca64fe2b05e21097daca3b6d33
2025-12-17 01:18:32 -08:00
Roberto Aloi
d4e14636b4 Do not run selected linters on tests by default
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Differential Revision: D89302965

fbshipit-source-id: 9b5c1d3c6402a6fea9f3fd5a6d93c2e49acba51e
2025-12-16 15:30:53 -08:00
Open Source Bot
b2ea905e7f Updating hashes
Summary:
GitHub commits:

020284a6e8
261ff05851
acdd3baf0a
b435fe91fa
a75b46bbbc
427330df23
fd2a5c46a7
e95090adb4
c28a092249
fab1e58dfd
848ddcedb2
270d39b2c3
65b11fc090
0f514eb389

Reviewed By: pranavcivi

fbshipit-source-id: 0c3453ad24a874db08fbc66cc4945f70c64d25d0
2025-12-16 11:27:09 -08:00
Facebook Community Bot
858b8e64ab
Re-sync with internal repository (#143)
The internal and external repositories are out of sync. This Pull Request attempts to brings them back in sync by patching the GitHub repository. Please carefully review this patch. You must disable ShipIt for your project in order to merge this pull request. DO NOT IMPORT this pull request. Instead, merge it directly on GitHub using the MERGE BUTTON. Re-enable ShipIt after merging.

fbshipit-source-id: a4e36831ac3939cb9a4881ca077b5f8c0d421104
2025-12-16 10:54:56 -08:00
Alan Zimmerman
271a52c37c honour --include-generated for elp ssr
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: As title

Reviewed By: michalmuskala, TD5

Differential Revision: D89292307

fbshipit-source-id: cbde669d57276b2aaa2c7365906e3ed86f15aec5
2025-12-16 09:08:25 -08:00
Roberto Aloi
ba4505e981 Do not run application_env linter on test suites
Reviewed By: alanz, TheGeorge, michalmuskala

Differential Revision: D89287769

fbshipit-source-id: 29618250ee6d75ede850603cb60c5e4d77e3ff06
2025-12-16 08:56:01 -08:00
Alan Zimmerman
d2da476882 Add test project for code gen
Summary:
ELP using buck is able to trigger rules that generate code, and load this generated code as part of the project.

This diff brings in a test project with an example of this process, for ensuring our support is sold.

Reviewed By: robertoaloi

Differential Revision: D88953198

fbshipit-source-id: b92cf86b556f5465b2a528895b4e56852630f82e
2025-12-16 02:03:43 -08:00
Victor Lanvin
166770cc92 Remove logic for --include-tests, opt-in tests
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
Remove all logic related to `--include-tests` in ELP for eqWAlizer.

Enable eqWAlizer on tests by default.

Reviewed By: michalmuskala

Differential Revision: D89049936

fbshipit-source-id: b3702ddcc8cdb9a3ced65ec6855918ea37b2a072
2025-12-15 03:16:34 -08:00
Roberto Aloi
b525eac0ea Pass range to fixes callback
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary: It is common for the `fixes` callback to act on the original match range. By making the matched range available to the callback, we avoid manually including the range in the linter-specific context.

Reviewed By: alanz

Differential Revision: D89048282

fbshipit-source-id: 01faa9842f04c34efb14a7d803cf5317794ea321
2025-12-12 06:17:31 -08:00
Victor Lanvin
2bd3d57d02 Clean-up old error messages
Summary:
Use new error message generation for callback type errors, add corresponding test

Cleanup old error message generation

Reviewed By: TD5

Differential Revision: D88941623

fbshipit-source-id: 262c2031c7d19ad2528ef63a5d73d146fd84d408
2025-12-12 06:08:41 -08:00
Roberto Aloi
eb5e0abbf8 Install Buck2 in OSS CI workflow
Summary: In preparation for enabling Buck2 tests on GitHub, we install the Buck2 binary.

Reviewed By: michalmuskala

Differential Revision: D89038926

fbshipit-source-id: 7e37c7e9ec143391e10eba8597df2b2aa9d55d0f
2025-12-12 04:22:36 -08:00
Alan Zimmerman
887d287c94 tweak elp parse-elp --severity output
Summary:
Apply the severity filter to the results before printing any information about them.

This prevents printing a module name that has no errors in it, and gives a correct count in the module diagnostic summary

Reviewed By: TD5

Differential Revision: D89043311

fbshipit-source-id: aa0c813314f32ca9c23d753c598974a1eb605390
2025-12-12 03:56:28 -08:00
Roberto Aloi
553c90d631 Bump OSS VS Code extension to 0.47.0
Summary:
Due to some [most likely transient infra issues](2013794095), the latest release was only partially published.

Bump the extension to trigger a new release.

Reviewed By: alanz

Differential Revision: D89024759

fbshipit-source-id: fce412fee451eb72246c121706108af3ac34d414
2025-12-12 03:02:33 -08:00
Alan Zimmerman
a16af7e9e2 Update emacs eglot instructions
Summary: Add a stanza to set the config so we get semantic highlighting of `dynamic()`, and types on hover.

Reviewed By: michalmuskala

Differential Revision: D88957646

fbshipit-source-id: 5be4d69fdcf02999b840081baae076b85f9a9260
2025-12-12 02:19:15 -08:00
Alan Zimmerman
0085fba772 Add --severity argument to elp parse-elp to limit output
Summary: As title.

Reviewed By: TD5

Differential Revision: D88963207

fbshipit-source-id: a8cc5ddfedcfa8063537e586ac086c8a0caac465
2025-12-12 01:38:41 -08:00
Victor Lanvin
babf61214c Bad occurrence typing with maps:foreach -- repro
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary: Occurrence typing doesn't take place in `maps:foreach` (and several other custom functions). Repro.

Reviewed By: michalmuskala

Differential Revision: D88949717

fbshipit-source-id: d6225a708f0c632d914c4ca38b1d789a3b077311
2025-12-11 07:25:42 -08:00
Roberto Aloi
7b0b29ae21 Temporarily ignore hierarchical_config tests
Summary:
The test is supposed to panic (and does so) when run with both Buck2 and rebar3.
Unfortunately, we are currently disabling the Buck2 tests on GitHub, which has the unfortunate consequence of not letting the test fail as expected, effectively breaking CI.

Temporarily ignore the test.

Reviewed By: alanz

Differential Revision: D88950046

fbshipit-source-id: edabc83ce2b533fa95075078feac624343c198ad
2025-12-11 06:36:45 -08:00
Alan Zimmerman
4bfedaee9a BE: validate all test fixtures
Summary:
The previous diff added the ability to validate a test fixture for parse errors, with an override mechanism if they are expected.

This diff enables the validation for all fixture parsing, and fixes all the resulting errors.

Reviewed By: TD5

Differential Revision: D88948727

fbshipit-source-id: c7e584f3e63c5ad095b9602eed56b469a73392d2
2025-12-11 06:21:28 -08:00
Alan Zimmerman
290b931170 BE: validate test fixture
Summary:
A common mistake when writing a declarative test fixture is to have a syntax error in it.

This diff adds `ChangeFixture::validate` to check for these, and panic if found, e.g.

```
thread 'tests::validate_fixture_with_parse_error' panicked at crates/ide_db/src/lib.rs:462:17:
Fixture validation failed: syntax errors found in test fixture

File: /src/test.erl
Errors: [Missing(")", 19..19)]
Content:
-module(test).
foo( -> ok.

Parse Tree:
SourceFile {
    syntax: SOURCE_FILE@0..27
      MODULE_ATTRIBUTE@0..14
        ANON_DASH@0..1 "-"
        ANON_MODULE@1..7 "module"
        ANON_LPAREN@7..8 "("
        ATOM@8..12
          ATOM@8..12 "test"
        ANON_RPAREN@12..13 ")"
        ANON_DOT@13..14 "."
      WHITESPACE@14..15 "\n"
      FUN_DECL@15..26
        FUNCTION_CLAUSE@15..25
          ATOM@15..18
            ATOM@15..18 "foo"
          EXPR_ARGS@18..19
            ANON_LPAREN@18..19 "("
          WHITESPACE@19..20 " "
          CLAUSE_BODY@20..25
            ANON_DASH_GT@20..22 "->"
            WHITESPACE@22..23 " "
            ATOM@23..25
              ATOM@23..25 "ok"
        ANON_DOT@25..26 "."
      WHITESPACE@26..27 "\n"
    ,
}
 ---
If this is expected, add `//- expect_parse_errors` to the start of the fixture
```

A subsequent diff will apply it to the code base

Reviewed By: TD5

Differential Revision: D88948352

fbshipit-source-id: 532275075bb338191594966bb3292986442cead6
2025-12-11 06:21:28 -08:00
Alan Zimmerman
0930edd693 BE: report malformed test fixture
Summary:
A declarative test fixture can have multiple files in it, in which case each has a metadata line giving the file name. But we have not been checking if it is omitted from the first file, leading to confusing behaviour when writing tests.

This diff updates test fixture parsing to panic in that case, with an appropriate message.

Reviewed By: TD5

Differential Revision: D88947477

fbshipit-source-id: 7ef7151fafb44d087b1da25c55454f20899ca67f
2025-12-11 05:22:57 -08:00
Alan Zimmerman
2d693f3578 BE: restore expected test result to generate a panic
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
As title.

Note that this is still failing on GH.

Reviewed By: robertoaloi

Differential Revision: D88751685

fbshipit-source-id: 4050a9f2094ac7c46395f0f05a7f77dfad9a583b
2025-12-10 08:59:12 -08:00
Victor Lanvin
0aef1f4005 Update fixtures for OTP 26/28
Summary: As title.

Reviewed By: robertoaloi, TD5

Differential Revision: D88853775

fbshipit-source-id: 8954794c428f6f1139ebe4f393ed80d1836a2784
2025-12-10 08:08:55 -08:00
Roberto Aloi
29c017c565 Polish extension README, improve package.json for discoverability
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-15-intel, macos-15-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-15-intel, macos-15-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
* Polish extension README (which is rendered [here](https://marketplace.visualstudio.com/items?itemName=erlang-language-platform.erlang-language-platform)).
* Set `displayName` (see [reference](https://code.visualstudio.com/api/references/extension-manifest)) to improve discoverability and hopefully ranking
* Update description
* Add `erlang` keyword to improve discoverability/ranking

Reviewed By: alanz

Differential Revision: D88847040

fbshipit-source-id: e2185e790f0711dd383d6cc51ad56716eeebb61e
2025-12-10 07:06:30 -08:00
Roberto Aloi
ed8820b3b2 Update Intel runners to mac-15-interl
Summary:
The Mac OS 13 Ventura runner images are [deprecated](https://github.com/actions/runner-images/issues/13046).
This results in a [CI error](2009932825).

This applies the recommended remediation.

Reviewed By: alanz

Differential Revision: D88848551

fbshipit-source-id: 201fa45e4834b082e84a150343042ae5a6104189
2025-12-10 07:06:17 -08:00
Roberto Aloi
a239a322cf Manually bump eqwalizer to the latest available version (#139)
Summary: Pull Request resolved: https://github.com/whatsapp/erlang-language-platform/pull/139

Reviewed By: alanz

Differential Revision: D88849209

Pulled By: robertoaloi

fbshipit-source-id: f3433841b248804dde41fca866680f8c6eaef338
2025-12-10 07:03:12 -08:00
Roberto Aloi
a4ded31602 Bump OSS VS Code extension to 0.46.0
Summary:
Several issues were affecting GitHub CI, preventing the extension to be correctly published to the marketplace.
A new release will therefore be necessary, hence the new bump.

Reviewed By: alanz

Differential Revision: D88848737

fbshipit-source-id: f4c31f1bbc5bb3aeec7359c8c8a5d1faeb0c2f9e
2025-12-10 07:00:19 -08:00
Roberto Aloi
6dbefe9bd0 Add Homebrew installation instructions for Mac users
Summary:
Mac users can now install ELP using the dedicated Homebrew formula at https://formulae.brew.sh/formula/erlang-language-platform. This provides a simpler installation method compared to downloading binaries manually or building from source.

Updated the installation documentation to highlight Homebrew as the easiest installation method for Mac users, placing it before the binary installation instructions.

Reviewed By: TheGeorge

Differential Revision: D88836106

fbshipit-source-id: 4df1340e7fe29e56e29e089d840f56092864b503
2025-12-10 03:50:13 -08:00
Roberto Aloi
4df5a7ae81 Bump OSS VS Code extension version to 0.45.0
Summary: In preparation for OSS release.

Reviewed By: alanz

Differential Revision: D88839310

fbshipit-source-id: f489b3e503c41e8302193cbdc78a46859967cbda
2025-12-10 03:45:29 -08:00
Roberto Aloi
f6b54832d7 Convert malformed_include linter to use a trait
Summary: Mechanical conversion, no functional change.

Reviewed By: alanz

Differential Revision: D88623867

fbshipit-source-id: 2d1f17430a44a705f22ec542e242165beb577285
2025-12-10 03:29:08 -08:00
Alan Zimmerman
1a086de994 BE: args.color
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: Move the decision-making logic for choosing to output color in CLI usage into a single place.

Reviewed By: TD5

Differential Revision: D88377007

fbshipit-source-id: 398552dba1547a9e9c0b5e6cd38808316280dd7a
2025-12-09 08:47:59 -08:00
Alan Zimmerman
77e0ff9bc8 Remove pre_parse_for_speed from elp eqwalize-all
Summary:
Measurements show it makes no difference to the run-time of `elp eqwalize-all`, and it is an impediment to providing streaming output.

Without this, parsing happens on-demand as files are processed by eqwalizer, so we can generate output as each is processed.

Reviewed By: robertoaloi

Differential Revision: D88379872

fbshipit-source-id: 5110788ac5a7ef471038db9de0abfa00bbe7312f
2025-12-09 08:47:59 -08:00
Alan Zimmerman
debed39b42 streaming results for elp lint
Summary:
At the moment the `elp lint` command processes all the files, and then renders the diagnostics at the end.  This can be annoying if you are wanting to just check for occurrences of a diagnostic.

This diff changes the behaviour to stream the results instead as they arrive.
This behaviour is turned off if
- the new `--no-stream` argument is given
- `elp lint` emits json formatted diagnostics
- `elp lint` applies fixes

Reviewed By: TheGeorge

Differential Revision: D88010824

fbshipit-source-id: dc725c1d503f56da6bb1c392cd88f635832320dc
2025-12-09 08:47:59 -08:00
Alan Zimmerman
c404d942df Update emacs eglot instructions for semantic tokens (#138)
Summary: Pull Request resolved: https://github.com/whatsapp/erlang-language-platform/pull/138

Reviewed By: michalmuskala

Differential Revision: D88746400

Pulled By: alanz

fbshipit-source-id: 0bfda35e25ebf62b62ec7f8209d1787fdbb58e80
2025-12-09 07:58:59 -08:00
Victor Lanvin
0f7069d02e Deprecate old error messages
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: As title. Remove the "detailed message" part, which is too verbose and mostly useless now.

Reviewed By: TD5

Differential Revision: D88633277

fbshipit-source-id: 092691c2520983148fa0ef8d61a62bd1149a1231
2025-12-09 06:29:17 -08:00
Roberto Aloi
e1296c5c14 Convert boolean_precedence linter to use a trait
Some checks are pending
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / edb (push) Waiting to run
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: Mechanical conversion, no functional change.

Reviewed By: TheGeorge

Differential Revision: D88620344

fbshipit-source-id: fb8a06f034b9c8ebf088acedad1d75769b340293
2025-12-08 04:50:14 -08:00
Roberto Aloi
4e6851c71a Convert misspelled_attribute linter to use a trait
Summary: Mechanical conversion. I also removed the "related info" since they did not seem to provide any additional benefit.

Reviewed By: TD5

Differential Revision: D88379801

fbshipit-source-id: 10926fdc31b88b5755ff346f97948cf83569f71e
2025-12-08 04:50:14 -08:00
Roberto Aloi
61512bf9b9 Convert unused_include linter to use trait
Summary: By using a trait we not only make the code more modular and readable, but we also have the ability to enable/disable the linter via config (without running it).

Reviewed By: michalmuskala

Differential Revision: D88351141

fbshipit-source-id: 7bcb3b2f72b1eb119f83b1784982d32867f9c486
2025-12-08 04:50:14 -08:00
Roberto Aloi
4726f8144d Convert missing_module linter to use a trait
Summary:
The diagnostic was computed in the `diagnostics.rs` module. By using a trait we ensure the code is more readable and the intention is clear.
We also modularize the code in `diagnostics.rs`.

Reviewed By: alanz

Differential Revision: D88349260

fbshipit-source-id: f761a9c9b0da188643b6e5eae35b30a74cb5d262
2025-12-08 04:50:14 -08:00
Roberto Aloi
016e0d7c1e Fix false positive for undefined_function linter
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
Summary:
It can happen that, when looking for undefined functions, we could not resolve the module name at compile-time.

With the old logic, we would incorrectly flag the case as an "invalid function".

With the improved version, we do not flag the case if we are not sure, avoiding a number of false positives.
A test case highlighting the issue is added as a unit test.

Reviewed By: TD5

Differential Revision: D88474342

fbshipit-source-id: f0f5ae1272f8264c5e11c6e8a7855e75a2832841
2025-12-05 03:48:33 -08:00
Eddie Shen
fd8fb4abeb Replace Duration::from_secs(240) to Duration::from_mins(4)
Summary:
Rust 1.91 introduced `Duration::from_mins`.

This diff replaces some instances of `Duration::from_secs` with the corresponding `Duration::from_mins`.

Reviewed By: dtolnay

Differential Revision: D88441014

fbshipit-source-id: 88d368316aeb6e4deb328e2052c105d70da9be06
2025-12-05 00:22:38 -08:00
Eddie Shen
c9cba57e40 Replace Duration::from_secs(60) to Duration::from_mins(1)
Summary:
X-link: https://github.com/meta-pytorch/torchft/pull/297

X-link: https://github.com/meta-pytorch/monarch/pull/2066

Rust 1.91 introduced `Duration::from_mins`.

This diff replaces some instances of `Duration::from_secs` with the corresponding `Duration::from_mins`.

Reviewed By: dtolnay

Differential Revision: D88434166

fbshipit-source-id: e5e86763e0f4cfa6da502d32f1f98ffc198399ed
2025-12-05 00:22:38 -08:00
Roberto Aloi
796f015f20 Make it possible to run buck tests in isolation
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
The buck2 tests seem to rely on a global state, which is only set for some of the test cases.

As a consequence, running all tests together works, but running some of them in isolation fails.

Consistently set the global state in all tests. As a follow-up, we could refactor this in a helper function.

Reviewed By: alanz

Differential Revision: D88274947

fbshipit-source-id: 5f22894e74bd41458139a93cd063647d95b86296
2025-12-04 09:45:48 -08:00
Roberto Aloi
d42e431df4 Add merge logic for linters configuration
Summary:
# Context

We want ELP to support hierarchical linter configurations. This means that, by placing a `.elp_lint.toml` file inside an OTP application dir it should be possible to specialize a more generic project-level linter configuration.

# This diff

Introduce the concept of "merging" two linter configurations. This mechanism, currently unused, will then be used when resolving the linter configuration for a given application.

Reviewed By: alanz

Differential Revision: D85573621

fbshipit-source-id: f52a9ed100be794be23c97174b12ce36c3ca7aba
2025-12-04 07:38:39 -08:00
Roberto Aloi
9ef2fec36e Add test for hierarchical config support
Summary:
# Context

We want ELP to support hierarchical linter configurations. This means that, by placing a `.elp_lint.toml` file inside an OTP application dir it should be possible to specialize a more generic project-level linter configuration.

# This diff

This diff introduces a new test project, named "hierarchical_config" to showcase the most basic form of the goal: the project is composed by two OTP applications (`app_a` and `app_b`). After applying the generic lint configuration, both applications should have two lint issues: an unused macro and an unused function. By placing an additional `.elp_lint.toml` file inside `app_a` to disable the unused macro linter, the unused macro lint issue should only be reported for `app_b`.

Since the feature is not implemented yet and the unused macro linter will be reported for both applications, the test is marked as "should panic". This will change at the end of the stack.

Reviewed By: alanz

Differential Revision: D85569527

fbshipit-source-id: 0772e3a84a25f23c3d6b7ae6c0c955f1206e2c6a
2025-12-04 07:38:39 -08:00
Alan Zimmerman
3461b85029 Improve emacs eglot config
Some checks are pending
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: Add a hook to automatically enable it in erlang-mode, and add the missing closing parens.

Reviewed By: lisztspace

Differential Revision: D88264639

fbshipit-source-id: d3d8166dd233ddc59ff6bb082f3c022851aec5dc
2025-12-03 06:46:58 -08:00
Alan Zimmerman
1fc2f63da8 Correctly report diagnostics from header file
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
It can happen that an included file has errors in it.

ELP is supposed to notice this, and report it with an L0000 (issue_in_included_file) diagnostic.

Unfortunately the logic for reporting this in the erlang service did not properly account for the exact location information reported in the `file` attribute, so this always fell back to a location of 0,0 in the including file. As a result, the diagnostic did not show up properly.

## This diff

We fix it by reporting the location according to the representation  used in the erlang service, and making sure we choose the correct include location.

We also add the diagnostic found in the included file as related information, so it is available in the original file

Reviewed By: robertoaloi

Differential Revision: D88010399

fbshipit-source-id: 4a1d2d76a809c104db059e9433200e1bfcf2ac59
2025-12-03 03:18:32 -08:00
Alan Zimmerman
8bd2c5e571 Include related information in elp lint non-json output
Summary:
An ELP Diagnostic can have related information in it, which provide additional context to the reported Diagnostic.

Although these are shown in the IDE when running as a server, they are not currently shown from the  command line.

This diff updates the `elp lint` command to display them, when not emitting JSON.

There are 3 variations, depending on where the related information is
-  same file: just show the range
- some erlang module: show the module name and range
- an erlang include file: show the full path and range

Reviewed By: robertoaloi

Differential Revision: D88010319

fbshipit-source-id: 26748ec7183a139a57ae97b75a9a61f62da27000
2025-12-03 03:18:32 -08:00
Alan Zimmerman
8558c9d5dc Add tree_print for a whole module
Some checks are pending
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
As per title.

We use tree_print as a development diagnostic tool.
The test runner for tree_print itself had code to tree_print an entire module via its forms.

This diff extracts this code and makes it available for use elsewhere.

Reviewed By: TD5

Differential Revision: D88159685

fbshipit-source-id: daf1bd1c25d22b9d9f48863b428538efe37a267c
2025-12-02 08:11:47 -08:00
Alan Zimmerman
cbe9a058cc update dependencies for dependabot
Summary: As title

Reviewed By: michalmuskala

Differential Revision: D88143729

fbshipit-source-id: cd5ecc02442e7661b4bf2f7e3f9b7f346561b2c4
2025-12-02 04:52:04 -08:00
Alan Zimmerman
e4b89ebac5 BE: fix clippy warnings
Some checks are pending
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: As title

Reviewed By: michalmuskala, TD5, robertoaloi

Differential Revision: D88143231

fbshipit-source-id: d7eebb3449b3c05a07ba1b5228930c13dd5708f0
2025-12-02 03:07:14 -08:00
Alan Zimmerman
f80d50389d remove --prefix command line argument
Summary: This should no longer be needed, remove it to reduce code complexity

Reviewed By: jcpetruzza

Differential Revision: D87929715

fbshipit-source-id: c62a6e07084d555bba12dafb96fb893e33f6dc9f
2025-12-02 01:53:20 -08:00
Roberto Aloi
eafb4940c7 Convert edoc linter to use a trait
Some checks are pending
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: Mechanical conversion.

Reviewed By: alanz

Differential Revision: D87546425

fbshipit-source-id: 4d938866586d89f9a6751e9b0c787c1faf1759d0
2025-12-01 09:05:40 -08:00
Roberto Aloi
270b8f4614 Fix support for rebar3 projects in IDE
Summary:
# Context

A number of `rebar3` users reported false positive diagnostics, including `duplicated module` when using ELP in combination with a basic rebar3 umbrella project. The problem only appears after the project is compiled.

# Problem

The issue is caused by a bug in the project discovery for rebar3. The project is not correctly recognized as a `rebar3` project, but as a `No manifest` one. This causes ELP to recursively look for Erlang applications within the project directory, discarding the rebar3 structure.

Since rebar3 projects populate a `_build` directory with symlinks to the project applications, each application is found twice, leading to "duplicated module" diagnostics. This is also behind a number of related issues, since paths (e.g. `extra_src_dirs`) are not correctly discovered.

# Solution

The `path` argument for the `discover_in_place` function contains the path to the `.elp.toml` configuration file. When looking for rebar3 projects, we are passing the path as-is, which is why discovery fails. Instead, we should be passing the base directory for the file, where the `rebar.config` resides.

Reviewed By: alanz

Differential Revision: D88071314

fbshipit-source-id: d79edbcdf7a01512f753db668606cb798e65b74b
2025-12-01 08:24:18 -08:00
Alan Zimmerman
89c0c87b0f Do not check for eqwalizer disappearing if we did not unpack it
Summary:
The normal case for the ELP executable is to have a copy of eqwalizer as a Graalvm exe embedded inside ELP. At startup, this is unpacked to a temporary directory, so we can run it.

In the past we had issues where external processes would clean up the temporary directory, and so it would disappear. To mitigate this, we check if the file still exists before running it, and recreate it if not.

BUT, if we are running with ELP_EQWALIZER_PATH pointing to the eqwalizer jar file, as per the OSS local build instructions, then we do not unpack it to a temporary directory, *and* the command name is set to simply "java", which is not a file, as it should be resolved from the path. As a result the current existence check fails, and we continuously report that eqwalizer has disappeared.

This diff changes the check to only be made if we have in fact unpacked eqwalizer to a temporary directory.

Reviewed By: TD5

Differential Revision: D88071028

fbshipit-source-id: 21e7c4897dd6a8f6ae6fe137c413b2fab094d936
2025-12-01 07:13:44 -08:00
Roberto Aloi
3e873e691d Make labels to denote test applications configurable
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary: Make it possible to customize the set of labels that in a Buck2 `erlang_application` target can identify a "test" application. Make it default to "test application".

Reviewed By: alanz, michalmuskala

Differential Revision: D88005051

fbshipit-source-id: d5a7cbb89373def5796420fa178c0a86fd72e3ed
2025-11-28 12:31:40 -08:00
Roberto Aloi
87bc60c524 Remove support for obsolete test_utils and elp_enabled Buck2 labels
Summary:
Simplify the classification of test applications, by removing support for the obsolete "test_utils" and "elp_enabled" labels.

A subsequent diff will make it possible to customize the labels via the `.elp.toml` configuration file.

Reviewed By: michalmuskala, alanz

Differential Revision: D88004904

fbshipit-source-id: fde38e8ce5a4f5c742c647a63ef736d3bbc84f51
2025-11-28 12:31:40 -08:00
Daniel Gorin
38c84d39a6 Remove unclear bits of W0050 docs
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
# Context
W0050 asks users to prefer the more efficient `tuple_size/1` and `byte_size/1`, instead of `size/1`.

# Problem
The explanation is muddled by some advice to always guard the usages of `byte_size/1` with `is_binary/1`. This doesn't make intuitive sense and there's nothing in the docs of `byte_size/1` that suggests this is advisable in any way.

# This diff
Remove this part. I'm also removing the part that rewrites `size/1` in terms of `byte_size/1` and `tuple_size/1` as it doesn't seem to be adding anything.

Reviewed By: TD5

Differential Revision: D87986348

fbshipit-source-id: dbd6aeec71989bc367f3d22b58a71d893b7fff76
2025-11-28 03:19:17 -08:00
Alan Zimmerman
7b124c7f06 Server: Impose a priority on next task selection
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
The ELP main loop is a message pump.  It calls `next_message` and processes it, until done.

There are multiple message sources, and the current code takes one at random from all available sources.

This diff changes this to an ordered selection, giving explicit priority when more than one source is ready at the same time.

This is motivated by
1. Make sure the messages we send go out as soon as possible (progress, telemetry)
2. Now that the vfs loader uses all available cores to speed up loading, make sure the loader progress messages do not drown out all others.

Reviewed By: michalmuskala

Differential Revision: D87984388

fbshipit-source-id: 3b8cc5f6614bdf9699e805b03da6b5696829d280
2025-11-28 02:27:14 -08:00
Alan Zimmerman
06892be8c1 Add server telemetry for workspace statistics
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
As title.

Note that for a buck project using quick start, we will get two values per project startup, the first smaller value is from processing the result of `buck2 targets`, the second includes any generated files from running `elp.bxl`

Reviewed By: jcpetruzza

Differential Revision: D87923914

fbshipit-source-id: 8b10cb1ef685250f022cf360e1b2d5f621c17407
2025-11-27 01:48:55 -08:00
Alan Zimmerman
0da6ec3079 Introduce elp --color argument to control ANSI color codes
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary: Also respond to the `NO_COLOR` environment variable, as per [no-color.org](no-color.org).

Reviewed By: jcpetruzza

Differential Revision: D77446683

fbshipit-source-id: c7b14c64813ca98a1163fb2f9e651ea304e5757d
2025-11-25 02:35:22 -08:00
Roberto Aloi
8997d5eb03 Implement support for renaming types
Summary: Long awaited feature: the ability to rename types. Take the opportunity to fix the range of the type name not to include arguments.

Reviewed By: alanz

Differential Revision: D87643493

fbshipit-source-id: e7fd3d13ff71ef5a3049aae3a242606899e582be
2025-11-25 02:19:42 -08:00
Cj Longoria
4fa7b6c8ac add internal rustfmt bin to elp cargo script
Summary: Add our nightly rustfmt binary to PATH for elp cargo shell script. This keeps the formatting consistent between `arc f` and `cargo.sh fmt` by using the same rustfmt.toml and rustfmt binary.

Reviewed By: alanz

Differential Revision: D87853695

fbshipit-source-id: dbb378acb8e48f5910187d32757d5f5597305df7
2025-11-25 02:19:37 -08:00
Alan Zimmerman
8dbbd1f6d4 Back out "Fix failing test"
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: As title

Reviewed By: robertoaloi

Differential Revision: D87786080

fbshipit-source-id: ab642c7b92b51c4df38fdef64f6741423e70e55a
2025-11-24 10:10:03 -08:00
Roberto Aloi
fe49f6ba3c Implement support for renaming macros
Summary: Long awaited feature: the ability to rename macros.

Reviewed By: alanz

Differential Revision: D87635298

fbshipit-source-id: 252ccd64193251fa9b0ce91cf6ab421c15c84086
2025-11-24 09:47:00 -08:00
Alan Zimmerman
be0cb21ea7 Make elp search a synonym for elp ssr
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
As title.

In future we may remove `elp ssr`.

Reviewed By: TD5

Differential Revision: D87766502

fbshipit-source-id: c9742292afe35984002d02b20ec0e051cfee125f
2025-11-24 05:04:16 -08:00
Alan Zimmerman
0de513221f ssr: stream command line match results
Summary:
It is annoying to wait for the entire body of code to be processed before seing results. Since the ssr search is based purely on the ast of a module, the search is embarrasingle trivial.

So report the results as they are found.

This does mean the summary statistic has to come at the end.

Reviewed By: TD5

Differential Revision: D87651432

fbshipit-source-id: b51b7bd94f8069113154adac9b1bf68f9b7351b3
2025-11-24 05:04:16 -08:00
Alan Zimmerman
473c0f1c56 Fix failing test
Summary: As title

Reviewed By: ilya-klyuchnikov, michalmuskala

Differential Revision: D87765456

fbshipit-source-id: deb9fc32f4bc547215619e43fecdaecf7ceb5a0f
2025-11-24 02:55:57 -08:00
Roberto Aloi
bc2c3f05d4 Require glob >=10.5.0
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary: Solves [GHSA-5j98-mcp5-4vw2](https://github.com/isaacs/node-glob/security/advisories/GHSA-5j98-mcp5-4vw2?fbclid=IwY2xjawONHSxleHRuA2FlbQIxMQBicmlkETFmTTVyb3hBUmNTbUNLeDlrc3J0YwZhcHBfaWQBMAABHt4eAVx-Yk7Cnshn0Hqrh-vQ8xKvHyVaF7_ovUMQhWSrRWN8um2ZimI4Vfmu_aem_B4s_KCafXrEOOcNU-AnJRA).

Reviewed By: TheGeorge

Differential Revision: D87628344

fbshipit-source-id: ab6ff51e5ddade4b93318606d573e6f7e5d043d5
2025-11-22 06:22:58 -08:00
Alan Zimmerman
0c2b43eb27 ssr: add test explicitly using colour output
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: As title

Reviewed By: TD5

Differential Revision: D87651912

fbshipit-source-id: 347be29dbb6f0dd71396dbb404b2ac98a9dbabc0
2025-11-21 10:19:14 -08:00
Alan Zimmerman
fbdb3e1baf ssr: Improve rendering of result
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
Inside ELP an SSR match is exposed as a diagnostic.  So the way it is output to the command line is as a diagnostic, giving location and the pattern that matched.

This is not very useful when exploring a code base from the command line.

This diff brings the ability to show the source for a matching diagnostic.  The command line interface is modeled on the one for grep, so it should be familiar to users.

It will automatically use colour if in a TTY context, but this can be controlled via CLI or environment variable.

Reviewed By: TD5

Differential Revision: D87634862

fbshipit-source-id: 52604d21100274b2abba9e364acbb972914aa4ac
2025-11-21 08:12:17 -08:00
Roberto Aloi
5470044b61 Bump js-yaml from 4.1.0 to 4.1.1 and glob from 10.4.5 to 10.5.0
Summary: Fix https://github.com/nodeca/js-yaml/security/advisories/GHSA-mh29-5h37-fv8m and https://github.com/isaacs/node-glob/security/advisories/GHSA-5j98-mcp5-4vw2

Reviewed By: jcpetruzza

Differential Revision: D87634207

fbshipit-source-id: 50ef19e9b138252d43a631b2c9501ca9a764b74a
2025-11-21 05:49:13 -08:00
Roberto Aloi
9860cc85f1 Publish OSS extension to OpenVSX marketplace
Summary:
As requested by several users:

https://github.com/WhatsApp/erlang-language-platform/issues/127

We can publish the extension to the open-vsx.org marketplace, in addition to the Microsoft one.

This enables using ELP in VSCodium.

Reviewed By: alanz

Differential Revision: D87625612

fbshipit-source-id: 8ee143cc3853b7ded04193802d32e164602be8d0
2025-11-21 02:44:09 -08:00
Roberto Aloi
5820634ce2 Allow severity method to receive &Semantic and FileId as arguments
Summary:
# Context

We want to convert the `edoc` linter to use a trait.

# Problem

The `edoc` linter has a different `Severity` for source code and test files.

# Solution

We can extend the `severity` and `cli_severity` methods to accept `sema` and `file_id`. This way, we can customize the severity based on the file. The new arguments will be used by the edoc linter in a subsequent diff.

Reviewed By: alanz

Differential Revision: D87545262

fbshipit-source-id: d7546d7d77ec019c2a2edc846e69134e93a6fe90
2025-11-21 02:03:27 -08:00
Roberto Aloi
99501811a5 Remove text_edit crate
Summary:
The `text_edit` crate contains a single file. Move it to the `ide_db` crate, and remove the whole `text_edit` crate.

This is in line with Rust Analyzer.

Reviewed By: alanz

Differential Revision: D87539326

fbshipit-source-id: cdc8f71902bc084eca79ae54ca71584ac48ed637
2025-11-21 02:03:27 -08:00
Roberto Aloi
b25b590a27 Move tree-diff functionality from syntax to ide_db crate
Summary:
# Context

The `text_edit` crate contains a single file, `lib.rs`. We can remove the entire crate by moving the functionality into a `text_edit.rs` in the `ide_db` crate. This is in line with Rust Analyzer.

# Problem

The move would eventually create a circular dependency between `syntax` and `ide_db`.

# Solution

To untangle the circular dependency, we can move the `tree-diff` functionality to the `ide_db` crate. Again, this is in line with Rust Analyzer.

Reviewed By: alanz

Differential Revision: D87524148

fbshipit-source-id: 90b1df3d4191a63c0d74c49af9fafec6578f530c
2025-11-21 02:03:27 -08:00
Roberto Aloi
1788ac77bd Move Emacs configuration under editors
Summary:
We already have a `editors` directory with editor-specific packages and configurations. Move the Emacs sample there.

Also reference it from the Emacs installation docs, to make it simpler to find.

Reviewed By: alanz

Differential Revision: D87517087

fbshipit-source-id: 754324de280ec094d6756d8702738d16fbdf268b
2025-11-21 02:03:27 -08:00
Roberto Aloi
44409a4346 Remove bench runner draft
Reviewed By: alanz

Differential Revision: D87516838

fbshipit-source-id: ab8bc396f005e8c3cf843583b61bd0e06e8ee2ca
2025-11-21 02:03:27 -08:00
Alan Zimmerman
7571e57155 BE: fix off-by-one in elp lint diagnostic output
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
When running any elp CLI command that produces diagnostics, the locations are incorrect, as they use the internal coordinate frame rather than the usual one for IDEs and other tools.

This means each line and col location is one less than it should be.

This diff fixes that, so the locations make sense to users.

Note: it does not affect output using `--format json`, which already does this.

Reviewed By: TD5

Differential Revision: D87539540

fbshipit-source-id: 27abd4ac5fb9e5056fc9e3397257d9e5cb9e678d
2025-11-20 07:30:38 -08:00
Roberto Aloi
77ff228aae Convert macro_precedence_surprise linter to use a trait
Summary: Simple conversion to use the new trait.

Reviewed By: jcpetruzza

Differential Revision: D87516327

fbshipit-source-id: 8a6669c4c337a54ecf0a65c864df8be40d82e720
2025-11-20 04:38:57 -08:00
Roberto Aloi
e9a9035e5a Convert no_warn_suppressions linter to use a trait
Summary: Simple conversion to use the new trait.

Reviewed By: jcpetruzza

Differential Revision: D87447644

fbshipit-source-id: 74e0caf1fc8fd289013af2fc69839b25f0b9bdc4
2025-11-20 04:38:57 -08:00
Roberto Aloi
5187bf3d3f Convert duplicate_module linter to use a trait
Summary: Simple conversion to use the new trait.

Reviewed By: TD5

Differential Revision: D87445553

fbshipit-source-id: 8b45cea1dcefe71b0cd573aa4529433974943d3f
2025-11-20 01:02:30 -08:00
Roberto Aloi
74ed6b2de4 Convert no_dialyzer_attribute linter to use a trait
Summary: Simple conversion to use the new trait.

Reviewed By: TD5

Differential Revision: D87079003

fbshipit-source-id: 7caaf84bf43882045637fe870046537e5eb82a5f
2025-11-20 01:02:30 -08:00
Roberto Aloi
cac1c952f9 Extend unavailable_type diagnostic to also scan record definitions
Summary: Take into account type references from record definitions when computing the `unavailable_type` diagnostic.

Reviewed By: TD5

Differential Revision: D87442698

fbshipit-source-id: 982a5e815877147d17e1d472230f06859263d343
2025-11-20 01:02:30 -08:00
Roberto Aloi
89ca280740 Ensure that linters specified via --diagnostic-filter run, even if disabled by default
Summary:
It is counterintuitive that, if a linter is disabled, it does not run when `--diagnostic-code` explicitly selects it.

This diff solves the issue.

Reviewed By: alanz

Differential Revision: D87434612

fbshipit-source-id: 7cc19544602f77e086919f0094b64120120fa7d4
2025-11-20 01:02:30 -08:00
Roberto Aloi
479c76ce85 Add unavailable_type diagnostic
Summary:
Introduce a new `unavailable_type` diagnostic, which warns about types which are correctly defined, but referenced from a module which does not have the application where the type is defined as a dependency.

The diagnostic, which is complementary to eqWAlizer's [unknown_id](https://github.com/WhatsApp/eqwalizer/blob/main/docs/reference/errors.md#unknown_id) (for remote types) and Erlang/OTP's L1295/undefined_type (for local types), can be seen a step towards a ELP-powered XRef.

The diagnostic works by scanning the `-spec`, `-type`, `-opaque` and `-callback` attributes. If a type is referenced, we verify whether the OTP application where the type is defined is a (recursive) dependency for the application where the type usage occurs.

The diagnostic is currently disabled by default.

Reviewed By: alanz

Differential Revision: D87341709

fbshipit-source-id: a7729de093f50ae2bdc0c2138019e4a5503e7359
2025-11-20 01:02:30 -08:00
Open Source Bot
65de999b3b Updating hashes
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
GitHub commits:

5a717a3930
b93909fb2a
c4ca15fcd7
2d38838986
f777219636
2ac8a7c0bb
8010220b21
c5209193b7
01b2a4fb60
c22a8d4dd8
03c425fcf4
ce1f68dda5
1e0f24c5b8

Reviewed By: sdwilsh

fbshipit-source-id: 8f60cbe0f2feac847240f89707cb2023201f1e54
2025-11-19 09:40:39 -08:00
Jon Janzen
9a91229311 Rollback submodule to enable syncing 2025-11-19 11:28:14 -08:00
Alan Zimmerman
8efb4fe29c BE: track related info in declarative tests
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
Our declarative tests allow us to add annotations for expected diagnostics, so we can clearly see and check what is generated.

But at present there is no way to check any related information for a diagnostic.

This diff adds that capability, showing related information together with the FileId and range each refers to.

Reviewed By: robertoaloi

Differential Revision: D87316965

fbshipit-source-id: ea7db2980b11950c3552befec7b666665ceef84b
2025-11-19 03:56:10 -08:00
Alan Zimmerman
dcf4e3a4ff add file_id to diagnostic RelatedInformation
Summary:
A given diagnostic can have related information in it, which carries relevant context to the provided diagnostic.
For example, for a head mismatch diagnostic, it reports the specific head location(s) that do not match.

The LSP spec uses a `Location` for these, which includes a file URL, meaning the related info can be in a different file from where the diagnostic is reported.

In ELP, we currently do not provide a way of populating this information, so can only refer to related information within the same file.  Thic can result in erroneous outcomes.

## This diff
We include a `FileId` in our internal `RelatedInformation` structure, and map it to a URL when serializing for transmission to the LSP client

Reviewed By: robertoaloi

Differential Revision: D87316542

fbshipit-source-id: 5f94eb4fe5bb73e7bf1fff7cad458231c51bd6f0
2025-11-19 03:56:10 -08:00
Daniel Gorin
8394c84d6b Bump docusaurus to 3.9.2
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary: This also bumps js-yaml to 4.1.1, addressing CVE-2025-64718

Reviewed By: robertoaloi

Differential Revision: D87222063

fbshipit-source-id: f36270df43f8412a880df7e730f562178a825156
2025-11-17 13:07:42 -08:00
Roberto Aloi
717422ebfe Convert the no_catch linter to use a trait
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: Simple conversion to use the new trait.

Reviewed By: TD5

Differential Revision: D87078566

fbshipit-source-id: 5e019d3b968a78997d1ebe24f5b168cf8fce4b1f
2025-11-17 02:22:16 -08:00
Roberto Aloi
30a992691f Convert the undocumented_function linter to use trait
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary:
Even if the `undocumented_function` is supposed to be disabled by default, it still runs. This is due to a flawed logic in `diagnostics.rs`, originally introduced in D59272525.

This is problematic, since open-source projects such as OTP see a huge number of errors when running the `elp lint` command without specifying a custom configuration.

By converting the linter to use the new trait, we incidentally fix the bug.

This was the last linter using the `default_disabled: true` logic. At this point the enabled/disabled logic can be simplified.

Reviewed By: alanz

Differential Revision: D87060203

fbshipit-source-id: 1121d286c766fb461420e3268aca817169020d7d
2025-11-14 10:05:06 -08:00
Roberto Aloi
20b8d9950a Convert undocumented_module linter to use trait
Summary:
Even if the `undocumented_module` is supposed to be disabled by default, it still runs. This is due to a flawed logic in `diagnostics.rs`, originally introduced in D59272525.

This is problematic, since open-source projects such as OTP see a huge number of errors when running the `elp lint` command without specifying a custom configuration.

By converting the linter to use the new trait, we incidentally fix the bug.

One more linters uses a `default_disabled: true` property in its descriptor: `undocumented_function`. It will be converted next, and the logic to handle the `default_disabled` will eventually be removed.

Reviewed By: alanz

Differential Revision: D87059857

fbshipit-source-id: 7fb6eff8773c786c6894548c914b8e3c78c38745
2025-11-14 10:05:06 -08:00
Roberto Aloi
aca24c8fc3 Convert missing_compile_warn_missing_spec linter to use trait
Summary:
Even if the `missing_compile_warn_missing_spec` is supposed to be disabled by default, it still runs. This is due to a flawed logic in `diagnostics.rs`, originally introduced in D59272525.

This is problematic, since open-source projects such as OTP see a huge number of errors when running the `elp lint` command without specifying a custom configuration.

By converting the linter to use the new trait, we incidentally fix the bug.

Two more linters use a `default_disabled: true` property in their descriptors: `undocumented_module` and `undocumented_function`. They will be converted next, and the logic to handle the `default_disabled` will eventually be removed.

Reviewed By: alanz

Differential Revision: D86978483

fbshipit-source-id: 5a89ff0fd1297a1e75db9d4b60d75b70f98d1e0c
2025-11-14 10:05:06 -08:00
Alan Zimmerman
276297e366 6/n: include: do not report W0058 if is is already reported by the erlang service
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
In a properly configured buck2 project, W0058 and E1516 will always be reported at the same time.

So do not report W0058 if there is already a E1516.

Reviewed By: TD5

Differential Revision: D86963330

fbshipit-source-id: fe1aaaa71330da059ed697d187542e3cb470e965
2025-11-14 04:35:24 -08:00
Alan Zimmerman
a8bb2de049 5/n: include: report HIR unresolved include files W0058
Summary:
For a buck project, if the dependencies are not set up properly for ELP use, it may compile but ELP is unable to resolve a nested include file when processing the middle ones in a chain.

This diff adds a check for the HIR include file resolution so this can be detected.

For a properly configured buck project this is redundant, because the Erlang service already reports `E1516` for this.

The next diff filters out occurrences generated here in that case.

Reviewed By: TD5

Differential Revision: D86963331

fbshipit-source-id: 356cefeba61e306fb3541a21ba16c189aa8c8faa
2025-11-14 04:35:24 -08:00
Alan Zimmerman
ed673119e4 4/n: include: do not report W0057 if it is already reported by the erlang service
Summary: As title.

Reviewed By: TD5

Differential Revision: D86963332

fbshipit-source-id: ffb3020fbfd6b09a273d4e34cb28f353fa12deab
2025-11-14 04:01:31 -08:00
Alan Zimmerman
42ef1d1924 3/n: includes: convert HIR diagnostics into ide Diagnostic W0057
Summary:
Create a new diagnostic W0057 (hir_unresolved_macro) to report macros not resolved during HIR lowering.

For a properly configured buck2 project this simply shadows the existing Erlang service `E1507` / `E1508` diagnostics, but for an incorrectly configured one they show up alone.

The next diff filters them out if they are already reported.

It also ensures it does not report on usages of `?FUNCTION_NAME` or ?FUNCTION_ARITY` in the replacement part of a `-define()` attribute.

Reviewed By: TD5

Differential Revision: D86963336

fbshipit-source-id: 08f8d1b6c58dde6ee0a106f9151b237709dc56e0
2025-11-14 04:01:31 -08:00
Alan Zimmerman
6fe7f108a1 2/n: includes: record macro expansion failures when lowering to HIR
Summary:
Record failed macro expansions when lowering to HIR.

We track them in the `BodySourceMap`, as we need to report based on `ast` locations.

Later diffs in this stack will turn them into ide Diagnostics, but that type is not available here because HIR is a leaf in the crate graph.

Reviewed By: TD5

Differential Revision: D86963333

fbshipit-source-id: 6f9afecbb10f6a2c999689e007f735f0bafbdf43
2025-11-14 04:01:31 -08:00
Alan Zimmerman
59ec8ab042 1/n: includes: add not-yet-failing test case for nested include buck targets
Summary:
This diff sets up a test case to demonstrate a problem which will be fixed by this stack, as it is currently silently ignored.

As such, there is no failure reported in the test. That will change later in the stack.

It is possible to configure a buck2 project with nested include files so that it compiles with buck2, and also with our erlang_service, but that we are unable to properly lower it into HIR and so do not resolve macros in ELP.

This occurs when we have three buck2 targets, A,B,C each in a separate directory.
- A has both B and C as dependencies, but
- B does not have C as one.

Then
- target A contains a .erl file that includes a .hrl from target B
- the .hrl in target B includes a .hrl from target C

So from A we can resolve the entire chain of includes via dependencies, but from B we cannot.

And ELP lowers the file into HIR for B in the context of B, so does not resolve the include at C, and silently fails to do so, entering a `Expr::Missing` value instead.

Reviewed By: TD5

Differential Revision: D86963334

fbshipit-source-id: 57b51714513fc78cd21083adea6abd12a9350571
2025-11-14 04:01:31 -08:00
Tom Davies
f050c6c671 Support calls to lists:nth/2
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
Fixes a query as to why we report on `hd(lists:reverse(L))`, but not `lists:nth(1, lists:reverse(L))`.

For the purposes of this diagnostic, `lists:nth(1, lists:reverse(L))` is equivalent to `hd(lists:reverse(L))`, so we trigger on that too.

Reviewed By: alanz

Differential Revision: D86969766

fbshipit-source-id: e6a022a10267d04c6700b3ee5fc9fa31a02b75ac
2025-11-13 07:23:15 -08:00
Roberto Aloi
395db3dda7 Add lists_reverse_append linter
Summary:
Introduce a new linter which identifies usages of the following pattern:

```
lists:reverse(List) ++ Tail
```

Suggesting to replace them with the more performing:

```
lists:reverse(List, Tail)
```

Reviewed By: michalmuskala, alanz

Differential Revision: D86967410

fbshipit-source-id: cc5142aa9548a69792bb5ba9ff6698afbd38227c
2025-11-13 06:33:43 -08:00
Alan Zimmerman
4486d66840 Clarify tool usage for building and testing the project in elp_development.md
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: Clarify tool usage for building and testing the project in elp_development.md

Reviewed By: TD5

Differential Revision: D86951935

fbshipit-source-id: 972aea59d3050c258270bbb1694b968d83655858
2025-11-13 03:14:38 -08:00
Alan Zimmerman
f4b93ec388 Improve file watch logging destination
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary: The temp directory location is not the same on all platforms.

Reviewed By: jcpetruzza

Differential Revision: D86679320

fbshipit-source-id: 39db19df4377798348ae81c87ffb9599e6f87334
2025-11-12 06:30:58 -08:00
Facebook Community Bot
c5263ed926
Re-sync with internal repository (#131)
The internal and external repositories are out of sync. This Pull Request attempts to brings them back in sync by patching the GitHub repository. Please carefully review this patch. You must disable ShipIt for your project in order to merge this pull request. DO NOT IMPORT this pull request. Instead, merge it directly on GitHub using the MERGE BUTTON. Re-enable ShipIt after merging.
2025-11-12 14:03:18 +00:00
Alan Zimmerman
e0c5e94ac0 Add file watch logging for project switch decisions
Some checks are pending
ELP CI / edb (push) Waiting to run
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Blocked by required conditions
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Blocked by required conditions
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Waiting to run
Summary:
We already have local logging of changes we receive related to file watching, both from VFS and the LSP client.

To contextualise these, include logging of the decisions made at key points in the project loading lifecyle when ELP is running as an LSP server.

Reviewed By: jcpetruzza

Differential Revision: D86679575

fbshipit-source-id: dc4fb2bdab5b489757a618aefee33f544bce4767
2025-11-12 03:31:52 -08:00
Alan Zimmerman
b01a09f2ff elp ssr: set info priority when --dump-config is set
Summary:
As title.

It does not make sense to have at least info severity in the IDE, otherwise the squiggles do not show up.

Reviewed By: jcpetruzza

Differential Revision: D86774246

fbshipit-source-id: 0db22ecf1b90c7e7a2d2037c0c45cc8619928c44
2025-11-12 01:56:31 -08:00
Alan Zimmerman
49fb231fe9 BE: remove workspace reference to non-existent erl_ast crate
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary: As title.

Reviewed By: jcpetruzza

Differential Revision: D86513055

fbshipit-source-id: 068357b9d6976bca2838036c5dbe308afbb52fe7
2025-11-10 03:36:04 -08:00
Alan Zimmerman
412ccca85e Update elp_development.md to improve declarative test example
Summary: We now include the diagnostic code in the expected diagnostic.

Reviewed By: RobinMorisset

Differential Revision: D86658752

fbshipit-source-id: 43f835633a0c81c15d7f43cfcdfde967db9a3178
2025-11-10 03:01:11 -08:00
Alan Zimmerman
85c1586d7d Add initial CLAUDE.md
Summary: As title. Also tweak elp_development.md

Reviewed By: TheGeorge

Differential Revision: D86507504

fbshipit-source-id: 0c3d92728014914c2954e1201d9da8fca56c19c0
2025-11-10 02:04:17 -08:00
Alan Zimmerman
6f2ee22321 buck2: Improve pop-up when the buck project is malformed
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary:
When ELP is loading a buck project it does queries using buck.
Sometimes these fail, because the current state of the buck configuration files is invalid.
In that case, we show a pop-up suggesting that the user examine the buck dashboard, and provide a URL for this.

It is not always clear to the user that this is related to a malformed buck project, rather than a bug in ELP.

This diff tries to make it clearer.

Note that we unfortunately do not have the ability to use any kind of formatting in the displayed message.

Reviewed By: TD5

Differential Revision: D86510447

fbshipit-source-id: 57a93f829d37a8a4d7c8be88d6cf68adcf41c859
2025-11-07 03:07:46 -08:00
Alan Zimmerman
4227771616 CLI ssr: Add --dump-config for .elp_lint.toml config snippet
Some checks failed
ELP CI / edb (push) Has been cancelled
Deploy Website to GitHub Pages / Deploy Website to GitHub Pages (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, true, linux-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, linux, 26.2, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, true, linux-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-13, macos-13-x64, x86_64-apple-darwin, true, darwin-x64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, macos, 26.2, macos-latest, macos-latest-arm, aarch64-apple-darwin, true, darwin-arm64) (push) Has been cancelled
ELP CI / ci (26, 26.2.5.13, windows, 26.2, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, true, win32-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, linux, 27.3, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, macos, 27.3, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (27, 27.3.4, windows, 27.3, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04, ubuntu-22.04-x64, x86_64-unknown-linux-gnu, false, linux-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, linux, 28, ubuntu-22.04-arm, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, false, linux-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-13, macos-13-x64, x86_64-apple-darwin, false, darwin-x64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, macos, 28, macos-latest, macos-latest-arm, aarch64-apple-darwin, false, darwin-arm64) (push) Has been cancelled
ELP CI / ci (28, 28.0.1, windows, 28, windows-2022, windows-2022-x64, x86_64-pc-windows-msvc, false, win32-x64) (push) Has been cancelled
Summary:
We can use the command line `elp ssr` command to search through files in a project for matches, but it is also convenient to be able to examine them in an IDE context.

This diff adds this capability, with two new command line options
- `--info` upgrades the reported diagnostic from weak warning to info
- `--dump-config` emits a toml snippet suitable for placement at the end of an `.elp_lint.toml` file.

```bash
elp ssr --parens --dump-config --info "(3)" "{_A}"

# Add this to your .elp_lint.toml
[[ad_hoc_lints.lints]]
type = "LintMatchSsr"
ssr_pattern = "ssr: (3)."
severity = "info"
macro_strategy = "expand"
paren_strategy = "visible"

[[ad_hoc_lints.lints]]
type = "LintMatchSsr"
ssr_pattern = "ssr: {_A}."
severity = "info"
macro_strategy = "expand"
paren_strategy = "visible"
```

The edit to `.elp_lint.toml` will be immediately picked up, and you will see the matches as normal diagnostics with a blue squiggle for info.

Reviewed By: TD5

Differential Revision: D85960380

fbshipit-source-id: 803c19f1917d939d13e6406e440057632b489ea6
2025-11-05 02:27:35 -08:00
774 changed files with 12580 additions and 14617 deletions

View file

@ -1,8 +1,8 @@
[alias]
xtask = "run --package xtask --"
# @fb-only
# @fb-only
# @fb-only: [build]
# @fb-only: target-dir = "../../../buck-out/elp"
[profile.release]
codegen-units = 1

View file

@ -30,7 +30,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform-arch: [ubuntu-22.04-x64, ubuntu-22.04-arm, macos-13-x64, macos-latest-arm, windows-2022-x64]
platform-arch: [ubuntu-22.04-x64, ubuntu-22.04-arm, macos-15-x64, macos-latest-arm, windows-2022-x64]
otp-version: [26.2, 27.3, 28.0]
include:
- otp-version: 26.2
@ -55,8 +55,8 @@ jobs:
os: linux
target: aarch64-unknown-linux-gnu
vscode-target: linux-arm64
- platform-arch: macos-13-x64
platform: macos-13
- platform-arch: macos-15-x64
platform: macos-15-intel
os: macos
target: x86_64-apple-darwin
vscode-target: darwin-x64
@ -97,6 +97,8 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y crossbuild-essential-arm64
- name: Install Buck2
uses: dtolnay/install-buck2@latest
- id: setup-erlang
uses: ./.github/actions/setup-erlang
with:
@ -135,7 +137,7 @@ jobs:
- name: Test elp
# Do not run the tests in case of cross-compilation or on Windows
if: matrix.platform-arch != 'macos-latest-arm' && matrix.os != 'windows'
run: 'cargo test --no-default-features --workspace --target ${{ matrix.target }}'
run: 'cargo test --workspace --target ${{ matrix.target }}'
- name: Build elp (No Windows)
if: matrix.os != 'windows'
run: 'cargo build --release --target ${{ matrix.target }} --config target.aarch64-unknown-linux-gnu.linker=\"aarch64-linux-gnu-gcc\"'
@ -200,6 +202,8 @@ jobs:
node-version: 20
- name: Install VSCE
run: npm install -g vsce
- name: Install OVSX
run: npm install -g ovsx
- name: Prepare VS Code Extension to host binaries (No Windows)
if: matrix.os != 'windows'
run: mkdir -p editors/code/bin
@ -285,3 +289,7 @@ jobs:
working-directory: editors/code
if: ${{ github.event_name == 'release' && matrix.vscode-publish && matrix.os != 'windows' }}
run: vsce publish -p ${{ secrets.VSCE_PAT }} --packagePath erlang-language-platform.vsix
- name: Publish extension to OpenVSX marketplace
working-directory: editors/code
if: ${{ github.event_name == 'release' && matrix.vscode-publish && matrix.os != 'windows' }}
run: ovsx publish -p ${{ secrets.OVSX_PAT }} --packagePath erlang-language-platform.vsix

View file

@ -3,13 +3,34 @@ llms-gk: 'devmate_elp_development_md'
apply_to_regex: '^(.*\.rs|.*\.md)$'
oncalls: ['vscode_erlang']
---
# ELP Development Rules for LLMs
# ELP Development Rules for LLMs (OSS)
## Project Overview
ELP (Erlang Language Platform) is a language server and development tools suite for Erlang, built in Rust. This project provides IDE features, diagnostics, and code analysis for Erlang codebases.
ELP (Erlang Language Platform) is a language server and development tools suite
for Erlang, built in Rust. This project provides IDE features, diagnostics, and
code analysis for Erlang codebases.
## Build System
Use standard Cargo commands:
```bash
# Build
cargo build --release
# Run tests
cargo test --workspace
# Run clippy
cargo clippy --tests
# Format code
cargo fmt
# Code generation
cargo xtask codegen
```
## Diagnostic Code Management
@ -17,13 +38,13 @@ ELP (Erlang Language Platform) is a language server and development tools suite
When adding new diagnostic codes to `DiagnosticCode` enum:
1. **Naming Convention**: Use descriptive PascalCase names that clearly indicate the issue
1. **Naming Convention**: Use descriptive PascalCase names that clearly indicate
the issue
- Good: `UnusedFunctionArg`, `MissingCompileWarnMissingSpec`
- Bad: `Error1`, `BadCode`
2. **Code Assignment**: Follow the established numbering scheme
- `W0000-W9999`: Native ELP diagnostics, visible in the OSS version
- `WA000-WA999`: WhatsApp-specific warnings, only visible in Meta builds
- Use the next available number in the appropriate range
- Never change the number of an existing diagnostic code
- Never change the label of an existing diagnostic code
@ -37,7 +58,8 @@ When adding new diagnostic codes to `DiagnosticCode` enum:
4. **Documentation**: Add comments explaining complex diagnostic codes
5. **Documentation File**: Create a corresponding documentation file in the website
5. **Documentation File**: Create a corresponding documentation file in the
website
- Location: `website/docs/erlang-error-index/{namespace}/{code}.md`
- Example: `W0051``website/docs/erlang-error-index/w/W0051.md`
- Include frontmatter with `sidebar_position` matching the code number
@ -51,16 +73,19 @@ When adding new diagnostic codes to `DiagnosticCode` enum:
### Creating DiagnosticDescriptor
Every diagnostic must have a corresponding `DiagnosticDescriptor` that defines when and how the diagnostic runs:
Every diagnostic must have a corresponding `DiagnosticDescriptor` that defines
when and how the diagnostic runs:
1. **Static Descriptor Declaration**: Create a public static descriptor in your diagnostic module
1. **Static Descriptor Declaration**: Create a public static descriptor in your
diagnostic module
- Use `pub(crate) static DESCRIPTOR: DiagnosticDescriptor` pattern
- Define `DiagnosticConditions` with appropriate flags
- Provide a checker function that implements the diagnostic logic
2. **Diagnostic Conditions**: Configure when the diagnostic should run
- `experimental`: Mark as true for experimental/unstable diagnostics
- `include_generated`: Set to false if diagnostic shouldn't run on generated code
- `include_generated`: Set to false if diagnostic shouldn't run on generated
code
- `include_tests`: Set to false if diagnostic shouldn't run on test files
- `default_disabled`: Set to true if diagnostic requires explicit enabling
@ -69,7 +94,8 @@ Every diagnostic must have a corresponding `DiagnosticDescriptor` that defines w
- Push diagnostics to the `diags` vector using `Diagnostic::new()`
- Use helper functions to keep the checker clean and focused
4. **Registration**: Add the descriptor to `diagnostics_descriptors()` function in `diagnostics.rs`
4. **Registration**: Add the descriptor to `diagnostics_descriptors()` function
in `diagnostics.rs`
- Include your module's `DESCRIPTOR` in the returned vector
5. **Module Structure**: Follow the established pattern
@ -78,12 +104,6 @@ Every diagnostic must have a corresponding `DiagnosticDescriptor` that defines w
- Include comprehensive tests with `#[cfg(test)]`
- Use SSR patterns when appropriate for complex matching
### Meta-Only vs OSS Code
- Use `@fb-only` and `@oss-only` comments to mark platform-specific code
- Meta-only diagnostics should use `MetaOnlyDiagnosticCode` wrapper
- Ensure OSS builds work by providing fallbacks for Meta-only features
## Rust Code Style
### Error Handling
@ -120,24 +140,40 @@ Every diagnostic must have a corresponding `DiagnosticDescriptor` that defines w
### Declarative Test Fixtures
ELP uses a declarative test fixture system that allows you to write tests with inline annotations and markers directly in test strings. This system is defined in `/data/sandcastle/boxes/fbsource/fbcode/whatsapp/elp/crates/project_model/src/test_fixture.rs`.
ELP uses a declarative test fixture system that allows you to write tests with
inline annotations and markers directly in test strings. This system is defined
in `crates/project_model/src/test_fixture.rs`.
#### Key Features
1. **File Organization**: Use `//- /path/to/file.erl` to define multiple files in a single test
2. **Metadata Markers**: Specify app names, include paths, OTP apps, etc. using metadata after the path
1. **File Organization**: Use `//- /path/to/file.erl` to define multiple files
in a single test
2. **Metadata Markers**: Specify app names, include paths, OTP apps, etc. using
metadata after the path
3. **Annotations**: Mark expected diagnostics or ranges using `%% ^^^` syntax
4. **Cursors and Ranges**: Use `~` markers to indicate positions or ranges in test code
4. **Cursors and Ranges**: Use `~` markers to indicate positions or ranges in
test code
#### Annotation Syntax
Annotations allow you to mark expected diagnostics, types, or other information directly in test code:
Annotations allow you to mark expected diagnostics, types, or other information
directly in test code:
- **Basic annotation**: `%% ^^^ some text` - Points to the range above matching the caret length
- **Top-of-file marker**: `%% <<< text` (at file start) - Creates annotation at position 0..0
- **File-wide annotation**: `%% ^^^file text` - Annotation spans the entire file contents
- **Left-margin annotation**: `%%<^^^ text` - Annotation starts at `%%` position instead of first `^`
- **Basic annotation**: `%% ^^^ some text` - Points to the range above matching
the caret length
- **Top-of-file marker**: `%% <<< text` (at file start) - Creates annotation at
position 0..0
- **File-wide annotation**: `%% ^^^file text` - Annotation spans the entire file
contents
- **Left-margin annotation**: `%%<^^^ text` - Annotation starts at `%%` position
instead of first `^`
- **Multiline annotations**: Use continuation lines with `%% | next line`
- Continuation lines are particularly useful for diagnostics with related information:
```erlang
foo() -> syntax error oops.
%% ^^^^^ error: P1711: syntax error before: error
%% | Related info: 0:45-50 function foo/0 undefined
```
#### Example Test Fixture
@ -146,9 +182,8 @@ let fixture = r#"
//- /src/main.erl
-module(main).
foo(X) ->
X + undefined.
%% ^^^^^^^^^ error: type mismatch
foo( -> ok. %%
%% ^ error: W0004: Missing ')'~
"#;
```
@ -160,34 +195,37 @@ foo(X) ->
### Running Tests for Specific Crates
When running tests for a specific crate, you need to specify the crate name, not the directory name. The mapping is:
When running tests for a specific crate, you need to specify the crate name, not
the directory name. The mapping is:
| Crate Name | Directory Name |
|------------|----------------|
| `elp_base_db` | `crates/base_db` |
| `elp_eqwalizer` | `crates/eqwalizer` |
| Crate Name | Directory Name |
| -------------------- | ----------------------- |
| `elp` | `crates/elp` |
| `elp_base_db` | `crates/base_db` |
| `elp_eqwalizer` | `crates/eqwalizer` |
| `elp_erlang_service` | `crates/erlang_service` |
| `elp_ide` | `crates/ide` |
| `elp_ide_assists` | `crates/ide_assists` |
| `elp_ide` | `crates/ide` |
| `elp_ide_assists` | `crates/ide_assists` |
| `elp_ide_completion` | `crates/ide_completion` |
| `elp_ide_db` | `crates/ide_db` |
| `elp_ide_ssr` | `crates/ide_ssr` |
| `elp_log` | `crates/elp_log` |
| `elp_project_model` | `crates/project_model` |
| `elp_syntax` | `crates/syntax` |
| `elp_text_edit` | `crates/text_edit` |
| `elp_types_db` | `crates/types_db` |
| `hir` | `crates/hir` |
| `erl_ast` | `crates/erl_ast` |
| `elp_ide_db` | `crates/ide_db` |
| `elp_ide_ssr` | `crates/ide_ssr` |
| `elp_log` | `crates/elp_log` |
| `elp_project_model` | `crates/project_model` |
| `elp_syntax` | `crates/syntax` |
| `elp_text_edit` | `crates/text_edit` |
| `elp_types_db` | `crates/types_db` |
| `hir` | `crates/hir` |
Example: To run tests for the `elp_ide` crate:
```bash
./meta/cargo.sh test -p elp_ide
cargo test -p elp_ide
```
Or to run tests in a specific directory:
```bash
./meta/cargo.sh test --manifest-path crates/ide/Cargo.toml
cargo test --manifest-path crates/ide/Cargo.toml
```
### Existing tests
@ -277,14 +315,8 @@ Or to run tests in a specific directory:
- Collect multiple errors rather than failing on the first one
- Provide partial results when full analysis isn't possible
### Tools
- ELP uses a cargo workspace.
- Inside Meta, use `./meta/cargo.sh` instead of `cargo`
- Inside Meta, use `./meta/clippy.sh` to run clippy
- Use `arc lint --apply-patches` for formatting.
### Process
- Always run tests before finishing.
- Always run `./meta/cargo.sh clippy --tests` before submitting a diff
- Always run tests before finishing
- Always run `cargo clippy --tests` before submitting PRs
- Use `cargo fmt` for code formatting

12
.vscode/tasks.json vendored
View file

@ -4,7 +4,7 @@
{
"label": "ELP: build (debug)",
"type": "shell",
// @fb-only
// @fb-only: "command": "./meta/cargo.sh build",
"command": "cargo build", // @oss-only
"group": {
"kind": "build",
@ -19,7 +19,7 @@
{
"label": "ELP: build (release)",
"type": "shell",
// @fb-only
// @fb-only: "command": "./meta/cargo.sh build --release",
"command": "cargo build --release", // @oss-only
"group": {
"kind": "build",
@ -34,7 +34,7 @@
{
"label": "ELP: build (release-thin)",
"type": "shell",
// @fb-only
// @fb-only: "command": "./meta/cargo.sh build --profile release-thin --bins",
"command": "cargo build --profile release-thin --bins", // @oss-only
"group": {
"kind": "build",
@ -49,7 +49,7 @@
{
"label": "ELP: run clippy on workspace",
"type": "shell",
// @fb-only
// @fb-only: "command": "./meta/clippy.sh --workspace --tests",
"command": "cargo clippy --workspace --tests", // @oss-only
"group": {
"kind": "build",
@ -64,7 +64,7 @@
{
"label": "ELP: run clippy on workspace, apply fixes",
"type": "shell",
// @fb-only
// @fb-only: "command": "./meta/clippy.sh --workspace --tests --fix",
"command": "cargo clippy --workspace --tests --fix", // @oss-only
"group": {
"kind": "build",
@ -79,7 +79,7 @@
{
"label": "ELP: run tests on workspace",
"type": "shell",
// @fb-only
// @fb-only: "command": "./meta/cargo.sh test --workspace",
"command": "cargo test --workspace", // @oss-only
"group": {
"kind": "build",

18
Cargo.lock generated
View file

@ -446,10 +446,10 @@ dependencies = [
"crossbeam-channel",
"elp_eqwalizer",
"elp_ide",
"elp_ide_db",
"elp_log",
"elp_project_model",
"elp_syntax",
"elp_text_edit",
"env_logger",
"expect-test",
"fs_extra",
@ -572,7 +572,6 @@ dependencies = [
"elp_ide_ssr",
"elp_project_model",
"elp_syntax",
"elp_text_edit",
"elp_types_db",
"env_logger",
"expect-test",
@ -604,7 +603,6 @@ dependencies = [
"cov-mark",
"elp_ide_db",
"elp_syntax",
"elp_text_edit",
"expect-test",
"fxhash",
"hir",
@ -637,6 +635,7 @@ name = "elp_ide_db"
version = "1.1.0"
dependencies = [
"anyhow",
"cov-mark",
"eetf",
"either",
"elp_base_db",
@ -644,12 +643,12 @@ dependencies = [
"elp_erlang_service",
"elp_project_model",
"elp_syntax",
"elp_text_edit",
"elp_types_db",
"expect-test",
"fxhash",
"hir",
"indexmap 2.9.0",
"itertools 0.10.5",
"lazy_static",
"log",
"memchr",
@ -664,6 +663,7 @@ dependencies = [
"strum",
"strum_macros",
"tempfile",
"text-size",
"toml",
"tracing",
]
@ -734,10 +734,8 @@ dependencies = [
name = "elp_syntax"
version = "1.1.0"
dependencies = [
"cov-mark",
"eetf",
"elp_ide_db",
"elp_text_edit",
"expect-test",
"fxhash",
"indexmap 2.9.0",
@ -757,14 +755,6 @@ dependencies = [
"tree-sitter-erlang",
]
[[package]]
name = "elp_text_edit"
version = "1.1.0"
dependencies = [
"itertools 0.10.5",
"text-size",
]
[[package]]
name = "elp_types_db"
version = "1.1.0"

View file

@ -30,13 +30,9 @@ elp_ide_ssr = { path = "./crates/ide_ssr" }
elp_log = { path = "./crates/elp_log" }
elp_project_model = { path = "./crates/project_model" }
elp_syntax = { path = "./crates/syntax" }
elp_text_edit = { path = "./crates/text_edit" }
elp_types_db = { path = "./crates/types_db" }
hir = { path = "./crates/hir" }
# Forks
erl_ast = { path = "./crates/erl_ast" }
# External crates
trie-rs = "0.4.2"
always-assert = "0.1.3"

View file

@ -1,60 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is dual-licensed under either the MIT license found in the
* LICENSE-MIT file in the root directory of this source tree or the Apache
* License, Version 2.0 found in the LICENSE-APACHE file in the root directory
* of this source tree. You may select, at your option, one of the
* above-listed licenses.
*/
use std::thread;
use std::time;
use criterion::BenchmarkId;
use criterion::Criterion;
use criterion::criterion_group;
use criterion::criterion_main;
fn fibonacci_slow(n: u64) -> u64 {
match n {
0 => 1,
1 => 1,
n => fibonacci_slow(n - 1) + fibonacci_slow(n - 2),
}
}
fn fibonacci_fast(n: u64) -> u64 {
let mut a = 0;
let mut b = 1;
let millis = time::Duration::from_millis(12);
thread::sleep(millis);
match n {
0 => b,
_ => {
for _ in 0..n {
let c = a + b;
a = b;
b = c;
}
b
}
}
}
fn bench_fibs(c: &mut Criterion) {
let mut group = c.benchmark_group("Fibonacci");
for i in [20u64, 21u64].iter() {
group.bench_with_input(BenchmarkId::new("Recursive", i), i, |b, i| {
b.iter(|| fibonacci_slow(*i))
});
group.bench_with_input(BenchmarkId::new("Iterative", i), i, |b, i| {
b.iter(|| fibonacci_fast(*i))
});
}
group.finish();
}
criterion_group!(benches, bench_fibs);
criterion_main!(benches);

View file

@ -1,16 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is dual-licensed under either the MIT license found in the
* LICENSE-MIT file in the root directory of this source tree or the Apache
* License, Version 2.0 found in the LICENSE-APACHE file in the root directory
* of this source tree. You may select, at your option, one of the
* above-listed licenses.
*/
use std::env;
fn main() {
let args: Vec<String> = env::args().collect();
println!("ARGS: {:?}", args);
}

View file

@ -87,6 +87,7 @@ pub trait WithFixture: Default + SourceDatabaseExt + 'static {
let (fixture, change) = ChangeFixture::parse(fixture_str);
let mut db = Self::default();
change.apply(&mut db, &|path| fixture.resolve_file_id(path));
fixture.validate(&db);
(db, fixture)
}
}
@ -101,6 +102,7 @@ pub struct ChangeFixture {
pub diagnostics_enabled: DiagnosticsEnabled,
pub tags: FxHashMap<FileId, Vec<(TextRange, Option<String>)>>,
pub annotations: FxHashMap<FileId, Vec<(TextRange, String)>>,
pub expect_parse_errors: bool,
}
struct Builder {
@ -172,6 +174,7 @@ impl ChangeFixture {
let FixtureWithProjectMeta {
fixture,
mut diagnostics_enabled,
expect_parse_errors,
} = fixture_with_meta.clone();
let builder = Builder::new(diagnostics_enabled.clone());
@ -344,6 +347,7 @@ impl ChangeFixture {
diagnostics_enabled,
tags,
annotations,
expect_parse_errors,
},
change,
project,
@ -405,6 +409,64 @@ impl ChangeFixture {
.get(&VfsPath::from(path.clone()))
.cloned()
}
/// Validate all files in the fixture for syntax errors.
/// Panics with context if any syntax errors are found.
/// Skips validation if `expect_parse_errors` is set to true.
#[track_caller]
pub fn validate<DB: SourceDatabaseExt>(&self, db: &DB) {
if self.expect_parse_errors {
return;
}
let mut errors_found = Vec::new();
for file_id in &self.files {
let parse = db.parse(*file_id);
let errors = parse.errors();
if !errors.is_empty() {
let path = self
.files_by_path
.iter()
.find_map(|(vfs_path, id)| {
if id == file_id {
Some(
vfs_path
.as_path()
.map(|p| p.to_string())
.unwrap_or_else(|| format!("{:?}", vfs_path)),
)
} else {
None
}
})
.unwrap_or_else(|| format!("FileId({:?})", file_id));
let file_text = SourceDatabaseExt::file_text(db, *file_id);
let tree = parse.tree();
errors_found.push((path, file_text.to_string(), errors.to_vec(), tree));
}
}
if !errors_found.is_empty() {
let mut message =
String::from("Fixture validation failed: syntax errors found in test fixture\n\n");
for (path, text, errors, tree) in errors_found {
message.push_str(&format!("File: {}\n", path));
message.push_str(&format!("Errors: {:?}\n", errors));
message.push_str(&format!("Content:\n{}\n", text));
message.push_str(&format!("Parse Tree:\n{:#?}\n", tree));
message.push_str("---\n");
}
message.push_str(
"If this is expected, add `//- expect_parse_errors` to the start of the fixture\n",
);
panic!("{}", message);
}
}
}
fn inc_file_id(file_id: &mut FileId) {

View file

@ -32,7 +32,7 @@ mod module_index;
// Public API
pub mod fixture;
// @fb-only
// @fb-only: mod meta_only;
pub mod test_utils;
pub use change::Change;
pub use elp_project_model::AppType;
@ -476,7 +476,7 @@ static ref IGNORED_SOURCES: Vec<Regex> = {
let regexes: Vec<Vec<Regex>> = vec![
vec![Regex::new(r"^.*_SUITE_data/.+$").unwrap()],
//ignore sources goes here
// @fb-only
// @fb-only: meta_only::ignored_sources_regexes()
];
regexes.into_iter().flatten().collect::<Vec<Regex>>()
};

View file

@ -18,10 +18,10 @@ workspace = true
[dependencies]
elp_eqwalizer.workspace = true
elp_ide.workspace = true
elp_ide_db.workspace = true
elp_log.workspace = true
elp_project_model.workspace = true
elp_syntax.workspace = true
elp_text_edit.workspace = true
hir.workspace = true
always-assert.workspace = true

View file

@ -8,8 +8,8 @@
* above-listed licenses.
*/
// @fb-only
// @fb-only
// @fb-only: /// Types as defined in https://www.internalfb.com/intern/wiki/Linting/adding-linters/#flow-type
// @fb-only: /// and https://www.internalfb.com/code/fbsource/[1238f73dac0efd4009443fee6a345a680dc9401b]/whatsapp/server/erl/tools/lint/arcanist.py?lines=17
use std::path::Path;
use serde::Serialize;

View file

@ -11,6 +11,7 @@
use std::cmp::Ordering;
use std::env;
use std::fs;
use std::io::IsTerminal;
use std::path::PathBuf;
use anyhow::Result;
@ -71,6 +72,17 @@ pub struct ParseAllElp {
/// Report system memory usage and other statistics
#[bpaf(long("report-system-stats"))]
pub report_system_stats: bool,
/// Minimum severity level to report. Valid values: error, warning, weak_warning, information
#[bpaf(
argument("SEVERITY"),
complete(severity_completer),
fallback(None),
guard(
severity_guard,
"Please use error, warning, weak_warning, or information"
)
)]
pub severity: Option<String>,
}
#[derive(Clone, Debug, Bpaf)]
@ -143,8 +155,6 @@ pub struct EqwalizeAll {
/// Also eqwalize opted-in generated modules from project (deprecated)
#[bpaf(hide)]
pub include_generated: bool,
/// Also eqwalize test modules from project
pub include_tests: bool,
/// Exit with a non-zero status code if any errors are found
pub bail_on_error: bool,
/// Print statistics when done
@ -161,8 +171,6 @@ pub struct EqwalizeTarget {
/// Also eqwalize opted-in generated modules from application (deprecated)
#[bpaf(hide)]
pub include_generated: bool,
/// Also eqwalize test modules from project
pub include_tests: bool,
/// Exit with a non-zero status code if any errors are found
pub bail_on_error: bool,
/// target, like //erl/chatd/...
@ -181,8 +189,6 @@ pub struct EqwalizeApp {
/// Also eqwalize opted-in generated modules from project (deprecated)
#[bpaf(hide)]
pub include_generated: bool,
/// Also eqwalize test modules from project
pub include_tests: bool,
/// Run with rebar
pub rebar: bool,
/// Exit with a non-zero status code if any errors are found
@ -205,8 +211,6 @@ pub struct EqwalizeStats {
/// Also eqwalize opted-in generated modules from project (deprecated)
#[bpaf(hide)]
pub include_generated: bool,
/// Also eqwalize test modules from project
pub include_tests: bool,
/// If specified, use the provided CLI severity mapping instead of the default one
pub use_cli_severity: bool,
}
@ -274,8 +278,6 @@ pub struct Lint {
guard(format_guard, "Please use json")
)]
pub format: Option<String>,
/// Optional prefix to prepend to each diagnostic file path. Only used when --format=json is set
pub prefix: Option<String>,
/// Include diagnostics produced by erlc
pub include_erlc_diagnostics: bool,
@ -332,6 +334,9 @@ pub struct Lint {
#[bpaf(long("report-system-stats"))]
pub report_system_stats: bool,
/// Disable streaming of diagnostics when applying fixes (collect all before printing)
pub no_stream: bool,
/// Rest of args are space separated list of apps to ignore
#[bpaf(positional("IGNORED_APPS"))]
pub ignore_apps: Vec<String>,
@ -386,6 +391,33 @@ pub struct Ssr {
#[bpaf(long("parens"))]
pub paren_strategy: bool,
/// Dump a configuration snippet that can be put in .elp_lint.toml to match the given SSR patterns
pub dump_config: bool,
/// Show source code context for matches
#[bpaf(long("show-source"))]
pub show_source: bool,
/// Print NUM lines of leading context, enables --show-source
#[bpaf(short('B'), long("before-context"), argument("NUM"))]
pub before_context: Option<usize>,
/// Print NUM lines of trailing context, enables --show-source
#[bpaf(short('A'), long("after-context"), argument("NUM"))]
pub after_context: Option<usize>,
/// Print NUM lines of output context, enables --show-source
#[bpaf(short('C'), long("context"), argument("NUM"))]
pub context: Option<usize>,
/// Print SEP on line between matches with context, enables --show-source
#[bpaf(long("group-separator"), argument("SEP"))]
pub group_separator: Option<String>,
/// Do not print separator for matches with context, enables --show-source
#[bpaf(long("no-group-separator"))]
pub no_group_separator: bool,
/// Report system memory usage and other statistics
#[bpaf(long("report-system-stats"))]
pub report_system_stats: bool,
@ -442,8 +474,6 @@ pub struct Glean {
pub pretty: bool,
/// Output each fact separately
pub multi: bool,
/// Optional prefix to prepend to each fact
pub prefix: Option<String>,
}
#[derive(Clone, Debug, Bpaf)]
@ -490,6 +520,16 @@ pub struct Args {
/// Use buck2 targets for first stage project loading
pub buck_quick_start: bool,
/// Use color in output; WHEN is 'always', 'never', or 'auto'
#[bpaf(
long("color"),
long("colour"),
argument("WHEN"),
fallback(Some("always".to_string())),
guard(color_guard, "Please use always, never, or auto")
)]
pub color: Option<String>,
#[bpaf(external(command))]
pub command: Command,
}
@ -504,6 +544,20 @@ impl Args {
BuckQueryConfig::BuildGeneratedCode
}
}
/// Determine if color should be used based on the --color argument
pub fn should_use_color(&self) -> bool {
match self.color.as_deref() {
Some("always") => true,
Some("never") => false,
Some("auto") | None => {
// Check NO_COLOR environment variable - if set (regardless of value), disable color
// Also check if stdout is connected to a TTY
env::var("NO_COLOR").is_err() && std::io::stdout().is_terminal()
}
_ => false, // Should be caught by the guard, but handle anyway
}
}
}
pub fn command() -> impl Parser<Command> {
@ -575,6 +629,12 @@ pub fn command() -> impl Parser<Command> {
.command("lint")
.help("Parse files in project and emit diagnostics, optionally apply fixes.");
let search = ssr()
.map(Command::Ssr)
.to_options()
.command("search")
.help("Alias for 'ssr': Run SSR (Structural Search and Replace) pattern matching on project files.");
let ssr = ssr()
.map(Command::Ssr)
.to_options()
@ -636,6 +696,7 @@ pub fn command() -> impl Parser<Command> {
dialyze_all,
lint,
ssr,
search,
parse_all,
parse_elp,
explain,
@ -725,6 +786,25 @@ fn format_guard(format: &Option<String>) -> bool {
}
}
fn severity_completer(_: &Option<String>) -> Vec<(String, Option<String>)> {
vec![
("error".to_string(), None),
("warning".to_string(), None),
("weak_warning".to_string(), None),
("information".to_string(), None),
]
}
fn severity_guard(severity: &Option<String>) -> bool {
match severity {
None => true,
Some(s) if s == "error" || s == "warning" || s == "weak_warning" || s == "information" => {
true
}
_ => false,
}
}
fn macros_completer(_: &Option<String>) -> Vec<(String, Option<String>)> {
vec![
("expand".to_string(), None),
@ -740,6 +820,14 @@ fn macros_guard(format: &Option<String>) -> bool {
}
}
fn color_guard(color: &Option<String>) -> bool {
match color {
None => true,
Some(c) if c == "always" || c == "never" || c == "auto" => true,
_ => false,
}
}
#[allow(clippy::ptr_arg)] // This is needed in the BPAF macros
fn at_least_1(data: &Vec<String>) -> bool {
!data.is_empty()
@ -820,6 +908,11 @@ impl Lint {
pub fn is_format_json(&self) -> bool {
self.format == Some("json".to_string())
}
/// To prevent flaky test results we allow disabling streaming when applying fixes
pub fn skip_stream_print(&self) -> bool {
self.apply_fix || self.no_stream
}
}
fn parse_macro_strategy(macro_strategy: &Option<String>) -> Result<MacroStrategy> {

View file

@ -24,7 +24,6 @@ use elp::cli::Cli;
use elp::convert;
use elp::memory_usage::MemoryUsage;
use elp::otp_file_to_ignore;
use elp::server::file_id_to_url;
use elp_eqwalizer::Mode;
use elp_ide::Analysis;
use elp_ide::diagnostics;
@ -58,6 +57,35 @@ use crate::args::ParseAllElp;
use crate::reporting;
use crate::reporting::print_memory_usage;
fn parse_severity(severity: &str) -> Option<diagnostics::Severity> {
match severity {
"error" => Some(diagnostics::Severity::Error),
"warning" => Some(diagnostics::Severity::Warning),
"weak_warning" => Some(diagnostics::Severity::WeakWarning),
"information" => Some(diagnostics::Severity::Information),
_ => None,
}
}
fn severity_rank(severity: diagnostics::Severity) -> u8 {
match severity {
diagnostics::Severity::Error => 1,
diagnostics::Severity::Warning => 2,
diagnostics::Severity::WeakWarning => 3,
diagnostics::Severity::Information => 4,
}
}
fn meets_severity_threshold(
diag_severity: diagnostics::Severity,
min_severity: Option<diagnostics::Severity>,
) -> bool {
match min_severity {
None => true,
Some(min) => severity_rank(diag_severity) <= severity_rank(min),
}
}
#[derive(Debug)]
struct ParseResult {
name: String,
@ -132,8 +160,7 @@ pub fn parse_all(
(None, _, true) => do_parse_all_seq(cli, &loaded, &cfg, &args.to)?,
(None, _, false) => do_parse_all_par(cli, &loaded, &cfg, &args.to)?,
(Some(file_id), Some(name), _) => {
do_parse_one(&analysis, &loaded.vfs, &cfg, &args.to, file_id, &name)?
.map_or(vec![], |x| vec![x])
do_parse_one(&analysis, &cfg, &args.to, file_id, &name)?.map_or(vec![], |x| vec![x])
}
(Some(file_id), _, _) => panic!("Could not get name from file_id for {file_id:?}"),
};
@ -144,15 +171,24 @@ pub fn parse_all(
let db = loaded.analysis_host.raw_database();
// We need a `Url` for converting to the lsp_types::Diagnostic for
// printing, but do not print it out. So just create a dummy value
let url = lsp_types::Url::parse("file:///unused_url").ok().unwrap();
telemetry::report_elapsed_time("parse-elp operational", start_time);
let memory_end = MemoryUsage::now();
let memory_used = memory_end - memory_start;
let min_severity = args
.severity
.as_ref()
.and_then(|s| parse_severity(s.as_str()));
res.retain(|parse_result| {
parse_result
.diagnostics
.diagnostics_for(parse_result.file_id)
.iter()
.any(|diag| meets_severity_threshold(diag.severity, min_severity))
});
if res.is_empty() {
if args.is_format_normal() {
writeln!(cli, "No errors reported")?;
@ -171,6 +207,7 @@ pub fn parse_all(
for diags in res {
let mut combined: Vec<diagnostics::Diagnostic> =
diags.diagnostics.diagnostics_for(diags.file_id);
combined.retain(|diag| meets_severity_threshold(diag.severity, min_severity));
if args.is_format_normal() {
writeln!(cli, " {}: {}", diags.name, combined.len())?;
}
@ -197,7 +234,7 @@ pub fn parse_all(
cli,
)?;
} else {
print_diagnostic(&diag, &line_index, &url, &mut err_in_diag, cli)?;
print_diagnostic(&diag, &line_index, &mut err_in_diag, cli)?;
}
}
}
@ -242,11 +279,10 @@ fn print_diagnostic_json(
fn print_diagnostic(
diag: &diagnostics::Diagnostic,
line_index: &LineIndex,
url: &lsp_types::Url,
err_in_diag: &mut bool,
cli: &mut dyn Cli,
) -> Result<(), anyhow::Error> {
let diag = convert::ide_to_lsp_diagnostic(line_index, url, diag);
let diag = convert::ide_to_lsp_diagnostic(line_index, diag, |_file_id| None);
let severity = match diag.severity {
None => DiagnosticSeverity::ERROR,
Some(sev) => {
@ -289,7 +325,6 @@ fn do_parse_all_par(
let pb = cli.progress(module_iter.len() as u64, "Parsing modules");
let vfs = &loaded.vfs;
Ok(module_iter
.par_bridge()
.progress_with(pb)
@ -300,7 +335,7 @@ fn do_parse_all_par(
&& file_source == FileSource::Src
&& db.file_app_type(file_id).ok() != Some(Some(AppType::Dep))
{
do_parse_one(db, vfs, config, to, file_id, module_name.as_str()).unwrap()
do_parse_one(db, config, to, file_id, module_name.as_str()).unwrap()
} else {
None
}
@ -321,7 +356,6 @@ fn do_parse_all_seq(
let pb = cli.progress(module_iter.len() as u64, "Parsing modules (sequential)");
let vfs = &loaded.vfs;
let db = loaded.analysis();
Ok(module_iter
.progress_with(pb)
@ -330,7 +364,7 @@ fn do_parse_all_seq(
&& file_source == FileSource::Src
&& db.file_app_type(file_id).ok() != Some(Some(AppType::Dep))
{
do_parse_one(&db, vfs, config, to, file_id, module_name.as_str()).unwrap()
do_parse_one(&db, config, to, file_id, module_name.as_str()).unwrap()
} else {
None
}
@ -340,13 +374,11 @@ fn do_parse_all_seq(
fn do_parse_one(
db: &Analysis,
vfs: &Vfs,
config: &DiagnosticsConfig,
to: &Option<PathBuf>,
file_id: FileId,
name: &str,
) -> Result<Option<ParseResult>> {
let url = file_id_to_url(vfs, file_id);
let native = db.native_diagnostics(config, &vec![], file_id)?;
let erlang_service_diagnostics =
db.erlang_service_diagnostics(file_id, config, RemoveElpReported::Yes)?;
@ -364,11 +396,13 @@ fn do_parse_one(
let mut output = File::create(to_path)?;
for diagnostic in native.iter() {
let diagnostic = convert::ide_to_lsp_diagnostic(&line_index, &url, diagnostic);
let diagnostic =
convert::ide_to_lsp_diagnostic(&line_index, diagnostic, |_file_id| None);
writeln!(output, "{diagnostic:?}")?;
}
for diagnostic in erlang_service.iter() {
let diagnostic = convert::ide_to_lsp_diagnostic(&line_index, &url, diagnostic);
let diagnostic =
convert::ide_to_lsp_diagnostic(&line_index, diagnostic, |_file_id| None);
writeln!(output, "{diagnostic:?}")?;
}
}

View file

@ -186,10 +186,7 @@ pub fn do_eqwalize_all(
.par_bridge()
.progress_with(pb.clone())
.map_with(analysis.clone(), |analysis, (name, _source, file_id)| {
if analysis
.should_eqwalize(file_id, args.include_tests)
.unwrap()
&& !otp_file_to_ignore(analysis, file_id)
if analysis.should_eqwalize(file_id).unwrap() && !otp_file_to_ignore(analysis, file_id)
{
if args.stats {
add_stat(name.to_string());
@ -269,9 +266,7 @@ pub fn do_eqwalize_app(
.iter_own()
.filter_map(|(_name, _source, file_id)| {
if analysis.file_app_name(file_id).ok()? == Some(AppName(args.app.clone()))
&& analysis
.should_eqwalize(file_id, args.include_tests)
.unwrap()
&& analysis.should_eqwalize(file_id).unwrap()
&& !otp_file_to_ignore(analysis, file_id)
{
Some(file_id)
@ -339,9 +334,7 @@ pub fn eqwalize_target(
let vfs_path = VfsPath::from(src.clone());
if let Some((file_id, _)) = loaded.vfs.file_id(&vfs_path) {
at_least_one_found = true;
if analysis
.should_eqwalize(file_id, args.include_tests)
.unwrap()
if analysis.should_eqwalize(file_id).unwrap()
&& !otp_file_to_ignore(analysis, file_id)
{
file_ids.push(file_id);
@ -408,9 +401,7 @@ pub fn eqwalize_stats(
.par_bridge()
.progress_with(pb.clone())
.map_with(analysis.clone(), |analysis, (name, _source, file_id)| {
if analysis
.should_eqwalize(file_id, args.include_tests)
.expect("cancelled")
if analysis.should_eqwalize(file_id).expect("cancelled")
&& !otp_file_to_ignore(analysis, file_id)
{
analysis
@ -482,8 +473,6 @@ fn eqwalize(
bail!("No files to eqWAlize detected")
}
pre_parse_for_speed(reporter, analysis.clone(), &file_ids);
let files_count = file_ids.len();
let pb = reporter.progress(files_count as u64, "EqWAlizing");
let output = loaded.with_eqwalizer_progress_bar(pb.clone(), move |analysis| {
@ -602,17 +591,6 @@ fn eqwalize(
}
}
fn pre_parse_for_speed(reporter: &dyn Reporter, analysis: Analysis, file_ids: &[FileId]) {
let pb = reporter.progress(file_ids.len() as u64, "Parsing modules");
file_ids
.par_iter()
.progress_with(pb.clone())
.for_each_with(analysis, |analysis, &file_id| {
let _ = analysis.module_ast(file_id);
});
pb.finish();
}
fn set_eqwalizer_config(loaded: &mut LoadResult) {
let config = EqwalizerConfig::default();
let db = loaded.analysis_host.raw_database_mut();

View file

@ -150,14 +150,15 @@ pub fn do_parse_one(
.chain(result.warnings.iter())
.map(|err| {
let relative_path: &Path = err.path.strip_prefix(root_dir).unwrap_or(&err.path);
let (range, line_num) = match err.location {
let (range, line_num) = match &err.location {
None => (None, convert::position(&line_index, 0.into()).line + 1),
Some(DiagnosticLocation::Normal(range)) => (
Some(range),
convert::position(&line_index, range.start()).line + 1,
),
Some(DiagnosticLocation::Included {
directive_location,
file_attribute_location: directive_location,
error_path: _,
error_location: _,
}) => (
Some(directive_location),
@ -169,7 +170,7 @@ pub fn do_parse_one(
relative_path: relative_path.to_owned(),
line_num,
msg: err.msg.to_owned(),
range,
range: range.copied(),
}
})
.collect();

View file

@ -11,7 +11,6 @@
use core::option::Option::None;
use std::io::Write;
use std::mem;
use std::path::Path;
use anyhow::Result;
use elp::build::load;
@ -85,7 +84,7 @@ const REC_ARITY: u32 = 99;
const HEADER_ARITY: u32 = 100;
const FACTS_FILE: &str = "facts.json";
// @fb-only
// @fb-only: mod meta_only;
#[derive(Serialize, Debug, Eq, Hash, PartialEq, Clone)]
struct GleanFileId(u32);
@ -93,7 +92,6 @@ struct GleanFileId(u32);
#[derive(Clone, Debug, Default)]
struct IndexConfig {
pub multi: bool,
pub prefix: Option<String>,
}
impl From<GleanFileId> for FileId {
@ -769,10 +767,7 @@ pub struct GleanIndexer {
pub fn index(args: &Glean, cli: &mut dyn Cli, query_config: &BuckQueryConfig) -> Result<()> {
let (indexer, _loaded) = GleanIndexer::new(args, cli, query_config)?;
let config = IndexConfig {
multi: args.multi,
prefix: args.prefix.clone(),
};
let config = IndexConfig { multi: args.multi };
let (facts, module_index) = indexer.index(config)?;
write_results(facts, module_index, cli, args)
}
@ -861,14 +856,7 @@ impl GleanIndexer {
let source_root_id = db.file_source_root(file_id);
let source_root = db.source_root(source_root_id);
let path = source_root.path_for_file(&file_id).unwrap();
match Self::index_file(
db,
file_id,
path,
project_id,
&module_index,
config.prefix.as_ref(),
) {
match Self::index_file(db, file_id, path, project_id, &module_index) {
Some((file, line, decl, xref, facts, module_fact)) => {
let mut result = FxHashMap::default();
result.insert(
@ -884,14 +872,7 @@ impl GleanIndexer {
.into_par_iter()
.map_with(self.analysis.clone(), |analysis, (file_id, path)| {
analysis.with_db(|db| {
Self::index_file(
db,
file_id,
&path,
project_id,
&module_index,
config.prefix.as_ref(),
)
Self::index_file(db, file_id, &path, project_id, &module_index)
})
})
.flatten()
@ -948,7 +929,6 @@ impl GleanIndexer {
path: &VfsPath,
project_id: ProjectId,
module_index: &FxHashMap<GleanFileId, String>,
prefix: Option<&String>,
) -> Option<(
FileFact,
FileLinesFact,
@ -957,7 +937,7 @@ impl GleanIndexer {
Option<(Vec<FunctionDeclarationFact>, XRefFact)>,
Option<ModuleFact>,
)> {
let file_fact = Self::file_fact(db, file_id, path, project_id, prefix)?;
let file_fact = Self::file_fact(db, file_id, path, project_id)?;
let line_fact = Self::line_fact(db, file_id);
let mut xref_v2 = Self::xrefs_v2(db, file_id, module_index);
let mut file_decl = Self::declarations_v2(db, file_id, path)?;
@ -1014,7 +994,7 @@ impl GleanIndexer {
.filter(|text| !text.is_empty())
});
// @fb-only
// @fb-only: let exdoc_link = elp_ide::meta_only::exdoc_links::module_exdoc_link(&module, &sema);
let exdoc_link: Option<String> = None; // @oss-only
ModuleFact::new(
@ -1173,16 +1153,12 @@ impl GleanIndexer {
file_id: FileId,
path: &VfsPath,
project_id: ProjectId,
prefix: Option<&String>,
) -> Option<FileFact> {
let project_data = db.project_data(project_id);
let root = project_data.root_dir.as_path();
let file_path = path.as_path()?;
let file_path = file_path.strip_prefix(root)?;
let file_path = match prefix {
Some(prefix) => Path::new(&prefix).join(file_path).to_str()?.into(),
None => file_path.as_str().to_string(),
};
let file_path = file_path.as_str().to_string();
Some(FileFact::new(file_id, file_path))
}
@ -1556,7 +1532,7 @@ impl GleanIndexer {
}) => {
let def = macro_def.as_ref()?;
let mut resolved = Self::resolve_macro_v2(sema, def, source_file, ctx)?;
// @fb-only
// @fb-only: meta_only::resolve_macro_expansion(sema, *expansion, ctx, &mut resolved);
Some(resolved)
}
hir::AnyExpr::Pat(Pat::MacroCall { macro_def, .. })
@ -1584,7 +1560,7 @@ impl GleanIndexer {
vars: FxHashMap<&Location, &String>,
) -> Vec<VarDecl> {
let mut result = vec![];
if !db.is_eqwalizer_enabled(file_id, false) {
if !db.is_eqwalizer_enabled(file_id) {
return result;
}
let module_diagnostics = db.eqwalizer_diagnostics_by_project(project_id, vec![file_id]);
@ -1899,9 +1875,9 @@ impl GleanIndexer {
let source_file = sema.parse(file_id);
let range = Self::find_range(sema, ctx, &source_file, &expr_source)?;
// @fb-only
// @fb-only
// @fb-only
// @fb-only: use elp_ide::meta_only::wam_links;
// @fb-only: let wam_ctx = wam_links::WamEventCtx::new(sema.db.upcast());
// @fb-only: let wam_url = wam_ctx.build_wam_link(name).map(|link| link.url());
let wam_url = None; // @oss-only
Some(XRef {
@ -2063,7 +2039,6 @@ mod tests {
v2: true,
pretty: false,
multi: false,
prefix: None,
};
let mut module_index = FxHashMap::default();
module_index.insert(file_id.into(), module_name.to_string());
@ -2090,25 +2065,6 @@ mod tests {
);
}
#[test]
fn file_fact_prefix_test() {
let spec = r#"
//- /glean/app_glean/src/glean_module2.erl
-module(glean_module2).
"#;
let config = IndexConfig {
multi: false,
prefix: Some("my/prefix".to_string()),
};
let result = facts_with_annotations_with_config(spec, config).0;
assert_eq!(result.file_facts.len(), 1);
let file_fact = &result.file_facts[0];
assert_eq!(
file_fact.file_path.as_str(),
"my/prefix/glean/app_glean/src/glean_module2.erl"
);
}
#[test]
fn line_fact_with_new_line_test() {
let spec = r#"
@ -2379,10 +2335,10 @@ mod tests {
fn xref_types_test() {
let spec = r#"
//- /glean/app_glean/src/glean_module81.erl
-type small() :: #{non_neg_integer() | infinity}.
-type small() :: {non_neg_integer() | infinity}.
//- /glean/app_glean/src/glean_module8.erl
-type huuuge() :: #{non_neg_integer() | infinity}.
-type huuuge() :: {non_neg_integer() | infinity}.
-spec baz(
A :: huuuge(),
%% ^^^^^^ glean_module8/huuuge/0
@ -2437,10 +2393,10 @@ mod tests {
fn xref_types_v2_test() {
let spec = r#"
//- /glean/app_glean/src/glean_module81.erl
-type small() :: #{non_neg_integer() | infinity}.
-type small() :: {non_neg_integer() | infinity}.
//- /glean/app_glean/src/glean_module8.erl
-type huuuge() :: #{non_neg_integer() | infinity}.
-type huuuge() :: {non_neg_integer() | infinity}.
-spec baz(
A :: huuuge(),
%% ^^^^^^ glean_module8.erl/type/huuuge/0

View file

@ -13,13 +13,14 @@ use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
use std::str;
use std::sync::Arc;
use std::thread;
use std::time::SystemTime;
use anyhow::Result;
use anyhow::bail;
use crossbeam_channel::unbounded;
use elp::build::load;
use elp::build::types::LoadResult;
use elp::cli::Cli;
@ -52,17 +53,16 @@ use elp_ide::elp_ide_db::elp_base_db::ProjectId;
use elp_ide::elp_ide_db::elp_base_db::Vfs;
use elp_ide::elp_ide_db::elp_base_db::VfsPath;
use elp_ide::elp_ide_db::source_change::SourceChange;
use elp_ide_db::text_edit::TextSize;
use elp_log::telemetry;
use elp_project_model::AppName;
use elp_project_model::AppType;
use elp_project_model::DiscoverConfig;
use elp_project_model::buck::BuckQueryConfig;
use elp_text_edit::TextSize;
use fxhash::FxHashMap;
use fxhash::FxHashSet;
use hir::FormIdx;
use hir::InFile;
use indicatif::ParallelProgressIterator;
use itertools::Itertools;
use paths::Utf8PathBuf;
use rayon::prelude::ParallelBridge;
@ -132,47 +132,101 @@ pub fn load_project(
)
}
fn do_parse_all(
cli: &dyn Cli,
fn do_diagnostics_all(
cli: &mut dyn Cli,
analysis: &Analysis,
project_id: &ProjectId,
config: &DiagnosticsConfig,
args: &Lint,
) -> Result<Vec<(String, FileId, DiagnosticCollection)>> {
loaded: &LoadResult,
module: &Option<String>,
) -> Result<(Vec<(String, FileId, DiagnosticCollection)>, bool, bool)> {
let module_index = analysis.module_index(*project_id).unwrap();
let module_iter = module_index.iter_own();
let ignored_apps: FxHashSet<Option<Option<AppName>>> = args
.ignore_apps
.iter()
.map(|name| Some(Some(AppName(name.to_string()))))
.collect();
let pb = cli.progress(module_iter.len() as u64, "Parsing modules");
let app_name = args.app.as_ref().map(|name| AppName(name.to_string()));
Ok(module_iter
.par_bridge()
.progress_with(pb)
.map_with(
analysis.clone(),
|db, (module_name, _file_source, file_id)| {
if !otp_file_to_ignore(db, file_id)
&& db.file_app_type(file_id).ok() != Some(Some(AppType::Dep))
&& !ignored_apps.contains(&db.file_app_name(file_id).ok())
&& (app_name.is_none()
|| db.file_app_name(file_id).ok().as_ref() == Some(&app_name))
{
do_parse_one(db, config, file_id, module_name.as_str(), args).unwrap()
} else {
None
}
},
)
.flatten()
.collect())
// Create a channel for streaming results
let (tx, rx) = unbounded();
// Collect modules into an owned vector
let modules: Vec<_> = module_index
.iter_own()
.map(|(name, source, file_id)| (name.as_str().to_string(), source, file_id))
.collect();
let analysis_clone = analysis.clone();
let config_clone = config.clone();
let args_clone = args.clone();
let join_handle = thread::spawn(move || {
modules
.into_iter()
.par_bridge()
.map_with(
(analysis_clone, tx),
|(db, tx), (module_name, _file_source, file_id)| {
if !otp_file_to_ignore(db, file_id)
&& db.file_app_type(file_id).ok() != Some(Some(AppType::Dep))
&& !ignored_apps.contains(&db.file_app_name(file_id).ok())
&& (app_name.is_none()
|| db.file_app_name(file_id).ok().as_ref() == Some(&app_name))
&& let Ok(Some(result)) = do_diagnostics_one(
db,
&config_clone,
file_id,
&module_name,
&args_clone,
)
{
// Send result through channel
let _ = tx.send(result);
}
},
)
.for_each(|_| {}); // Consume the iterator
});
// Collect results as they arrive from the channel
let mut results = Vec::new();
let mut err_in_diag = false;
let mut module_count = 0;
let mut any_diagnostics_printed = false;
for result in rx {
let printed = if args.skip_stream_print() {
false
} else {
print_diagnostic_result(
cli,
analysis,
config,
args,
loaded,
module,
&mut err_in_diag,
&mut module_count,
&result,
)?
};
any_diagnostics_printed = any_diagnostics_printed || printed;
results.push(result);
}
// Wait for the thread to complete before returning
// This ensures that analysis_clone is dropped and its read lock is released
join_handle
.join()
.expect("Failed to join diagnostics thread");
Ok((results, err_in_diag, any_diagnostics_printed))
}
fn do_parse_one(
fn do_diagnostics_one(
db: &Analysis,
config: &DiagnosticsConfig,
file_id: FileId,
@ -239,6 +293,8 @@ pub fn do_codemod(
) -> Result<()> {
// Declare outside the block so it has the right lifetime for filter_diagnostics
let res;
let streamed_err_in_diag;
let mut any_diagnostics_printed = false;
let mut initial_diags = {
// We put this in its own block so that analysis is
// freed before we apply lints. To apply lints
@ -279,7 +335,18 @@ pub fn do_codemod(
res = match (file_id, name) {
(None, _) => {
do_parse_all(cli, &analysis, &loaded.project_id, diagnostics_config, args)?
let (results, err_in_diag, any_printed) = do_diagnostics_all(
cli,
&analysis,
&loaded.project_id,
diagnostics_config,
args,
loaded,
&args.module,
)?;
streamed_err_in_diag = err_in_diag;
any_diagnostics_printed = any_printed;
results
}
(Some(file_id), Some(name)) => {
if let Some(app) = &args.app
@ -288,87 +355,124 @@ pub fn do_codemod(
{
panic!("Module {} does not belong to app {}", name.as_str(), app)
}
do_parse_one(&analysis, diagnostics_config, file_id, &name, args)?
.map_or(vec![], |x| vec![x])
let result =
do_diagnostics_one(&analysis, diagnostics_config, file_id, &name, args)?
.map_or(vec![], |x| vec![x]);
// Print diagnostics for the single file
let mut err_in_diag = false;
let mut module_count = 0;
if args.skip_stream_print() {
any_diagnostics_printed = false;
} else {
for r in &result {
let printed = print_diagnostic_result(
cli,
&analysis,
diagnostics_config,
args,
loaded,
&args.module,
&mut err_in_diag,
&mut module_count,
r,
)?;
any_diagnostics_printed = any_diagnostics_printed || printed;
}
}
streamed_err_in_diag = err_in_diag;
result
}
(Some(file_id), _) => {
panic!("Could not get name from file_id for {file_id:?}")
}
};
filter_diagnostics(
&analysis,
&args.module,
Some(&diagnostics_config.enabled),
&res,
&FxHashSet::default(),
)?
res
};
if initial_diags.is_empty() {
if args.is_format_normal() {
writeln!(cli, "No diagnostics reported")?;
}
} else {
initial_diags.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
let mut err_in_diag = false;
if args.is_format_json() {
for (_name, file_id, diags) in &initial_diags {
if args.print_diags {
for diag in diags {
// We use JSON output for CI, and want to see warnings too.
// So do not filter on errors only
err_in_diag = true;
let vfs_path = loaded.vfs.file_path(*file_id);
let analysis = loaded.analysis();
let root_path = &analysis
.project_data(*file_id)
.unwrap_or_else(|_err| panic!("could not find project data"))
.unwrap_or_else(|| panic!("could not find project data"))
.root_dir;
let relative_path = reporting::get_relative_path(root_path, vfs_path);
let prefix = args.prefix.as_ref();
print_diagnostic_json(
diag,
&analysis,
*file_id,
with_prefix(relative_path, prefix).as_path(),
args.use_cli_severity,
cli,
)?;
}
}
}
} else {
writeln!(
cli,
"Diagnostics reported in {} modules:",
initial_diags.len()
)?;
let mut err_in_diag = streamed_err_in_diag;
// At this point, the analysis variable from above is dropped
for (name, file_id, diags) in &initial_diags {
writeln!(cli, " {}: {}", name, diags.len())?;
if args.print_diags {
for diag in diags {
if let diagnostics::Severity::Error = diag.severity {
err_in_diag = true;
};
print_diagnostic(
diag,
&loaded.analysis(),
*file_id,
args.use_cli_severity,
cli,
)?;
}
}
}
// When streaming is disabled (--no-stream) and we're not applying fixes,
// we need to print diagnostics now since they weren't printed during streaming
if args.no_stream && !args.apply_fix && !initial_diags.is_empty() {
let analysis = loaded.analysis();
let mut module_count = 0;
initial_diags.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
for result in &initial_diags {
let printed = print_diagnostic_result(
cli,
&analysis,
diagnostics_config,
args,
loaded,
&args.module,
&mut err_in_diag,
&mut module_count,
result,
)?;
any_diagnostics_printed = any_diagnostics_printed || printed;
}
if args.apply_fix && diagnostics_config.enabled.all_enabled() {
}
// Handle apply_fix case separately since it needs to filter diagnostics anyway
if args.apply_fix {
if diagnostics_config.enabled.all_enabled() {
bail!(
"We cannot apply fixes if all diagnostics enabled. Perhaps provide --diagnostic-filter"
);
}
if args.apply_fix && !diagnostics_config.enabled.all_enabled() {
let mut filtered_diags = {
let analysis = loaded.analysis();
filter_diagnostics(
&analysis,
&args.module,
Some(&diagnostics_config.enabled),
&initial_diags,
&FxHashSet::default(),
)?
};
if filtered_diags.is_empty() {
if args.is_format_normal() {
writeln!(cli, "No diagnostics reported")?;
}
} else {
if args.skip_stream_print() {
filtered_diags.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
let module_count: &mut i32 = &mut 0;
let has_diagnostics: &mut bool = &mut false;
if args.is_format_json() {
do_print_diagnostics_json_filtered(
cli,
args,
loaded,
&mut err_in_diag,
module_count,
has_diagnostics,
&filtered_diags,
)?;
} else {
{
// Scope the analysis instance to ensure it's dropped before creating Lints
let analysis = loaded.analysis();
do_print_diagnostics_filtered(
cli,
&analysis,
args,
loaded,
&mut err_in_diag,
module_count,
has_diagnostics,
&filtered_diags,
)?;
// Analysis is dropped here
}
}
}
let mut changed_files = FxHashSet::default();
let mut lints = Lints::new(
&mut loaded.analysis_host,
@ -376,7 +480,7 @@ pub fn do_codemod(
&mut loaded.vfs,
args,
&mut changed_files,
initial_diags,
filtered_diags,
);
// We handle the fix application result here, so
// the overall status of whether error-severity
@ -388,14 +492,225 @@ pub fn do_codemod(
writeln!(cli, "Apply fix failed: {err:#}").ok();
}
};
if err_in_diag {
bail!("Errors found")
}
}
if err_in_diag {
} else {
// Non-apply-fix case: rely on any_diagnostics_printed which is set
// correctly based on filtered diagnostics during streaming/batch printing
if !any_diagnostics_printed {
if args.is_format_normal() {
writeln!(cli, "No diagnostics reported")?;
}
} else if err_in_diag {
bail!("Errors found")
}
}
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn print_diagnostic_result(
cli: &mut dyn Cli,
analysis: &Analysis,
config: &DiagnosticsConfig,
args: &Lint,
loaded: &LoadResult,
module: &Option<String>,
err_in_diag: &mut bool,
module_count: &mut i32,
result: &(String, FileId, DiagnosticCollection),
) -> Result<bool> {
if args.is_format_json() {
do_print_diagnostic_collection_json(
cli,
analysis,
config,
args,
loaded,
module,
err_in_diag,
module_count,
result,
)
} else {
do_print_diagnostic_collection(
cli,
analysis,
config,
args,
loaded,
module,
err_in_diag,
module_count,
result,
)
}
}
#[allow(clippy::too_many_arguments)]
fn do_print_diagnostic_collection(
cli: &mut dyn Cli,
analysis: &Analysis,
config: &DiagnosticsConfig,
args: &Lint,
loaded: &LoadResult,
module: &Option<String>,
err_in_diag: &mut bool,
module_count: &mut i32,
result: &(String, FileId, DiagnosticCollection),
) -> Result<bool> {
let single_result = vec![result.clone()];
let mut has_diagnostics = false;
if let Ok(filtered) = filter_diagnostics(
analysis,
module,
Some(&config.enabled),
&single_result,
&FxHashSet::default(),
) {
do_print_diagnostics_filtered(
cli,
analysis,
args,
loaded,
err_in_diag,
module_count,
&mut has_diagnostics,
&filtered,
)?;
}
Ok(has_diagnostics)
}
#[allow(clippy::too_many_arguments)]
fn do_print_diagnostics_filtered(
cli: &mut dyn Cli,
analysis: &Analysis,
args: &Lint,
loaded: &LoadResult,
err_in_diag: &mut bool,
module_count: &mut i32,
has_diagnostics: &mut bool,
filtered: &[(String, FileId, Vec<diagnostics::Diagnostic>)],
) -> Result<(), anyhow::Error> {
let _: () = for (name, file_id, diags) in filtered {
if !diags.is_empty() {
*has_diagnostics = true;
if *module_count == 0 {
writeln!(cli, "Diagnostics reported:")?;
}
*module_count += 1;
if !args.print_diags {
writeln!(cli, " {}: {}", name, diags.len())?;
} else {
for diag in diags {
if let diagnostics::Severity::Error = diag.severity {
*err_in_diag = true;
};
// Get relative path for diagnostic output
let vfs_path = loaded.vfs.file_path(*file_id);
let root_path = &analysis
.project_data(*file_id)
.unwrap_or_else(|_err| panic!("could not find project data"))
.unwrap_or_else(|| panic!("could not find project data"))
.root_dir;
let relative_path = reporting::get_relative_path(root_path, vfs_path);
print_diagnostic(
diag,
analysis,
&loaded.vfs,
*file_id,
Some(relative_path),
args.use_cli_severity,
cli,
)?;
}
}
}
};
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn do_print_diagnostic_collection_json(
cli: &mut dyn Cli,
analysis: &Analysis,
config: &DiagnosticsConfig,
args: &Lint,
loaded: &LoadResult,
module: &Option<String>,
err_in_diag: &mut bool,
module_count: &mut i32,
result: &(String, FileId, DiagnosticCollection),
) -> Result<bool> {
let single_result = vec![result.clone()];
let mut has_diagnostics = false;
if let Ok(filtered) = filter_diagnostics(
analysis,
module,
Some(&config.enabled),
&single_result,
&FxHashSet::default(),
) {
do_print_diagnostics_json_filtered(
cli,
args,
loaded,
err_in_diag,
module_count,
&mut has_diagnostics,
&filtered,
)?;
}
Ok(has_diagnostics)
}
fn do_print_diagnostics_json_filtered(
cli: &mut dyn Cli,
args: &Lint,
loaded: &LoadResult,
err_in_diag: &mut bool,
module_count: &mut i32,
has_diagnostics: &mut bool,
filtered: &[(String, FileId, Vec<diagnostics::Diagnostic>)],
) -> Result<(), anyhow::Error> {
let _: () = for (name, file_id, diags) in filtered {
if !diags.is_empty() {
*has_diagnostics = true;
*module_count += 1;
if !args.print_diags {
writeln!(cli, " {}: {}", name, diags.len())?;
} else {
for diag in diags {
*err_in_diag = true;
// Get relative path for diagnostic output
let vfs_path = loaded.vfs.file_path(*file_id);
let analysis = loaded.analysis();
let root_path = &analysis
.project_data(*file_id)
.unwrap_or_else(|_err| panic!("could not find project data"))
.unwrap_or_else(|| panic!("could not find project data"))
.root_dir;
let relative_path = reporting::get_relative_path(root_path, vfs_path);
print_diagnostic_json(
diag,
&analysis,
*file_id,
relative_path,
args.use_cli_severity,
cli,
)?;
}
}
}
};
Ok(())
}
fn get_diagnostics_config(args: &Lint) -> Result<DiagnosticsConfig> {
let cfg_from_file = if args.read_config || args.config_file.is_some() {
read_lint_config_file(&args.project, &args.config_file)?
@ -421,12 +736,82 @@ fn get_diagnostics_config(args: &Lint) -> Result<DiagnosticsConfig> {
fn print_diagnostic(
diag: &diagnostics::Diagnostic,
analysis: &Analysis,
vfs: &Vfs,
file_id: FileId,
path: Option<&Path>,
use_cli_severity: bool,
cli: &mut dyn Cli,
) -> Result<(), anyhow::Error> {
let line_index = analysis.line_index(file_id)?;
writeln!(cli, " {}", diag.print(&line_index, use_cli_severity))?;
let diag_str = diag.print(&line_index, use_cli_severity);
if let Some(path) = path {
writeln!(cli, "{}:{}", path.display(), diag_str)?;
} else {
writeln!(cli, " {}", diag_str)?;
}
// Print any related information, indented
if let Some(related_info) = &diag.related_info {
for info in related_info {
let info_line_index = analysis.line_index(info.file_id)?;
let start = info_line_index.line_col(info.range.start());
let end = info_line_index.line_col(info.range.end());
// Include file identifier if related info is from a different file
if info.file_id != file_id {
let file_identifier =
if let Ok(Some(module_name)) = analysis.module_name(info.file_id) {
// It's a module (.erl file), use module name
format!("[{}]", module_name.as_str())
} else {
// Not a module (e.g., include file), use relative path
let vfs_path = vfs.file_path(info.file_id);
if let Ok(Some(project_data)) = analysis.project_data(info.file_id) {
let relative_path =
reporting::get_relative_path(&project_data.root_dir, vfs_path);
format!("[{}]", relative_path.display())
} else {
// Fallback: just show location without file identifier
String::new()
}
};
if file_identifier.is_empty() {
writeln!(
cli,
" {}:{}-{}:{}: {}",
start.line + 1,
start.col_utf16 + 1,
end.line + 1,
end.col_utf16 + 1,
info.message
)?;
} else {
writeln!(
cli,
" {} {}:{}-{}:{}: {}",
file_identifier,
start.line + 1,
start.col_utf16 + 1,
end.line + 1,
end.col_utf16 + 1,
info.message
)?;
}
} else {
writeln!(
cli,
" {}:{}-{}:{}: {}",
start.line + 1,
start.col_utf16 + 1,
end.line + 1,
end.col_utf16 + 1,
info.message
)?;
}
}
}
Ok(())
}
@ -611,13 +996,10 @@ impl<'a> Lints<'a> {
if self.args.check_eqwalize_all {
writeln!(cli, "Running eqwalize-all to check for knock-on problems.")?;
}
let diags = do_parse_one(
&self.analysis_host.analysis(),
self.cfg,
file_id,
&name,
self.args,
)?;
let diags = {
let analysis = self.analysis_host.analysis();
do_diagnostics_one(&analysis, self.cfg, file_id, &name, self.args)?
};
let err_in_diags = diags.iter().any(|(_, file_id, diags)| {
let diags = diags.diagnostics_for(*file_id);
diags
@ -628,14 +1010,15 @@ impl<'a> Lints<'a> {
bail!("Applying change introduces an error diagnostic");
} else {
self.changed_files.insert((file_id, name.clone()));
let changes = changes
.iter()
.filter_map(|d| {
form_from_diff(&self.analysis_host.analysis(), file_id, d)
})
.collect::<Vec<_>>();
let changed_forms = {
let analysis = self.analysis_host.analysis();
changes
.iter()
.filter_map(|d| form_from_diff(&analysis, file_id, d))
.collect::<Vec<_>>()
};
for form_id in &changes {
for form_id in &changed_forms {
self.changed_forms.insert(InFile::new(file_id, *form_id));
}
@ -648,24 +1031,24 @@ impl<'a> Lints<'a> {
.flatten()
.collect::<Vec<_>>();
let new_diagnostics = filter_diagnostics(
&self.analysis_host.analysis(),
&None,
None,
&new_diags,
&self.changed_forms,
)?;
let new_diagnostics = {
let analysis = self.analysis_host.analysis();
filter_diagnostics(&analysis, &None, None, &new_diags, &self.changed_forms)?
};
self.diags = diagnostics_by_file_id(&new_diagnostics);
if !self.diags.is_empty() {
writeln!(cli, "---------------------------------------------\n")?;
writeln!(cli, "New filtered diagnostics")?;
let analysis = self.analysis_host.analysis();
for (file_id, (name, diags)) in &self.diags {
writeln!(cli, " {}: {}", name, diags.len())?;
for diag in diags.iter() {
print_diagnostic(
diag,
&self.analysis_host.analysis(),
&analysis,
self.vfs,
*file_id,
None,
self.args.use_cli_severity,
cli,
)?;
@ -737,10 +1120,13 @@ impl<'a> Lints<'a> {
if format_normal {
writeln!(cli, "---------------------------------------------\n")?;
writeln!(cli, "Applying fix in module '{name}' for")?;
let analysis = self.analysis_host.analysis();
print_diagnostic(
diagnostic,
&self.analysis_host.analysis(),
&analysis,
self.vfs,
file_id,
None,
self.args.use_cli_severity,
cli,
)?;
@ -807,7 +1193,9 @@ impl<'a> Lints<'a> {
print_diagnostic(
&diagnostic,
&self.analysis_host.analysis(),
self.vfs,
file_id,
None,
self.args.use_cli_severity,
cli,
)?;
@ -942,13 +1330,6 @@ fn get_form_id_at_offset(
Some(form_id)
}
fn with_prefix(path: &Path, prefix: Option<&String>) -> PathBuf {
match prefix {
Some(prefix) => Path::new(prefix).join(path),
None => path.into(),
}
}
#[cfg(test)]
mod tests {
use std::ffi::OsString;
@ -1088,11 +1469,11 @@ mod tests {
head_mismatcX(0) -> 0.
"#,
expect![[r#"
module specified: lints
Diagnostics reported in 1 modules:
lints: 1
4:2-4:15::[Error] [P1700] head mismatch 'head_mismatcX' vs 'head_mismatch'
"#]],
module specified: lints
Diagnostics reported:
app_a/src/lints.erl:5:3-5:16::[Error] [P1700] head mismatch 'head_mismatcX' vs 'head_mismatch'
4:3-4:16: Mismatched clause name
"#]],
expect![""],
);
}
@ -1109,9 +1490,8 @@ mod tests {
"#,
expect![[r#"
module specified: lints
Diagnostics reported in 1 modules:
lints: 1
2:2-2:5::[Warning] [L1230] function foo/0 is unused
Diagnostics reported:
app_a/src/lints.erl:3:3-3:6::[Warning] [L1230] function foo/0 is unused
"#]],
expect![""],
);

File diff suppressed because it is too large Load diff

View file

@ -227,9 +227,6 @@ impl Reporter for JsonReporter<'_> {
diagnostics: &[EqwalizerDiagnostic],
) -> Result<()> {
let line_index = self.analysis.line_index(file_id)?;
// Pass include_Tests = false so that errors for tests files that are not opted-in are tagged as
// arc_types::Severity::Disabled and don't break CI.
let eqwalizer_enabled = self.analysis.is_eqwalizer_enabled(file_id, false).unwrap();
let file_path = &self.loaded.vfs.file_path(file_id);
let root_path = &self
.analysis
@ -238,12 +235,8 @@ impl Reporter for JsonReporter<'_> {
.root_dir;
let relative_path = get_relative_path(root_path, file_path);
for diagnostic in diagnostics {
let diagnostic = convert::eqwalizer_to_arc_diagnostic(
diagnostic,
&line_index,
relative_path,
eqwalizer_enabled,
);
let diagnostic =
convert::eqwalizer_to_arc_diagnostic(diagnostic, &line_index, relative_path);
let diagnostic = serde_json::to_string(&diagnostic)?;
writeln!(self.cli, "{diagnostic}")?;
}

View file

@ -157,10 +157,9 @@ impl ShellCommand {
}
"eqwalize-app" => {
let include_generated = options.contains(&"--include-generated");
let include_tests = options.contains(&"--include-tests");
if let Some(other) = options
.into_iter()
.find(|&opt| opt != "--include-generated" && opt != "--include-tests")
.find(|&opt| opt != "--include-generated")
{
return Err(ShellError::UnexpectedOption(
"eqwalize-app".into(),
@ -177,7 +176,6 @@ impl ShellCommand {
rebar,
app: app.into(),
include_generated,
include_tests,
bail_on_error: false,
})));
}
@ -185,10 +183,9 @@ impl ShellCommand {
}
"eqwalize-all" => {
let include_generated = options.contains(&"--include-generated");
let include_tests = options.contains(&"--include-tests");
if let Some(other) = options
.into_iter()
.find(|&opt| opt != "--include-generated" && opt != "--include-tests")
.find(|&opt| opt != "--include-generated")
{
return Err(ShellError::UnexpectedOption(
"eqwalize-all".into(),
@ -204,7 +201,6 @@ impl ShellCommand {
rebar,
format: None,
include_generated,
include_tests,
bail_on_error: false,
stats: false,
list_modules: false,
@ -226,10 +222,8 @@ COMMANDS:
eqwalize <modules> Eqwalize specified modules
--clause-coverage Use experimental clause coverage checker
eqwalize-all Eqwalize all modules in the current project
--include-tests Also eqwalize test modules from project
--clause-coverage Use experimental clause coverage checker
eqwalize-app <app> Eqwalize all modules in specified application
--include-tests Also eqwalize test modules from project
--clause-coverage Use experimental clause coverage checker
";

View file

@ -11,10 +11,12 @@
use std::fs;
use std::path::Path;
use std::str;
use std::thread;
use std::time::SystemTime;
use anyhow::Result;
use anyhow::bail;
use crossbeam_channel::unbounded;
use elp::build::load;
use elp::build::types::LoadResult;
use elp::cli::Cli;
@ -28,7 +30,9 @@ use elp_ide::diagnostics;
use elp_ide::diagnostics::DiagnosticsConfig;
use elp_ide::diagnostics::FallBackToAll;
use elp_ide::diagnostics::LintConfig;
use elp_ide::diagnostics::LintsFromConfig;
use elp_ide::diagnostics::MatchSsr;
use elp_ide::elp_ide_db::LineCol;
use elp_ide::elp_ide_db::elp_base_db::AbsPath;
use elp_ide::elp_ide_db::elp_base_db::FileId;
use elp_ide::elp_ide_db::elp_base_db::IncludeOtp;
@ -41,7 +45,6 @@ use elp_project_model::AppType;
use elp_project_model::DiscoverConfig;
use elp_project_model::buck::BuckQueryConfig;
use hir::Semantic;
use indicatif::ParallelProgressIterator;
use paths::Utf8PathBuf;
use rayon::prelude::ParallelBridge;
use rayon::prelude::ParallelIterator;
@ -62,6 +65,7 @@ pub fn run_ssr_command(
args: &Ssr,
cli: &mut dyn Cli,
query_config: &BuckQueryConfig,
use_color: bool,
) -> Result<()> {
let start_time = SystemTime::now();
let memory_start = MemoryUsage::now();
@ -85,10 +89,17 @@ pub fn run_ssr_command(
let mut lint_config = LintConfig::default();
for pattern in &args.ssr_specs {
let normalized_pattern = normalize_ssr_pattern(pattern);
let severity = if args.dump_config {
// Set the severity so that squiggles are shown in the VS Code UI
Some(diagnostics::Severity::Information)
} else {
None
};
let ssr_lint = diagnostics::Lint::LintMatchSsr(MatchSsr {
ssr_pattern: normalized_pattern,
message: None,
strategy: Some(strategy),
severity,
});
lint_config.ad_hoc_lints.lints.push(ssr_lint);
}
@ -105,15 +116,20 @@ pub fn run_ssr_command(
.set_experimental(false)
.set_use_cli_severity(false);
if diagnostics_config.enabled.all_enabled() && args.is_format_normal() {
writeln!(cli, "Reporting all diagnostics codes")?;
if args.dump_config {
let result = toml::to_string::<LintsFromConfig>(&diagnostics_config.lints_from_config)?;
// This is a subsection of .elp_lint.toml, add subsection prefix
let result = result.replace("[[lints]]", "[[ad_hoc_lints.lints]]");
writeln!(cli, "\n# Add this to your .elp_lint.toml")?;
writeln!(cli, "{}", result)?;
return Ok(());
}
// Load the project
let mut loaded = load_project(args, cli, query_config)?;
telemetry::report_elapsed_time("ssr operational", start_time);
let r = run_ssr(cli, &mut loaded, &diagnostics_config, args);
let r = run_ssr(cli, &mut loaded, &diagnostics_config, args, use_color);
telemetry::report_elapsed_time("ssr done", start_time);
@ -133,6 +149,7 @@ pub fn run_ssr(
loaded: &mut LoadResult,
diagnostics_config: &DiagnosticsConfig,
args: &Ssr,
use_color: bool,
) -> Result<()> {
let analysis = loaded.analysis();
let (file_id, name) = match &args.module {
@ -166,8 +183,23 @@ pub fn run_ssr(
},
};
let mut diags = match (file_id, name) {
(None, _) => do_parse_all(cli, &analysis, &loaded.project_id, diagnostics_config, args)?,
let mut match_count = 0;
match (file_id, name) {
(None, _) => {
// Streaming case: process all modules
let project_id = loaded.project_id;
do_parse_all_streaming(
cli,
&analysis,
&project_id,
diagnostics_config,
args,
use_color,
loaded,
&mut match_count,
)?;
}
(Some(file_id), Some(name)) => {
if let Some(app) = &args.app
&& let Ok(Some(file_app)) = analysis.file_app_name(file_id)
@ -175,42 +207,171 @@ pub fn run_ssr(
{
panic!("Module {} does not belong to app {}", name.as_str(), app)
}
do_parse_one(&analysis, diagnostics_config, file_id, &name, args)?
.map_or(vec![], |x| vec![x])
if let Some(diag) = do_parse_one(&analysis, diagnostics_config, file_id, &name, args)? {
match_count = 1;
print_single_result(cli, loaded, &diag, args, use_color)?;
}
}
(Some(file_id), _) => {
panic!("Could not get name from file_id for {file_id:?}")
}
};
if diags.is_empty() {
if match_count == 0 {
if args.is_format_normal() {
writeln!(cli, "No matches found")?;
}
} else if args.is_format_normal() {
writeln!(cli, "\nMatches found in {} modules", match_count)?;
}
Ok(())
}
#[allow(clippy::too_many_arguments)]
fn do_parse_all_streaming(
cli: &mut dyn Cli,
analysis: &Analysis,
project_id: &ProjectId,
config: &DiagnosticsConfig,
args: &Ssr,
use_color: bool,
loaded: &mut LoadResult,
match_count: &mut usize,
) -> Result<()> {
let module_index = analysis.module_index(*project_id).unwrap();
let app_name = args.app.as_ref().map(|name| AppName(name.to_string()));
// Create a channel for streaming results
let (tx, rx) = unbounded();
// Spawn a thread to process modules in parallel and send results
let analysis_clone = analysis.clone();
let config_clone = config.clone();
let args_clone = args.clone();
// Collect modules into an owned vector
let modules: Vec<_> = module_index
.iter_own()
.map(|(name, source, file_id)| (name.as_str().to_string(), source, file_id))
.collect();
thread::spawn(move || {
modules
.into_iter()
.par_bridge()
.map_with(
(analysis_clone, tx),
|(db, tx), (module_name, _file_source, file_id)| {
if !otp_file_to_ignore(db, file_id)
&& db.file_app_type(file_id).ok() != Some(Some(AppType::Dep))
&& (app_name.is_none()
|| db.file_app_name(file_id).ok().as_ref() == Some(&app_name))
&& let Ok(Some(result)) =
do_parse_one(db, &config_clone, file_id, &module_name, &args_clone)
{
// Send result through channel
let _ = tx.send(result);
}
},
)
.for_each(|_| {}); // Consume the iterator
// Channel is dropped here, signaling end of results
});
// Process and print results as they arrive from the channel
for result in rx {
*match_count += 1;
print_single_result(cli, loaded, &result, args, use_color)?;
}
Ok(())
}
fn print_single_result(
cli: &mut dyn Cli,
loaded: &mut LoadResult,
result: &(String, FileId, Vec<diagnostics::Diagnostic>),
args: &Ssr,
use_color: bool,
) -> Result<()> {
let (name, file_id, diags) = result;
if args.is_format_json() {
for diag in diags {
let vfs_path = loaded.vfs.file_path(*file_id);
let analysis = loaded.analysis();
let root_path = &analysis
.project_data(*file_id)
.unwrap_or_else(|_err| panic!("could not find project data"))
.unwrap_or_else(|| panic!("could not find project data"))
.root_dir;
let relative_path = reporting::get_relative_path(root_path, vfs_path);
print_diagnostic_json(diag, &analysis, *file_id, relative_path, false, cli)?;
}
} else {
diags.sort_by(|(a, _, _), (b, _, _)| a.cmp(b));
if args.is_format_json() {
for (_name, file_id, diags) in &diags {
for diag in diags {
// We use JSON output for CI, and want to see warnings too.
// So do not filter on errors only
let vfs_path = loaded.vfs.file_path(*file_id);
let analysis = loaded.analysis();
let root_path = &analysis
.project_data(*file_id)
.unwrap_or_else(|_err| panic!("could not find project data"))
.unwrap_or_else(|| panic!("could not find project data"))
.root_dir;
let relative_path = reporting::get_relative_path(root_path, vfs_path);
print_diagnostic_json(diag, &analysis, *file_id, relative_path, false, cli)?;
}
writeln!(cli, " {}: {}", name, diags.len())?;
// Determine if we should show source context
let show_source = args.show_source
|| args.before_context.is_some()
|| args.after_context.is_some()
|| args.context.is_some()
|| args.group_separator.is_some()
|| args.no_group_separator;
let (before_lines, after_lines) = calculate_context_lines(args);
let has_context = before_lines > 0 || after_lines > 0;
let group_separator = should_show_group_separator(args, has_context && show_source);
for (idx, diag) in diags.iter().enumerate() {
// Print group separator before each match (except the first) if showing source with context
if show_source
&& idx > 0
&& let Some(ref sep) = group_separator
{
writeln!(cli, "{}", sep)?;
}
} else {
writeln!(cli, "Matches found in {} modules:", diags.len())?;
for (name, file_id, diags) in &diags {
writeln!(cli, " {}: {}", name, diags.len())?;
for diag in diags {
print_diagnostic(diag, &loaded.analysis(), *file_id, false, cli)?;
// Get relative path for diagnostic output
let vfs_path = loaded.vfs.file_path(*file_id);
let analysis = loaded.analysis();
let root_path = &analysis
.project_data(*file_id)
.unwrap_or_else(|_err| panic!("could not find project data"))
.unwrap_or_else(|| panic!("could not find project data"))
.root_dir;
let relative_path = reporting::get_relative_path(root_path, vfs_path);
// Only show path when showing source context
let path_to_show = if show_source {
Some(relative_path)
} else {
None
};
print_diagnostic(diag, &loaded.analysis(), *file_id, path_to_show, false, cli)?;
// Only show source context if --show-source or --show-source-markers is set
if show_source {
if use_color {
print_source_with_context(
diag,
&loaded.analysis(),
*file_id,
before_lines,
after_lines,
true,
cli,
)?;
} else {
print_source_with_context_markers(
diag,
&loaded.analysis(),
*file_id,
before_lines,
after_lines,
cli,
)?;
}
writeln!(cli)?;
}
}
}
@ -233,41 +394,6 @@ fn load_project(
query_config,
)
}
fn do_parse_all(
cli: &dyn Cli,
analysis: &Analysis,
project_id: &ProjectId,
config: &DiagnosticsConfig,
args: &Ssr,
) -> Result<Vec<(String, FileId, Vec<diagnostics::Diagnostic>)>> {
let module_index = analysis.module_index(*project_id).unwrap();
let module_iter = module_index.iter_own();
let pb = cli.progress(module_iter.len() as u64, "Scanning modules");
let app_name = args.app.as_ref().map(|name| AppName(name.to_string()));
Ok(module_iter
.par_bridge()
.progress_with(pb)
.map_with(
analysis.clone(),
|db, (module_name, _file_source, file_id)| {
if !otp_file_to_ignore(db, file_id)
&& db.file_app_type(file_id).ok() != Some(Some(AppType::Dep))
&& (app_name.is_none()
|| db.file_app_name(file_id).ok().as_ref() == Some(&app_name))
{
do_parse_one(db, config, file_id, module_name.as_str(), args).unwrap()
} else {
None
}
},
)
.flatten()
.collect())
}
fn do_parse_one(
db: &Analysis,
config: &DiagnosticsConfig,
@ -275,6 +401,9 @@ fn do_parse_one(
name: &str,
args: &Ssr,
) -> Result<Option<(String, FileId, Vec<diagnostics::Diagnostic>)>> {
if !args.include_generated && db.is_generated(file_id)? {
return Ok(None);
}
if !args.include_tests && db.is_test_suite_or_test_helper(file_id)?.unwrap_or(false) {
return Ok(None);
}
@ -286,7 +415,6 @@ fn do_parse_one(
config
.lints_from_config
.get_diagnostics(&mut diags, &sema, file_id);
sema.parse(file_id);
diags
})?;
@ -302,11 +430,17 @@ fn print_diagnostic(
diag: &diagnostics::Diagnostic,
analysis: &Analysis,
file_id: FileId,
path: Option<&Path>,
use_cli_severity: bool,
cli: &mut dyn Cli,
) -> Result<(), anyhow::Error> {
let line_index = analysis.line_index(file_id)?;
writeln!(cli, " {}", diag.print(&line_index, use_cli_severity))?;
let diag_str = diag.print(&line_index, use_cli_severity);
if let Some(path) = path {
writeln!(cli, "{}:{}", path.display(), diag_str)?;
} else {
writeln!(cli, " {}", diag_str)?;
}
Ok(())
}
@ -330,3 +464,254 @@ fn print_diagnostic_json(
)?;
Ok(())
}
/// Print a line with color highlighting
fn print_line_with_color(
line_num: usize,
line_content: &str,
is_match_line: bool,
start: &LineCol,
end: &LineCol,
current_line: u32,
cli: &mut dyn Cli,
) -> Result<(), anyhow::Error> {
// Line number in gray
write!(cli, "\x1b[90m{:4} |\x1b[0m ", line_num)?;
if !is_match_line {
// Non-match line: print normally
writeln!(cli, "{}", line_content)?;
} else {
// Match line: highlight the matched portion
if current_line == start.line && current_line == end.line {
// Single-line match
let start_col = start.col_utf16 as usize;
let end_col = end.col_utf16 as usize;
let before = &line_content[..start_col.min(line_content.len())];
let matched =
&line_content[start_col.min(line_content.len())..end_col.min(line_content.len())];
let after = &line_content[end_col.min(line_content.len())..];
write!(cli, "{}", before)?;
write!(cli, "\x1b[91;1m{}\x1b[0m", matched)?; // Red bold
writeln!(cli, "{}", after)?;
} else if current_line == start.line {
// First line of multi-line match
let start_col = start.col_utf16 as usize;
let before = &line_content[..start_col.min(line_content.len())];
let matched = &line_content[start_col.min(line_content.len())..];
write!(cli, "{}", before)?;
writeln!(cli, "\x1b[91;1m{}\x1b[0m", matched)?; // Red bold
} else if current_line == end.line {
// Last line of multi-line match
let end_col = end.col_utf16 as usize;
let matched = &line_content[..end_col.min(line_content.len())];
let after = &line_content[end_col.min(line_content.len())..];
write!(cli, "\x1b[91;1m{}\x1b[0m", matched)?; // Red bold
writeln!(cli, "{}", after)?;
} else {
// Middle line of multi-line match
writeln!(cli, "\x1b[91;1m{}\x1b[0m", line_content)?; // Red bold
}
}
Ok(())
}
/// Calculate context lines from the new grep-style arguments
fn calculate_context_lines(args: &Ssr) -> (usize, usize) {
// -C/--context takes precedence and sets both before and after
if let Some(context) = args.context {
return (context, context);
}
// Otherwise use individual before/after values, defaulting to 0
let before = args.before_context.unwrap_or(0);
let after = args.after_context.unwrap_or(0);
(before, after)
}
/// Determine if a group separator should be shown
fn should_show_group_separator(args: &Ssr, has_context: bool) -> Option<String> {
// If --no-group-separator is set, don't show separator
if args.no_group_separator {
return None;
}
// Only show separators if there's context to separate
if !has_context {
return None;
}
// Use custom separator if provided, otherwise default to "--"
Some(
args.group_separator
.clone()
.unwrap_or_else(|| "--".to_string()),
)
}
/// Print source code context with the specified before/after context lines
fn print_source_with_context(
diag: &diagnostics::Diagnostic,
analysis: &Analysis,
file_id: FileId,
before_lines: usize,
after_lines: usize,
use_color: bool,
cli: &mut dyn Cli,
) -> Result<(), anyhow::Error> {
let line_index = analysis.line_index(file_id)?;
let source = &analysis.file_text(file_id)?;
let range = diag.range;
let start = line_index.line_col(range.start());
let end = line_index.line_col(range.end());
let lines: Vec<&str> = source.lines().collect();
let total_lines = lines.len();
// Calculate the range of lines to display
let first_line = start.line.saturating_sub(before_lines as u32) as usize;
let last_line = ((end.line + after_lines as u32 + 1) as usize).min(total_lines);
// Display the source context
for line_idx in first_line..last_line {
let line_num = line_idx + 1;
let line_content = lines.get(line_idx).unwrap_or(&"");
// Check if this line contains part of the match
let is_match_line = line_idx >= start.line as usize && line_idx <= end.line as usize;
if use_color {
print_line_with_color(
line_num,
line_content,
is_match_line,
&start,
&end,
line_idx as u32,
cli,
)?;
} else {
// Just print the line without any highlighting
write!(cli, "{:4} | ", line_num)?;
writeln!(cli, "{}", line_content)?;
}
}
Ok(())
}
/// Print source code context with text markers
fn print_source_with_context_markers(
diag: &diagnostics::Diagnostic,
analysis: &Analysis,
file_id: FileId,
before_lines: usize,
after_lines: usize,
cli: &mut dyn Cli,
) -> Result<(), anyhow::Error> {
let line_index = analysis.line_index(file_id)?;
let source = &analysis.file_text(file_id)?;
let range = diag.range;
let start = line_index.line_col(range.start());
let end = line_index.line_col(range.end());
let lines: Vec<&str> = source.lines().collect();
let total_lines = lines.len();
// Calculate the range of lines to display
let first_line = start.line.saturating_sub(before_lines as u32) as usize;
let last_line = ((end.line + after_lines as u32 + 1) as usize).min(total_lines);
// Display the source context
for line_idx in first_line..last_line {
let line_num = line_idx + 1;
let line_content = lines.get(line_idx).unwrap_or(&"");
// Check if this line contains part of the match
let is_match_line = line_idx >= start.line as usize && line_idx <= end.line as usize;
print_line_with_markers(
line_num,
line_content,
is_match_line,
&start,
&end,
line_idx as u32,
cli,
)?;
}
Ok(())
}
/// Print a line with text markers (like diagnostic carets)
fn print_line_with_markers(
line_num: usize,
line_content: &str,
is_match_line: bool,
start: &LineCol,
end: &LineCol,
current_line: u32,
cli: &mut dyn Cli,
) -> Result<(), anyhow::Error> {
// Line number
write!(cli, "{:4} | ", line_num)?;
writeln!(cli, "{}", line_content)?;
if is_match_line {
// Print marker line with ^^^ under the match
write!(cli, " | ")?; // Indent to match line content
if current_line == start.line && current_line == end.line {
// Single-line match
let start_col = start.col_utf16 as usize;
let end_col = end.col_utf16 as usize;
let marker_len = (end_col - start_col).max(1);
// Spaces before the marker
for _ in 0..start_col {
write!(cli, " ")?;
}
// Marker carets
for _ in 0..marker_len {
write!(cli, "^")?;
}
writeln!(cli)?;
} else if current_line == start.line {
// First line of multi-line match
let start_col = start.col_utf16 as usize;
let marker_len = line_content.len().saturating_sub(start_col).max(1);
for _ in 0..start_col {
write!(cli, " ")?;
}
for _ in 0..marker_len {
write!(cli, "^")?;
}
writeln!(cli)?;
} else if current_line == end.line {
// Last line of multi-line match
let end_col = end.col_utf16 as usize;
for _ in 0..end_col {
write!(cli, "^")?;
}
writeln!(cli)?;
} else {
// Middle line of multi-line match
for _ in 0..line_content.len() {
write!(cli, "^")?;
}
writeln!(cli)?;
}
}
Ok(())
}

View file

@ -30,18 +30,13 @@ pub trait Cli: Write + WriteColor {
fn err(&mut self) -> &mut dyn Write;
}
pub struct Real(StandardStream, Stderr);
pub struct StandardCli(StandardStream, Stderr);
impl Default for Real {
fn default() -> Self {
Self(
StandardStream::stdout(ColorChoice::Always),
std::io::stderr(),
)
impl StandardCli {
fn new(color_choice: ColorChoice) -> Self {
Self(StandardStream::stdout(color_choice), std::io::stderr())
}
}
impl Real {
fn progress_with_style(
&self,
len: u64,
@ -59,7 +54,7 @@ impl Real {
}
}
impl Cli for Real {
impl Cli for StandardCli {
fn progress(&self, len: u64, prefix: &'static str) -> ProgressBar {
self.progress_with_style(len, prefix, " {prefix:25!} {bar} {pos}/{len} {wide_msg}")
}
@ -84,6 +79,63 @@ impl Cli for Real {
}
}
impl Write for StandardCli {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.0.flush()
}
}
impl WriteColor for StandardCli {
fn supports_color(&self) -> bool {
self.0.supports_color()
}
fn set_color(&mut self, spec: &ColorSpec) -> std::io::Result<()> {
self.0.set_color(spec)
}
fn reset(&mut self) -> std::io::Result<()> {
self.0.reset()
}
}
pub struct Real(StandardCli);
pub struct NoColor(StandardCli);
impl Default for Real {
fn default() -> Self {
Real(StandardCli::new(ColorChoice::Always))
}
}
impl Default for NoColor {
fn default() -> Self {
NoColor(StandardCli::new(ColorChoice::Never))
}
}
impl Cli for Real {
fn progress(&self, len: u64, prefix: &'static str) -> ProgressBar {
self.0.progress(len, prefix)
}
fn simple_progress(&self, len: u64, prefix: &'static str) -> ProgressBar {
self.0.simple_progress(len, prefix)
}
fn spinner(&self, prefix: &'static str) -> ProgressBar {
self.0.spinner(prefix)
}
fn err(&mut self) -> &mut dyn Write {
self.0.err()
}
}
impl Write for Real {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.0.write(buf)
@ -108,6 +160,48 @@ impl WriteColor for Real {
}
}
impl Cli for NoColor {
fn progress(&self, len: u64, prefix: &'static str) -> ProgressBar {
self.0.progress(len, prefix)
}
fn simple_progress(&self, len: u64, prefix: &'static str) -> ProgressBar {
self.0.simple_progress(len, prefix)
}
fn spinner(&self, prefix: &'static str) -> ProgressBar {
self.0.spinner(prefix)
}
fn err(&mut self) -> &mut dyn Write {
self.0.err()
}
}
impl Write for NoColor {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.0.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.0.flush()
}
}
impl WriteColor for NoColor {
fn supports_color(&self) -> bool {
self.0.supports_color()
}
fn set_color(&mut self, spec: &ColorSpec) -> std::io::Result<()> {
self.0.set_color(spec)
}
fn reset(&mut self) -> std::io::Result<()> {
self.0.reset()
}
}
pub struct Fake(Buffer, Vec<u8>);
impl Default for Fake {

View file

@ -30,7 +30,7 @@ use serde::de::DeserializeOwned;
use serde_json::json;
use crate::from_json;
// @fb-only
// @fb-only: use crate::meta_only;
// Defines the server-side configuration of ELP. We generate *parts*
// of VS Code's `package.json` config from this.
@ -180,7 +180,7 @@ impl Config {
return;
}
self.data = ConfigData::from_json(json);
// @fb-only
// @fb-only: meta_only::harmonise_gks(self);
}
pub fn update_gks(&mut self, json: serde_json::Value) {

View file

@ -26,6 +26,7 @@ use elp_ide::elp_ide_db::assists::AssistContextDiagnostic;
use elp_ide::elp_ide_db::assists::AssistContextDiagnosticCode;
use elp_ide::elp_ide_db::elp_base_db::AbsPath;
use elp_ide::elp_ide_db::elp_base_db::AbsPathBuf;
use elp_ide::elp_ide_db::elp_base_db::FileId;
use elp_ide::elp_ide_db::elp_base_db::VfsPath;
use lsp_types::DiagnosticRelatedInformation;
use lsp_types::Location;
@ -67,11 +68,14 @@ pub fn diagnostic_severity(severity: Severity) -> lsp_types::DiagnosticSeverity
}
}
pub fn ide_to_lsp_diagnostic(
pub fn ide_to_lsp_diagnostic<F>(
line_index: &LineIndex,
url: &Url,
d: &Diagnostic,
) -> lsp_types::Diagnostic {
get_file_info: F,
) -> lsp_types::Diagnostic
where
F: Fn(FileId) -> Option<(LineIndex, Url)>,
{
let code_description = match &d.code_doc_uri {
Some(uri) => match lsp_types::Url::parse(uri) {
Ok(href) => Some(lsp_types::CodeDescription { href }),
@ -90,7 +94,7 @@ pub fn ide_to_lsp_diagnostic(
code_description,
source,
message: d.message.clone(),
related_information: from_related(line_index, url, &d.related_info),
related_information: from_related(get_file_info, &d.related_info),
tags: d.tag.as_ref().map(lsp_diagnostic_tags),
data: None,
}
@ -122,18 +126,11 @@ pub fn eqwalizer_to_arc_diagnostic(
d: &EqwalizerDiagnostic,
line_index: &LineIndex,
relative_path: &Path,
eqwalizer_enabled: bool,
) -> arc_types::Diagnostic {
let pos = position(line_index, d.range.start());
let line_num = pos.line + 1;
let character = Some(pos.character + 1);
let severity = if eqwalizer_enabled {
arc_types::Severity::Error
} else {
// We use Severity::Disabled so that diagnostics are reported in cont lint
// but not in CI.
arc_types::Severity::Disabled
};
let severity = arc_types::Severity::Error;
// formatting: https://fburl.com/max_wiki_link_to_phabricator_rich_text
let explanation = match &d.explanation {
Some(s) => format!("```\n{s}\n```"),
@ -165,22 +162,26 @@ pub fn eqwalizer_to_arc_diagnostic(
)
}
fn from_related(
line_index: &LineIndex,
url: &Url,
fn from_related<F>(
get_file_info: F,
r: &Option<Vec<RelatedInformation>>,
) -> Option<Vec<DiagnosticRelatedInformation>> {
) -> Option<Vec<DiagnosticRelatedInformation>>
where
F: Fn(elp_ide::elp_ide_db::elp_base_db::FileId) -> Option<(LineIndex, Url)>,
{
r.as_ref().map(|ri| {
ri.iter()
.map(|i| {
.filter_map(|i| {
// Get the line index and URL for the file that contains the related information
let (line_index, uri) = get_file_info(i.file_id)?;
let location = Location {
range: range(line_index, i.range),
uri: url.clone(),
range: range(&line_index, i.range),
uri,
};
DiagnosticRelatedInformation {
Some(DiagnosticRelatedInformation {
location,
message: i.message.clone(),
}
})
})
.collect()
})

View file

@ -37,7 +37,7 @@ pub mod line_endings;
pub mod lsp_ext;
mod mem_docs;
pub mod memory_usage;
// @fb-only
// @fb-only: mod meta_only;
mod op_queue;
mod project_loader;
pub mod reload;
@ -108,7 +108,7 @@ pub fn otp_file_to_ignore(db: &Analysis, file_id: FileId) -> bool {
"redbug_dtop",
]
.iter()
// @fb-only
// @fb-only: .chain(meta_only::FILES_TO_IGNORE.iter())
.map(SmolStr::new)
.collect();
}
@ -193,6 +193,7 @@ mod tests {
ssr_pattern: "ssr: _@A = 10.".to_string(),
message: None,
strategy: None,
severity: None,
}),
],
},

View file

@ -192,7 +192,7 @@ impl ReloadManager {
self.get_query_config()
}
fn get_query_config(&self) -> BuckQueryConfig {
pub fn get_query_config(&self) -> BuckQueryConfig {
if self.buck_quick_start {
match self.buck_generated {
BuckGenerated::NoLoadDone => BuckQueryConfig::BuckTargetsOnly,

View file

@ -0,0 +1 @@
Project Initialisation Failed: invalid or missing buck 2 configuration

View file

@ -1,18 +1,7 @@
[check_include_separate_1/include/include_with_bug.hrl] 5:14-5:18: E1507: undefined macro 'FOO'
[check_include_separate_1/include/top_includer.hrl] 3:10-3:30: E1516: can't find include file "does_not_exist.hrl"
Diagnostics reported:
Reporting all diagnostics codes
Diagnostics reported in 4 modules:
app_a: 3
0:0-0:0::[Error] [W0012] Please add "-compile(warn_missing_spec_all)." to the module. If exported functions are not all specced, they need to be specced.
5:9-5:31::[WeakWarning] [W0037] Unspecific include.
0:8-0:13::[WeakWarning] [W0046] The module is not documented.
auto_gen_a: 2
0:0-0:0::[Error] [W0012] Please add "-compile(warn_missing_spec_all)." to the module. If exported functions are not all specced, they need to be specced.
0:8-0:18::[WeakWarning] [W0046] The module is not documented.
eqwalizer: 1
1:8-1:17::[WeakWarning] [W0046] The module is not documented.
wa_buck2_module_search: 6
19:0-19:18::[WeakWarning] [W0040] The function is non-trivial, exported, but not documented.
2:8-2:30::[WeakWarning] [W0046] The module is not documented.
54:18-54:31::[WeakWarning] [W0051] Binary string can be written using sigil syntax.
56:18-56:28::[WeakWarning] [W0051] Binary string can be written using sigil syntax.
56:38-56:51::[WeakWarning] [W0051] Binary string can be written using sigil syntax.
60:30-60:40::[WeakWarning] [W0051] Binary string can be written using sigil syntax.
check_include/src/top_includer.erl:14:5-14:11::[Error] [E1508] undefined macro 'THIRD/2'
check_include/src/top_includer.erl:6:1-6:67::[Error] [L0000] Issue in included file
module specified: top_includer

View file

@ -0,0 +1,138 @@
Reporting all diagnostics codes
Diagnostics reported:
app_a/src/app_a.erl:52:3-52:23::[Warning] [W0006] this statement has no effect
app_a/src/app_a.erl:3:10-3:21::[WeakWarning] [W0037] Unspecific include.
app_a/src/app_a.erl:27:3-27:9::[Warning] [W0017] Function 'foo:ok/0' is undefined.
app_a/src/app_a.erl:28:4-28:11::[Warning] [W0017] Function 'mod:foo/0' is undefined.
app_a/src/app_a.erl:72:4-72:11::[Warning] [W0017] Function 'foo:bar/2' is undefined.
app_a/src/app_a.erl:37:11-37:28::[Warning] [W0017] Function 'mod_name:fun_name/2' is undefined.
app_a/src/app_a.erl:58:11-58:24::[WeakWarning] [W0051] Binary string can be written using sigil syntax.
app_a/src/app_a.erl:4:1-4:41::[Warning] [W0020] Unused file: inets/include/httpd.hrl
app_a/src/app_a.erl:39:7-39:28::[Error] [L1267] variable 'A' shadowed in 'named fun'
app_a/src/app_a.erl:55:32-55:35::[Error] [L1295] type uri/0 undefined
app_a/src/app_a.erl:56:20-56:26::[Error] [L1295] type binary/1 undefined
app_a/src/app_a.erl:72:3-72:34::[Error] [L1252] record record undefined
app_a/src/app_a.erl:75:5-75:16::[Error] [L1252] record record undefined
app_a/src/app_a.erl:35:1-35:2::[Warning] [L1230] function g/1 is unused
app_a/src/app_a.erl:35:3-35:4::[Warning] [L1268] variable 'A' is unused
app_a/src/app_a.erl:36:3-36:4::[Warning] [L1268] variable 'F' is unused
app_a/src/app_a.erl:37:3-37:4::[Warning] [L1268] variable 'G' is unused
app_a/src/app_a.erl:38:3-38:4::[Warning] [L1268] variable 'H' is unused
app_a/src/app_a.erl:39:3-39:4::[Warning] [L1268] variable 'I' is unused
app_a/src/app_a.erl:39:7-39:28::[Warning] [L1268] variable 'A' is unused
app_a/src/app_a.erl:41:1-41:2::[Warning] [L1230] function h/0 is unused
app_a/src/app_a.erl:45:1-45:2::[Warning] [L1230] function i/0 is unused
app_a/src/app_a.erl:50:1-50:2::[Warning] [L1230] function j/2 is unused
app_a/src/app_a.erl:50:15-50:16::[Warning] [L1268] variable 'A' is unused
app_a/src/app_a.erl:50:23-50:24::[Warning] [L1268] variable 'B' is unused
app_a/src/app_a.erl:55:1-55:46::[Warning] [L1296] type session(_) is unused
app_a/src/app_a.erl:55:1-55:46::[Warning] [L1313] opaque type session(_) is not exported
app_a/src/app_a.erl:56:7-56:13::[Warning] [L1296] type source(_) is unused
app_a/src/app_a.erl:58:1-58:4::[Warning] [L1230] function map/2 is unused
app_a/src/app_a.erl:60:1-60:9::[Warning] [L1230] function with_dot/0 is unused
app_a/src/app_a.erl:62:1-62:9::[Warning] [L1230] function lang_dir/1 is unused
app_a/src/app_a.erl:66:1-66:7::[Warning] [L1230] function escape/1 is unused
app_a/src/app_a.erl:66:13-66:17::[Warning] [L1268] variable 'T' is unused
app_a/src/app_a.erl:67:9-67:25::[Warning] [L1260] record all_configs_file is unused
app_a/src/app_a.erl:71:1-71:2::[Warning] [L1230] function k/0 is unused
app_a/src/app_a.erl:74:1-74:2::[Warning] [L1230] function l/1 is unused
app_a/src/app_a.erl:77:1-77:2::[Warning] [L1230] function m/0 is unused
app_a/src/broken_parse_trans.erl:10:21-10:22::[Error] [L1256] field b undefined in record a
app_a/src/broken_parse_trans.erl:10:32-10:33::[Error] [L1262] variable 'B' is unbound
app_a/src/cascading.erl:9:5-9:6::[Error] [W0004] Missing ')'
3:10-3:15: function foo/0 undefined
6:10-6:15: function foo/0 undefined
8:7-8:10: spec for undefined function foo/0
app_a/src/diagnostics.erl:3:10-3:27::[WeakWarning] [W0037] Unspecific include.
app_a/src/diagnostics.erl:4:10-4:34::[WeakWarning] [W0037] Unspecific include.
app_a/src/diagnostics.erl:12:8-12:12::[Warning] [W0060] Match on a bound variable
app_a/src/diagnostics.erl:4:1-4:36::[Error] [L0000] Issue in included file
[app_a/include/broken_diagnostics.hrl] 1:8-1:15: P1702: bad attribute
[app_a/include/broken_diagnostics.hrl] 3:6-3:15: P1702: bad attribute
app_a/src/diagnostics.erl:6:31-6:45::[Error] [L1295] type undefined_type/0 undefined
app_a/src/diagnostics.erl:7:1-7:5::[Warning] [L1230] function main/1 is unused
app_a/src/diagnostics.erl:10:1-10:4::[Warning] [L1230] function foo/0 is unused
app_a/src/lint_recursive.erl:23:5-23:14::[Warning] [W0006] this statement has no effect
app_a/src/lint_recursive.erl:6:5-6:7::[Warning] [W0006] this statement has no effect
app_a/src/lint_recursive.erl:14:5-14:12::[Warning] [L1268] variable 'Config1' is unused
app_a/src/lint_recursive.erl:19:5-19:12::[Warning] [L1268] variable 'Config1' is unused
app_a/src/lints.erl:5:1-5:14::[Error] [P1700] head mismatch 'head_mismatcX' vs 'head_mismatch'
4:1-4:14: Mismatched clause name
app_a/src/lints.erl:4:22-4:23::[Warning] [W0018] Unexpected ';'
app_a/src/lints.erl:2:10-2:25::[Error] [L1227] function head_mismatch/1 undefined
app_a/src/otp27_docstrings.erl:34:9-34:24::[Warning] [W0002] Unused macro (THIS_IS_THE_END)
app_a/src/otp27_docstrings.erl:24:5-24:6::[Warning] [W0060] Match on a bound variable
app_a/src/otp27_docstrings.erl:30:5-30:6::[Warning] [W0060] Match on a bound variable
app_a/src/otp27_sigils.erl:11:6-11:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:12:5-12:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:13:5-13:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:14:5-14:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:15:5-15:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:17:6-17:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:18:5-18:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:19:5-19:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:20:5-20:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:21:5-21:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:23:6-23:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:24:5-24:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:25:5-25:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:26:5-26:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:27:5-27:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:29:6-29:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:30:5-30:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:31:5-31:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:32:5-32:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:33:5-33:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:35:6-35:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:36:5-36:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:37:5-37:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:38:5-38:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:39:5-39:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:41:6-41:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:42:5-42:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:43:5-43:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:44:5-44:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:45:5-45:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:47:6-47:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:48:5-48:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:49:5-49:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:50:5-50:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:51:5-51:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:53:6-53:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:53:6-53:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:54:5-54:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:54:5-54:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:55:5-55:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:55:5-55:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:56:5-56:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:57:5-57:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:59:6-59:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:60:5-60:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:61:5-61:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:62:5-62:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:63:5-63:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:65:6-65:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:66:5-66:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:67:5-67:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:68:5-68:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:69:5-69:24::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:76:5-79:8::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:76:5-79:8::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:80:5-84:9::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:80:5-84:9::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:85:5-89:10::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:85:5-89:10::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:90:5-94:11::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:95:5-99:12::[Warning] [W0006] this statement has no effect
app_a/src/otp27_sigils.erl:102:5-102:24::[WeakWarning] [W0051] Binary string can be written using sigil syntax.
app_a/src/otp27_sigils.erl:128:9-128:24::[Warning] [W0002] Unused macro (THIS_IS_THE_END)
app_a/src/otp27_sigils.erl:112:4-112:5::[Error] [P1711] syntax error before: X
4:15-4:18: function g/0 undefined
74:7-74:8: spec for undefined function g/0
app_a/src/otp27_sigils.erl:71:5-71:6::[Warning] [L1268] variable 'X' is unused
app_a/src/otp_7655.erl:5:1-5:28::[Error] [L1201] no module definition
app_a/src/parse_error_a_cascade.erl:10:20-11:1::[Error] [W0004] Missing 'atom'
6:6-6:11: function bar/0 undefined
app_a/src/suppressed.erl:8:5-8:9::[Warning] [L1268] variable 'Life' is unused
app_a/src/syntax.erl:5:46-5:47::[Error] [P1711] syntax error before: ')'
app_a/src/syntax.erl:11:9-11:10::[Error] [W0004] Missing ')'

View file

@ -1,4 +1,3 @@
module specified: suppressed
Diagnostics reported in 1 modules:
suppressed: 1
7:4-7:8::[Warning] [W0007] match is redundant
Diagnostics reported:
app_a/src/suppressed.erl:8:5-8:9::[Warning] [W0007] match is redundant

View file

@ -1,9 +1,10 @@
module specified: diagnostics
Diagnostics reported in 1 modules:
diagnostics: 6
diagnostics: 7
2:9-2:26::[Hint] [W0037] Unspecific include.
3:0-3:0::[Error] [L0000] Issue in included file
3:0-3:35::[Error] [L0000] Issue in included file
3:9-3:33::[Hint] [W0037] Unspecific include.
5:30-5:44::[Error] [L1295] type undefined_type/0 undefined
6:0-6:4::[Warning] [L1230] function main/1 is unused
9:0-9:3::[Warning] [L1230] function foo/0 is unused
11:7-11:11::[Warning] [W0060] Match on a bound variable

View file

@ -0,0 +1,5 @@
module specified: diagnostics
Diagnostics reported in 1 modules:
diagnostics: 2
3:0-3:35::[Error] [L0000] Issue in included file
5:30-5:44::[Error] [L1295] type undefined_type/0 undefined

View file

@ -4,3 +4,4 @@
{"path":"app_a/src/diagnostics.erl","line":6,"char":31,"code":"ELP","severity":"error","name":"L1295 (L1295)","original":null,"replacement":null,"description":"type undefined_type/0 undefined\n\nFor more information see: /erlang-error-index/l/L1295","docPath":null}
{"path":"app_a/src/diagnostics.erl","line":7,"char":1,"code":"ELP","severity":"warning","name":"L1230 (L1230)","original":null,"replacement":null,"description":"function main/1 is unused\n\nFor more information see: /erlang-error-index/l/L1230","docPath":null}
{"path":"app_a/src/diagnostics.erl","line":10,"char":1,"code":"ELP","severity":"warning","name":"L1230 (L1230)","original":null,"replacement":null,"description":"function foo/0 is unused\n\nFor more information see: /erlang-error-index/l/L1230","docPath":null}
{"path":"app_a/src/diagnostics.erl","line":12,"char":8,"code":"ELP","severity":"warning","name":"W0060 (bound_var_in_lhs)","original":null,"replacement":null,"description":"Match on a bound variable\n\nFor more information see: /erlang-error-index/w/W0060","docPath":"website/docs/erlang-error-index/w/W0060.md"}

View file

@ -1,11 +1,12 @@
module specified: lints
Diagnostics reported in 1 modules:
lints: 1
4:0-4:13::[Error] [P1700] head mismatch 'head_mismatcX' vs 'head_mismatch'
Diagnostics reported:
app_a/src/lints.erl:5:1-5:14::[Error] [P1700] head mismatch 'head_mismatcX' vs 'head_mismatch'
4:1-4:14: Mismatched clause name
---------------------------------------------
Applying fix in module 'lints' for
4:0-4:13::[Error] [P1700] head mismatch 'head_mismatcX' vs 'head_mismatch'
5:1-5:14::[Error] [P1700] head mismatch 'head_mismatcX' vs 'head_mismatch'
4:1-4:14: Mismatched clause name
@@ -1,6 +1,6 @@
-module(lints).
-export([head_mismatch/1]).

View file

@ -1,12 +1,11 @@
module specified: lint_recursive
Diagnostics reported in 1 modules:
lint_recursive: 2
18:4-18:11::[Warning] [W0007] match is redundant
13:4-13:11::[Warning] [W0007] match is redundant
Diagnostics reported:
app_a/src/lint_recursive.erl:19:5-19:12::[Warning] [W0007] match is redundant
app_a/src/lint_recursive.erl:14:5-14:12::[Warning] [W0007] match is redundant
---------------------------------------------
Applying fix in module 'lint_recursive' for
18:4-18:11::[Warning] [W0007] match is redundant
19:5-19:12::[Warning] [W0007] match is redundant
@@ -16,7 +16,7 @@
test_foo2(Config) ->
@ -21,12 +20,12 @@ Applying fix in module 'lint_recursive' for
New filtered diagnostics
lint_recursive: 2
13:4-13:11::[Warning] [W0007] match is redundant
18:4-18:10::[Warning] [W0006] this statement has no effect
14:5-14:12::[Warning] [W0007] match is redundant
19:5-19:11::[Warning] [W0006] this statement has no effect
---------------------------------------------
Applying fix in module 'lint_recursive' for
13:4-13:11::[Warning] [W0007] match is redundant
14:5-14:12::[Warning] [W0007] match is redundant
@@ -11,7 +11,7 @@
%% something/0.
test_foo(Config) ->
@ -41,12 +40,12 @@ Applying fix in module 'lint_recursive' for
New filtered diagnostics
lint_recursive: 2
18:4-18:10::[Warning] [W0006] this statement has no effect
13:4-13:10::[Warning] [W0006] this statement has no effect
19:5-19:11::[Warning] [W0006] this statement has no effect
14:5-14:11::[Warning] [W0006] this statement has no effect
---------------------------------------------
Applying fix in module 'lint_recursive' for
18:4-18:10::[Warning] [W0006] this statement has no effect
19:5-19:11::[Warning] [W0006] this statement has no effect
@@ -16,7 +16,6 @@
test_foo2(Config) ->
@ -60,12 +59,12 @@ Applying fix in module 'lint_recursive' for
New filtered diagnostics
lint_recursive: 2
16:10-16:16::[Warning] [W0010] this variable is unused
13:4-13:10::[Warning] [W0006] this statement has no effect
17:11-17:17::[Warning] [W0010] this variable is unused
14:5-14:11::[Warning] [W0006] this statement has no effect
---------------------------------------------
Applying fix in module 'lint_recursive' for
16:10-16:16::[Warning] [W0010] this variable is unused
17:11-17:17::[Warning] [W0010] this variable is unused
@@ -14,7 +14,7 @@
Config,
clean_mocks().
@ -80,11 +79,11 @@ Applying fix in module 'lint_recursive' for
New filtered diagnostics
lint_recursive: 1
13:4-13:10::[Warning] [W0006] this statement has no effect
14:5-14:11::[Warning] [W0006] this statement has no effect
---------------------------------------------
Applying fix in module 'lint_recursive' for
13:4-13:10::[Warning] [W0006] this statement has no effect
14:5-14:11::[Warning] [W0006] this statement has no effect
@@ -11,7 +11,6 @@
%% something/0.
test_foo(Config) ->
@ -98,11 +97,11 @@ Applying fix in module 'lint_recursive' for
New filtered diagnostics
lint_recursive: 1
11:9-11:15::[Warning] [W0010] this variable is unused
12:10-12:16::[Warning] [W0010] this variable is unused
---------------------------------------------
Applying fix in module 'lint_recursive' for
11:9-11:15::[Warning] [W0010] this variable is unused
12:10-12:16::[Warning] [W0010] this variable is unused
@@ -9,7 +9,7 @@
%% We want to check that the "no effect" statements in test_foo/1 and
%% test_foo2/1 are removed, but not the ones in clean_mocks/0 and

View file

@ -1,4 +1,6 @@
module specified: otp27_docstrings
Diagnostics reported in 1 modules:
otp27_docstrings: 1
otp27_docstrings: 3
23:4-23:5::[Warning] [W0060] Match on a bound variable
29:4-29:5::[Warning] [W0060] Match on a bound variable
33:8-33:23::[Warning] [W0002] Unused macro (THIS_IS_THE_END)

View file

@ -0,0 +1,2 @@
module specified: erlang_diagnostics_errors_gen
No matches found

View file

@ -0,0 +1,5 @@
module specified: erlang_diagnostics_errors_gen
erlang_diagnostics_errors_gen: 1
6:5-6:7::[WeakWarning] [ad-hoc: ssr-match] SSR pattern matched: ssr: ok.
Matches found in 1 modules

View file

@ -1,11 +1,10 @@
Usage: [--project PROJECT] [--as PROFILE] [[--format FORMAT]] [--rebar] [--include-tests] [--bail-on-error] [--stats] [--list-modules]
Usage: [--project PROJECT] [--as PROFILE] [[--format FORMAT]] [--rebar] [--bail-on-error] [--stats] [--list-modules]
Available options:
--project <PROJECT> Path to directory with project, or to a JSON file (defaults to `.`)
--as <PROFILE> Rebar3 profile to pickup (default is test)
--format <FORMAT> Show diagnostics in JSON format
--rebar Run with rebar
--include-tests Also eqwalize test modules from project
--bail-on-error Exit with a non-zero status code if any errors are found
--stats Print statistics when done
--list-modules When printing statistics, include the list of modules parsed

View file

@ -1,4 +1,4 @@
Usage: [--project PROJECT] [--as PROFILE] [--include-tests] [--rebar] [--bail-on-error] <APP>
Usage: [--project PROJECT] [--as PROFILE] [--rebar] [--bail-on-error] <APP>
Available positional items:
<APP> app name
@ -6,7 +6,6 @@ Available positional items:
Available options:
--project <PROJECT> Path to directory with project, or to a JSON file (defaults to `.`)
--as <PROFILE> Rebar3 profile to pickup (default is test)
--include-tests Also eqwalize test modules from project
--rebar Run with rebar
--bail-on-error Exit with a non-zero status code if any errors are found
-h, --help Prints help information

View file

@ -1,10 +1,9 @@
Usage: [--project PROJECT] [--include-tests] [--bail-on-error] <TARGET>
Usage: [--project PROJECT] [--bail-on-error] <TARGET>
Available positional items:
<TARGET> target, like //erl/chatd/...
Available options:
--project <PROJECT> Path to directory with project, or to a JSON file (defaults to `.`)
--include-tests Also eqwalize test modules from project
--bail-on-error Exit with a non-zero status code if any errors are found
-h, --help Prints help information

View file

@ -37,12 +37,6 @@ Because in the expression's type:
Here the type is: fun((term()) -> term())
Context expects type: fun((term(), term()) -> term())
------------------------------ Detailed message ------------------------------
fun((term()) -> term()) is not compatible with f2()
because
fun((term()) -> term()) is not compatible with fun((term(), term()) -> term())
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/any_fun_type.erl:64:1
@ -67,16 +61,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
)
------------------------------ Detailed message ------------------------------
f5('a' | 'b') is not compatible with f4('a')
because
fun((term()) -> 'a' | 'b') is not compatible with f4('a')
because
fun((term()) -> 'a' | 'b') is not compatible with fun((...) -> 'a')
because
'a' | 'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/any_fun_type.erl:98:20
@ -103,14 +87,4 @@ Because in the expression's type:
Differs from the expected type: 'a'
)
------------------------------ Detailed message ------------------------------
fun((term()) -> 'a' | 'b') is not compatible with f4('a')
because
fun((term()) -> 'a' | 'b') is not compatible with fun((...) -> 'a')
because
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
7 ERRORS

View file

@ -60,12 +60,6 @@ Because in the expression's type:
However the following candidate: string()
Differs from the expected type: 'anything'
------------------------------ Detailed message ------------------------------
string() | dynamic() is not compatible with 'anything'
because
string() is not compatible with 'anything'
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/approx.erl:74:1

View file

@ -2,15 +2,8 @@ error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types
┌─ check/src/auto_imports.erl:22:20
22 │ erlang:error(ok, ok).
│ ^^
│ │
│ 'ok'.
│ ^^ 'ok'.
Expression has type: 'ok'
Context expected type: [term()] | 'none'
'ok' is not compatible with [term()] | 'none'
because
'ok' is not compatible with [term()]
1 ERROR

View file

@ -22,10 +22,4 @@ Because in the expression's type:
However the following candidate: 'false'
Differs from the expected type: 'true'
------------------------------ Detailed message ------------------------------
'false' | 'true' is not compatible with 'true'
because
'false' is not compatible with 'true'
2 ERRORS

View file

@ -1,14 +0,0 @@
error: incorrect_return_type_in_cb_implementation (See https://fb.me/eqwalizer_errors#incorrect_return_type_in_cb_implementation)
┌─ check/src/callbacks3_neg.erl:12:1
12 │ -behavior(gen_server).
│ ^^^^^^^^^^^^^^^^^^^^^
│ │
│ Incorrect return type for implementation of gen_server:handle_cast/2. Expected: {'noreply', term()} | {'noreply', term(), timeout() | 'hibernate' | {'continue', term()}} | {'stop', term(), term()}, Got: 'wrong_ret'.
'wrong_ret' is not compatible with {'noreply', term()} | {'noreply', term(), timeout() | 'hibernate' | {'continue', term()}} | {'stop', term(), term()}
because
'wrong_ret' is not compatible with {'noreply', term()}
1 ERROR

View file

@ -1,14 +0,0 @@
error: incorrect_return_type_in_cb_implementation (See https://fb.me/eqwalizer_errors#incorrect_return_type_in_cb_implementation)
┌─ check/src/callbacks3_neg.erl:12:1
12 │ -behavior(gen_server).
│ ^^^^^^^^^^^^^^^^^^^^^
│ │
│ Incorrect return type for implementation of gen_server:handle_cast/2. Expected: {'noreply', term()} | {'noreply', term(), timeout() | 'hibernate' | {'continue', term()}} | {'stop', term(), term()}, Got: 'wrong_ret'.
'wrong_ret' is not compatible with {'noreply', term()} | {'noreply', term(), timeout() | 'hibernate' | {'continue', term()}} | {'stop', term(), term()}
because
'wrong_ret' is not compatible with {'noreply', term()}
1 ERROR

View file

@ -1,14 +0,0 @@
error: incorrect_return_type_in_cb_implementation (See https://fb.me/eqwalizer_errors#incorrect_return_type_in_cb_implementation)
┌─ check/src/callbacks3_neg.erl:12:1
12 │ -behavior(gen_server).
│ ^^^^^^^^^^^^^^^^^^^^^
│ │
│ Incorrect return type for implementation of gen_server:handle_cast/2. Expected: {'noreply', term()} | {'noreply', term(), gen_server:action()} | {'stop', term(), term()}, Got: 'wrong_ret'.
'wrong_ret' is not compatible with {'noreply', term()} | {'noreply', term(), gen_server:action()} | {'stop', term(), term()}
because
'wrong_ret' is not compatible with {'noreply', term()}
1 ERROR

View file

@ -0,0 +1,27 @@
error: incorrect_return_type_in_cb_implementation (See https://fb.me/eqwalizer_errors#incorrect_return_type_in_cb_implementation)
┌─ check/src/callbacks3_neg.erl:13:1
13 │ -behavior(gen_server).
│ ^^^^^^^^^^^^^^^^^^^^^ Incorrect return type for implementation of gen_server:handle_cast/2.
Expected: {'noreply', term()} | {'noreply', term(), timeout() | 'hibernate' | {'continue', term()}} | {'stop', term(), term()}
Got: 'wrong_ret'
error: incorrect_return_type_in_cb_implementation (See https://fb.me/eqwalizer_errors#incorrect_return_type_in_cb_implementation)
┌─ check/src/callbacks3_neg.erl:13:1
13 │ -behavior(gen_server).
│ ^^^^^^^^^^^^^^^^^^^^^
│ │
│ Incorrect return type for implementation of gen_server:handle_info/2.
Expected: {'noreply', term()} | {'noreply', term(), timeout() | 'hibernate' | {'continue', term()}} | {'stop', term(), term()}
Got: {'noreply', 'ok', 'wrong_atom'}
Because in the expression's type:
{ 'noreply', 'ok',
Here the type is: 'wrong_atom'
Context expects type: 'infinity' | number() | 'hibernate' | {'continue', term()}
No candidate matches in the expected union.
}
2 ERRORS

View file

@ -72,17 +72,6 @@ Because in the expression's type:
Differs from the expected type: pid()
}
------------------------------ Detailed message ------------------------------
{'p', pid() | reference()} is not compatible with {'a', atom()} | {'p', pid()}
because
at tuple index 2:
{'p', pid() | reference()} is not compatible with {'p', pid()}
because
pid() | reference() is not compatible with pid()
because
reference() is not compatible with pid()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/case_predicates.erl:144:10
@ -99,14 +88,6 @@ Because in the expression's type:
However the following candidate: 'restarting'
Differs from the expected type: {'p', pid()} | 'undefined'
------------------------------ Detailed message ------------------------------
'undefined' | 'restarting' is not compatible with {'p', pid()} | 'undefined'
because
'restarting' is not compatible with {'p', pid()} | 'undefined'
because
'restarting' is not compatible with {'p', pid()}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/case_predicates.erl:174:16

View file

@ -14,10 +14,6 @@ Because in the expression's type:
Context expects type: #{...}
The expected map has no corresponding key for: c.
------------------------------ Detailed message ------------------------------
key `c` is declared in the former but not in the latter and the latter map has no default association
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:17:21
@ -35,15 +31,6 @@ Because in the expression's type:
Context expects type: number()
, ... }
------------------------------ Detailed message ------------------------------
#{a => 'b', c => 'd'} is not compatible with #{a => 'b', atom() => number()}
because
#{a => 'b', c => 'd'} is not compatible with #{a => 'b', atom() => number()}
key `c` is declared in the former but not in the latter and key `c` isn't compatible with the default association of the latter map
because
'd' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:20:19
@ -60,13 +47,6 @@ Because in the expression's type:
Context expects type: #{...} (no default association)
The expected map has no default association while the type of the expression has one.
------------------------------ Detailed message ------------------------------
#{a => 'b', atom() => atom()} is not compatible with #{a => 'b', c => 'd'}
key c is not present in the former map but is incompatible with its default association
because
atom() is not compatible with 'd'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:23:19
@ -85,13 +65,6 @@ Because in the expression's type:
, ... }
The context introduces a new association c => 'd' which is incompatible with the expression's default association.
------------------------------ Detailed message ------------------------------
#{a => 'b', atom() => number()} is not compatible with #{a => 'b', c => 'd', atom() => number()}
key c is not present in the former map but is incompatible with its default association
because
number() is not compatible with 'd'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:38:21
@ -108,13 +81,6 @@ Because in the expression's type:
Context expects type: #{...} (no default association)
The expected map has no default association while the type of the expression has one.
------------------------------ Detailed message ------------------------------
#{a => 'b', atom() => atom()} is not compatible with #{a => 'b'}
because
#{a => 'b', atom() => atom()} is not compatible with #{a => 'b'}
the latter map has no default association while the first map has one
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:44:26
@ -131,13 +97,6 @@ Because in the expression's type:
Context expects type: #{...} (no default association)
The expected map has no default association while the type of the expression has one.
------------------------------ Detailed message ------------------------------
#{a => 'b', dynamic(atom()) => atom()} is not compatible with #{a => 'b'}
because
#{a => 'b', dynamic(atom()) => atom()} is not compatible with #{a => 'b'}
the latter map has no default association while the first map has one
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:47:26
@ -154,13 +113,6 @@ Because in the expression's type:
Context expects type: #{...} (no default association)
The expected map has no default association while the type of the expression has one.
------------------------------ Detailed message ------------------------------
#{a => 'b', atom() => dynamic(atom())} is not compatible with #{a => 'b'}
because
#{a => 'b', atom() => dynamic(atom())} is not compatible with #{a => 'b'}
the latter map has no default association while the first map has one
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:56:44
@ -218,13 +170,6 @@ Because in the expression's type:
Context expects type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{atom() => binary()} is not compatible with #{a => binary(), atom() => atom()}
the default associations are not compatible
because
binary() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:83:28
@ -242,13 +187,6 @@ Because in the expression's type:
Context expects type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{a := 'b', atom() => binary()} is not compatible with #{a => 'b', {c, d} => atom() | binary(), term() => atom()}
the default associations are not compatible
because
binary() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:86:28
@ -266,13 +204,6 @@ Because in the expression's type:
Context expects type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{a := 'b', atom() => binary()} is not compatible with #{a => 'b', {c, d} => atom() | binary(), atom() => atom()}
the default associations are not compatible
because
binary() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/complex_maps.erl:89:29
@ -290,11 +221,4 @@ Because in the expression's type:
Context expects type: binary()
, ... }
------------------------------ Detailed message ------------------------------
#{dynamic() => atom()} is not compatible with #{dynamic() => binary()}
the default associations are not compatible
because
atom() is not compatible with binary()
16 ERRORS

View file

@ -15,12 +15,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [atom()]
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/comprehensions.erl:40:16
@ -86,12 +80,6 @@ Because in the expression's type:
Context expects type: binary()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [binary()]
because
number() is not compatible with binary()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/comprehensions.erl:72:5
@ -270,12 +258,6 @@ Because in the expression's type:
Context expects type: binary()
]
------------------------------ Detailed message ------------------------------
[atom()] is not compatible with [binary()]
because
atom() is not compatible with binary()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/comprehensions.erl:226:5
@ -293,12 +275,6 @@ Because in the expression's type:
Context expects type: 'false'
]
------------------------------ Detailed message ------------------------------
['true'] is not compatible with ['false']
because
'true' is not compatible with 'false'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/comprehensions.erl:231:5
@ -316,12 +292,6 @@ Because in the expression's type:
Context expects type: 'false'
]
------------------------------ Detailed message ------------------------------
['true'] is not compatible with ['false']
because
'true' is not compatible with 'false'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/comprehensions.erl:239:5
@ -339,12 +309,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [atom()]
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/comprehensions.erl:267:5
@ -363,14 +327,6 @@ Because in the expression's type:
Differs from the expected type: binary()
]
------------------------------ Detailed message ------------------------------
[binary() | 'undefined'] is not compatible with [binary()]
because
binary() | 'undefined' is not compatible with binary()
because
'undefined' is not compatible with binary()
error: expected_fun_type (See https://fb.me/eqwalizer_errors#expected_fun_type)
┌─ check/src/comprehensions.erl:386:9

View file

@ -16,14 +16,4 @@ Because in the expression's type:
Differs from the expected type: 'a'
) -> 'ok')
------------------------------ Detailed message ------------------------------
ref_contravariant('a') is not compatible with ref_contravariant_ab()
because
contravariant('a') is not compatible with ref_contravariant_ab()
because
fun(('a') -> 'ok') is not compatible with ref_contravariant_ab()
because
fun(('a') -> 'ok') is not compatible with ref_contravariant('a' | 'b')
1 ERROR

View file

@ -66,61 +66,33 @@ error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types
┌─ check/src/dynamic_calls.erl:78:14
78 │ (FUnion)(false).
│ ^^^^^
│ │
│ 'false'.
│ ^^^^^ 'false'.
Expression has type: 'false'
Context expected type: 'a1' | 'a2'
'false' is not compatible with 'a1' | 'a2'
because
'false' is not compatible with 'a1'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_calls.erl:78:14
78 │ (FUnion)(false).
│ ^^^^^
│ │
│ 'false'.
│ ^^^^^ 'false'.
Expression has type: 'false'
Context expected type: 'a2' | 'a3'
'false' is not compatible with 'a2' | 'a3'
because
'false' is not compatible with 'a2'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_calls.erl:86:20
86 │ Res = (FUnion)(false),
│ ^^^^^
│ │
│ 'false'.
│ ^^^^^ 'false'.
Expression has type: 'false'
Context expected type: 'a1' | 'a2'
'false' is not compatible with 'a1' | 'a2'
because
'false' is not compatible with 'a1'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_calls.erl:86:20
86 │ Res = (FUnion)(false),
│ ^^^^^
│ │
│ 'false'.
│ ^^^^^ 'false'.
Expression has type: 'false'
Context expected type: 'a2' | 'a3'
'false' is not compatible with 'a2' | 'a3'
because
'false' is not compatible with 'a2'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_calls.erl:87:5
@ -146,12 +118,6 @@ Because in the expression's type:
However the following candidate: 'r2'
Differs from the expected type: 'r1'
------------------------------ Detailed message ------------------------------
'r1' | 'r2' is not compatible with 'r1'
because
'r2' is not compatible with 'r1'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_calls.erl:94:5
@ -176,12 +142,6 @@ Because in the expression's type:
However the following candidate: 'r2'
Differs from the expected type: 'r1'
------------------------------ Detailed message ------------------------------
'r1' | 'r2' | 'r3' is not compatible with 'r1'
because
'r2' is not compatible with 'r1'
error: expected_fun_type (See https://fb.me/eqwalizer_errors#expected_fun_type)
┌─ check/src/dynamic_calls.erl:108:5

View file

@ -14,10 +14,4 @@ Because in the expression's type:
However the following candidate: atom()
Differs from the expected type: binary()
------------------------------ Detailed message ------------------------------
atom() | dynamic() is not compatible with binary()
because
atom() is not compatible with binary()
1 ERROR

View file

@ -72,16 +72,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
)
------------------------------ Detailed message ------------------------------
f5('a' | 'b') is not compatible with f4('a')
because
fun((term()) -> 'a' | 'b') is not compatible with f4('a')
because
fun((term()) -> 'a' | 'b') is not compatible with fun((...) -> 'a')
because
'a' | 'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_fun.erl:155:20
@ -108,16 +98,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
)
------------------------------ Detailed message ------------------------------
fun((term()) -> 'a' | 'b') is not compatible with f4('a')
because
fun((term()) -> 'a' | 'b') is not compatible with fun((...) -> 'a')
because
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_fun.erl:176:21
@ -136,16 +116,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
)
------------------------------ Detailed message ------------------------------
f4('a' | 'b') is not compatible with fun((term()) -> 'a')
because
fun((...) -> 'a' | 'b') is not compatible with fun((term()) -> 'a')
because
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_fun.erl:208:34

View file

@ -38,12 +38,6 @@ Because in the expression's type:
However the following candidate: number()
Differs from the expected type: none()
------------------------------ Detailed message ------------------------------
number() | dynamic() is not compatible with none()
because
number() is not compatible with none()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_generics.erl:72:3
@ -68,12 +62,6 @@ Because in the expression's type:
However the following candidate: string()
Differs from the expected type: 'ok'
------------------------------ Detailed message ------------------------------
dynamic() | string() is not compatible with 'ok'
because
string() is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_generics.erl:87:3
@ -112,14 +100,6 @@ Because in the expression's type:
Differs from the expected type: number()
]
------------------------------ Detailed message ------------------------------
[number() | 'three'] is not compatible with [number()]
because
number() | 'three' is not compatible with number()
because
'three' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_generics.erl:115:9
@ -136,12 +116,6 @@ Because in the expression's type:
However the following candidate: 'three'
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
number() | 'three' is not compatible with number()
because
'three' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_generics.erl:115:22
@ -158,12 +132,6 @@ Because in the expression's type:
However the following candidate: 'three'
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
number() | 'three' is not compatible with number()
because
'three' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_generics.erl:127:13

View file

@ -14,12 +14,6 @@ Because in the expression's type:
However the following candidate: number()
Differs from the expected type: atom()
------------------------------ Detailed message ------------------------------
dynamic() | number() is not compatible with atom()
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_local_funs.erl:36:15

View file

@ -100,12 +100,6 @@ Because in the expression's type:
However the following candidate: 'error'
Differs from the expected type: 'ok'
------------------------------ Detailed message ------------------------------
dynamic() | 'error' is not compatible with 'ok'
because
'error' is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_refine.erl:236:3
@ -138,12 +132,6 @@ Because in the expression's type:
However the following candidate: 'err'
Differs from the expected type: 'ok'
------------------------------ Detailed message ------------------------------
dyn_alias() | 'err' is not compatible with 'ok'
because
'err' is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/dynamic_refine.erl:260:27
@ -162,15 +150,4 @@ Because in the expression's type:
Differs from the expected type: 'ok'
}
------------------------------ Detailed message ------------------------------
union() is not compatible with {'ok'}
because
at tuple index 1:
{dyn_alias() | 'err'} is not compatible with {'ok'}
because
dyn_alias() | 'err' is not compatible with 'ok'
because
'err' is not compatible with 'ok'
16 ERRORS

View file

@ -38,12 +38,6 @@ Because in the expression's type:
However the following candidate: 'error'
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
'error' | 'exit' | 'throw' | number() is not compatible with number()
because
'error' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/elab_clause.erl:86:5
@ -60,12 +54,6 @@ Because in the expression's type:
However the following candidate: [dynamic()]
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
number() | [dynamic()] is not compatible with number()
because
[dynamic()] is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/elab_clause.erl:93:17

View file

@ -15,17 +15,6 @@ Because in the expression's type:
Context expects type: number()
, ... }
------------------------------ Detailed message ------------------------------
#{bar := atom(), baz := atom()} is not compatible with foo_map() | #{foo => atom()}
because
#{bar := atom(), baz := atom()} is not compatible with foo_map()
because
#{bar := atom(), baz := atom()} is not compatible with #{bar => atom(), baz => number(), other => atom(), other2 => atom(), other3 => atom(), other4 => atom(), other5 => atom()}
because
at key `baz`:
#{bar := atom(), baz := atom()} is not compatible with #{bar => atom(), baz => number(), other => atom(), other2 => atom(), other3 => atom(), other4 => atom(), other5 => atom()}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/error_messages.erl:19:24
@ -44,12 +33,6 @@ Because in the expression's type:
The expected map has no corresponding key for: baz.
]
------------------------------ Detailed message ------------------------------
[#{bar => 'a' | 'b'} | #{baz => 'a' | 'b'}] is not compatible with [#{bar => 'a'}]
because
#{bar => 'a' | 'b'} | #{baz => 'a' | 'b'} is not compatible with #{bar => 'a'}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/error_messages.erl:22:22
@ -68,15 +51,6 @@ Because in the expression's type:
Differs from the expected type: binary()
, ... }
------------------------------ Detailed message ------------------------------
#{'undefined' | binary() => atom()} is not compatible with #{binary() => atom()}
the default associations are not compatible
because
'undefined' | binary() is not compatible with binary()
because
'undefined' is not compatible with binary()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/error_messages.erl:27:32
@ -89,17 +63,9 @@ error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types
┌─ check/src/error_messages.erl:30:32
30 │ no_record_conversion_2(Foo) -> Foo.
│ ^^^
│ │
│ Foo.
│ ^^^ Foo.
Expression has type: #foo{}
Context expected type: {binary(), atom(), atom()}
at tuple index 1:
{'foo', atom(), atom()} is not compatible with {binary(), atom(), atom()}
because
'foo' is not compatible with binary()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/error_messages.erl:33:27
@ -118,13 +84,6 @@ Because in the expression's type:
Context expects type: binary()
, atom()}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{'foo', atom(), atom()} is not compatible with {'foo', binary(), atom()}
because
atom() is not compatible with binary()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/error_messages.erl:37:31
@ -143,18 +102,6 @@ Because in the expression's type:
The expected map has no corresponding key for: large_map_key_a.
, ... }
------------------------------ Detailed message ------------------------------
#{foo => #{large_map_key_a => 'large_map_val_a', large_map_key_b => 'large_map_val_b'}} is not compatible with #{foo => #{large_map_key_c => 'large_map_val_c'} | #{large_map_key_d => 'large_map_val_d'}}
because
at key `foo`:
#{foo => #{large_map_key_a => 'large_map_val_a', large_map_key_b => 'large_map_val_b'}} is not compatible with #{foo => #{large_map_key_c => 'large_map_val_c'} | #{large_map_key_d => 'large_map_val_d'}}
because
#{large_map_key_a => 'large_map_val_a', large_map_key_b => 'large_map_val_b'} is not compatible with #{large_map_key_c => 'large_map_val_c'} | #{large_map_key_d => 'large_map_val_d'}
because
#{large_map_key_a => 'large_map_val_a', large_map_key_b => 'large_map_val_b'} is not compatible with #{large_map_key_c => 'large_map_val_c'}
key `large_map_key_a` is declared in the former but not in the latter and the latter map has no default association
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/error_messages.erl:41:31
@ -173,16 +120,4 @@ Because in the expression's type:
The expected map has no corresponding key for: large_map_key_a.
, ... }
------------------------------ Detailed message ------------------------------
#{foo => #{large_map_key_a => 'large_map_val_a', large_map_key_b => 'large_map_val_b'}} is not compatible with #{foo => #{large_map_key_c => 'large_map_val_c', large_map_key_d => 'large_map_val_d'} | 'any'}
because
at key `foo`:
#{foo => #{large_map_key_a => 'large_map_val_a', large_map_key_b => 'large_map_val_b'}} is not compatible with #{foo => #{large_map_key_c => 'large_map_val_c', large_map_key_d => 'large_map_val_d'} | 'any'}
because
#{large_map_key_a => 'large_map_val_a', large_map_key_b => 'large_map_val_b'} is not compatible with #{large_map_key_c => 'large_map_val_c', large_map_key_d => 'large_map_val_d'} | 'any'
because
#{large_map_key_a => 'large_map_val_a', large_map_key_b => 'large_map_val_b'} is not compatible with #{large_map_key_c => 'large_map_val_c', large_map_key_d => 'large_map_val_d'}
key `large_map_key_a` is declared in the former but not in the latter and the latter map has no default association
8 ERRORS

View file

@ -13,10 +13,4 @@ Because in the expression's type:
Here the type is: [number() | io_lib:chars()]
Context expects type: string()
------------------------------ Detailed message ------------------------------
io_lib:chars() is not compatible with string()
because
[number() | io_lib:chars()] is not compatible with string()
1 ERROR

View file

@ -29,12 +29,6 @@ Because in the expression's type:
Here the type is: number()
Context expects type: [term()]
------------------------------ Detailed message ------------------------------
n() is not compatible with [term()]
because
number() is not compatible with [term()]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:63:9
@ -50,12 +44,6 @@ Because in the expression's type:
Here the type is: [dynamic()]
Context expects type: number()
------------------------------ Detailed message ------------------------------
[dynamic()] is not compatible with n()
because
[dynamic()] is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:70:13
@ -71,12 +59,6 @@ Because in the expression's type:
Here the type is: binary()
Context expects type: number()
------------------------------ Detailed message ------------------------------
binary() is not compatible with n()
because
binary() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:70:35
@ -92,12 +74,6 @@ Because in the expression's type:
Here the type is: number()
Context expects type: atom()
------------------------------ Detailed message ------------------------------
n() is not compatible with atom()
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:77:5
@ -116,14 +92,6 @@ Because in the expression's type:
Context expects type: 'a'
]
------------------------------ Detailed message ------------------------------
[n()] is not compatible with ['a']
because
n() is not compatible with 'a'
because
number() is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:90:18
@ -139,12 +107,6 @@ Because in the expression's type:
Here the type is: number()
Context expects type: [term()]
------------------------------ Detailed message ------------------------------
n() is not compatible with [term()]
because
number() is not compatible with [term()]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:90:18
@ -160,12 +122,6 @@ Because in the expression's type:
Here the type is: [dynamic()]
Context expects type: number()
------------------------------ Detailed message ------------------------------
[dynamic()] is not compatible with n()
because
[dynamic()] is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:90:23
@ -181,12 +137,6 @@ Because in the expression's type:
Here the type is: number()
Context expects type: [term()]
------------------------------ Detailed message ------------------------------
n() is not compatible with [term()]
because
number() is not compatible with [term()]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:96:31
@ -202,12 +152,6 @@ Because in the expression's type:
Here the type is: number()
Context expects type: atom()
------------------------------ Detailed message ------------------------------
n() is not compatible with atom()
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:97:9
@ -223,12 +167,6 @@ Because in the expression's type:
Here the type is: number()
Context expects type: [term()]
------------------------------ Detailed message ------------------------------
n() is not compatible with [term()]
because
number() is not compatible with [term()]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:97:9
@ -244,12 +182,6 @@ Because in the expression's type:
Here the type is: [dynamic()]
Context expects type: number()
------------------------------ Detailed message ------------------------------
[dynamic()] is not compatible with n()
because
[dynamic()] is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:97:14
@ -265,12 +197,6 @@ Because in the expression's type:
Here the type is: number()
Context expects type: [term()]
------------------------------ Detailed message ------------------------------
n() is not compatible with [term()]
because
number() is not compatible with [term()]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs.erl:104:7

View file

@ -19,14 +19,6 @@ Because in the expression's type:
]
]
------------------------------ Detailed message ------------------------------
[[[[]]]] is not compatible with [[[]]]
because
[[[]]] is not compatible with [[]]
because
[[]] is not compatible with []
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs2.erl:54:5
@ -66,12 +58,6 @@ Because in the expression's type:
Context expects type: atom()
)
------------------------------ Detailed message ------------------------------
fun((atom()) -> string()) is not compatible with fun((atom()) -> atom())
because
string() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs2.erl:101:9
@ -90,14 +76,6 @@ Because in the expression's type:
Differs from the expected type: atom()
) -> string())
------------------------------ Detailed message ------------------------------
fun((atom()) -> string()) is not compatible with fun((dynamic() | fun((string()) -> atom())) -> dynamic() | fun((string()) -> atom()))
because
dynamic() | fun((string()) -> atom()) is not compatible with atom()
because
fun((string()) -> atom()) is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs2.erl:101:9
@ -116,14 +94,6 @@ Because in the expression's type:
Differs from the expected type: atom()
) -> string())
------------------------------ Detailed message ------------------------------
fun((atom()) -> string()) is not compatible with fun((dynamic() | string() | fun((string()) -> atom())) -> dynamic() | string() | fun((string()) -> atom()))
because
dynamic() | string() | fun((string()) -> atom()) is not compatible with atom()
because
string() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/funs2.erl:152:27

View file

@ -31,12 +31,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [atom()]
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:38:29
@ -54,14 +48,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [dynamic(atom())]
because
number() is not compatible with dynamic(atom())
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:43:5
@ -87,12 +73,6 @@ Because in the expression's type:
Context expects type: B
)
------------------------------ Detailed message ------------------------------
fun((atom()) -> pid()) is not compatible with fun((number()) -> B)
because
pid() is not compatible with B
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:43:18
@ -111,14 +91,6 @@ Because in the expression's type:
Differs from the expected type: atom()
) -> pid())
------------------------------ Detailed message ------------------------------
fun((atom()) -> pid()) is not compatible with fun((dynamic() | number()) -> pid())
because
dynamic() | number() is not compatible with atom()
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:47:33
@ -136,12 +108,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [atom()]
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:47:33
@ -159,14 +125,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [dynamic(atom())]
because
number() is not compatible with dynamic(atom())
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:48:5
@ -192,12 +150,6 @@ Because in the expression's type:
Context expects type: B
)
------------------------------ Detailed message ------------------------------
fun((atom()) -> pid()) is not compatible with fun((number()) -> B)
because
pid() is not compatible with B
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:52:22
@ -216,14 +168,6 @@ Because in the expression's type:
Differs from the expected type: atom()
) -> pid())
------------------------------ Detailed message ------------------------------
fun((atom()) -> pid()) is not compatible with fun((dynamic() | number()) -> pid())
because
dynamic() | number() is not compatible with atom()
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:53:5
@ -272,10 +216,6 @@ Because in the expression's type:
Context expects type: #{...}
The expected map has no corresponding key for: true.
------------------------------ Detailed message ------------------------------
key `true` is declared in the former but not in the latter and the latter map has no default association
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:99:13
@ -365,15 +305,6 @@ Because in the expression's type:
Context expects type: T
, ... }
------------------------------ Detailed message ------------------------------
#{a => number()} is not compatible with #{atom() => T}
because
#{a => number()} is not compatible with #{atom() => T}
key `a` is declared in the former but not in the latter and key `a` isn't compatible with the default association of the latter map
because
number() is not compatible with T
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:126:5
@ -414,12 +345,6 @@ Because in the expression's type:
However the following candidate: 'b'
Differs from the expected type: 'a'
------------------------------ Detailed message ------------------------------
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:157:5
@ -444,12 +369,6 @@ Because in the expression's type:
However the following candidate: 'b'
Differs from the expected type: 'a'
------------------------------ Detailed message ------------------------------
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:172:5
@ -466,12 +385,6 @@ Because in the expression's type:
However the following candidate: 'a'
Differs from the expected type: 'b'
------------------------------ Detailed message ------------------------------
'a' | 'b' is not compatible with 'b'
because
'a' is not compatible with 'b'
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/generic_fun_application.erl:226:1
@ -521,12 +434,6 @@ Because in the expression's type:
Context expects type: X
)
------------------------------ Detailed message ------------------------------
fun(() -> A) is not compatible with fun(() -> X)
because
A is not compatible with X
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:276:5
@ -567,12 +474,6 @@ Because in the expression's type:
However the following candidate: Last
Differs from the expected type: 'first'
------------------------------ Detailed message ------------------------------
'first' | Last is not compatible with 'first'
because
Last is not compatible with 'first'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:296:5
@ -589,12 +490,6 @@ Because in the expression's type:
However the following candidate: T
Differs from the expected type: atom()
------------------------------ Detailed message ------------------------------
atom() | T is not compatible with atom()
because
T is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:322:5
@ -612,13 +507,6 @@ Because in the expression's type:
Context expects type: pid()
, pid()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{number(), pid()} is not compatible with {pid(), number()}
because
number() is not compatible with pid()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:330:5
@ -677,12 +565,6 @@ Because in the expression's type:
Context expects type: fun((A) -> A) with 0 type parameters
The number of type parameters doesn't match.
------------------------------ Detailed message ------------------------------
fun((Z) -> Z) | fun((dynamic()) -> dynamic()) is not compatible with fun((A) -> A)
because
fun((Z) -> Z) with 1 type parameter is not compatible with fun((A) -> A) with 0 type parameters
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:346:9
@ -701,12 +583,6 @@ Because in the expression's type:
Context expects type: fun((dynamic()) -> dynamic()) with 0 type parameters
The number of type parameters doesn't match.
------------------------------ Detailed message ------------------------------
fun((Z) -> Z) | fun((dynamic()) -> dynamic()) is not compatible with fun((dynamic()) -> dynamic())
because
fun((Z) -> Z) with 1 type parameter is not compatible with fun((dynamic()) -> dynamic()) with 0 type parameters
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:346:9
@ -725,12 +601,6 @@ Because in the expression's type:
Context expects type: fun((A) -> A) with 0 type parameters
The number of type parameters doesn't match.
------------------------------ Detailed message ------------------------------
fun((Z) -> Z) | fun((dynamic()) -> dynamic()) is not compatible with fun((A) -> A)
because
fun((Z) -> Z) with 1 type parameter is not compatible with fun((A) -> A) with 0 type parameters
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:358:9
@ -781,12 +651,6 @@ Because in the expression's type:
Context expects type: fun((Z) -> Z) with 0 type parameters
The number of type parameters doesn't match.
------------------------------ Detailed message ------------------------------
fun((Z) -> Z) | fun((dynamic()) -> dynamic()) is not compatible with fun((Z) -> Z)
because
fun((Z) -> Z) with 1 type parameter is not compatible with fun((Z) -> Z) with 0 type parameters
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:358:9
@ -805,12 +669,6 @@ Because in the expression's type:
Context expects type: fun((dynamic()) -> dynamic()) with 0 type parameters
The number of type parameters doesn't match.
------------------------------ Detailed message ------------------------------
fun((Z) -> Z) | fun((dynamic()) -> dynamic()) is not compatible with fun((dynamic()) -> dynamic())
because
fun((Z) -> Z) with 1 type parameter is not compatible with fun((dynamic()) -> dynamic()) with 0 type parameters
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:358:9
@ -829,12 +687,6 @@ Because in the expression's type:
Context expects type: fun((Z) -> Z) with 0 type parameters
The number of type parameters doesn't match.
------------------------------ Detailed message ------------------------------
fun((Z) -> Z) | fun((dynamic()) -> dynamic()) is not compatible with fun((Z) -> Z)
because
fun((Z) -> Z) with 1 type parameter is not compatible with fun((Z) -> Z) with 0 type parameters
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:432:18
@ -875,10 +727,6 @@ Because in the expression's type:
Context expects type: #{a := ..., ...}
The type of the expression is missing the following required keys: a.
------------------------------ Detailed message ------------------------------
key `a` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:441:16
@ -895,10 +743,6 @@ Because in the expression's type:
Context expects type: #{a := ..., ...}
The type of the expression is missing the following required keys: a.
------------------------------ Detailed message ------------------------------
key `a` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:446:15
@ -916,12 +760,6 @@ Because in the expression's type:
Context expects type: T
)
------------------------------ Detailed message ------------------------------
fun((#{a => number()}) -> number()) is not compatible with fun((#{{T} => T}) -> T)
because
number() is not compatible with T
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:446:15
@ -940,15 +778,6 @@ Because in the expression's type:
The expected map has no default association while the type of the expression has one.
) -> number())
------------------------------ Detailed message ------------------------------
fun((#{a => number()}) -> number()) is not compatible with fun((#{{number()} => number()}) -> number())
because
#{{number()} => number()} is not compatible with #{a => number()}
because
#{{number()} => number()} is not compatible with #{a => number()}
the latter map has no default association while the first map has one
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:471:24
@ -966,12 +795,6 @@ Because in the expression's type:
Context expects type: 'c'
)
------------------------------ Detailed message ------------------------------
fun(('a') -> 'b') is not compatible with fun(('a') -> 'c')
because
'b' is not compatible with 'c'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:478:17
@ -988,10 +811,6 @@ Because in the expression's type:
Context expects type: #{a := ..., ...}
The type of the expression is missing the following required keys: a.
------------------------------ Detailed message ------------------------------
key `a` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:478:17
@ -1008,10 +827,6 @@ Because in the expression's type:
Context expects type: #{a := ..., ...}
The type of the expression is missing the following required keys: a.
------------------------------ Detailed message ------------------------------
key `a` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:500:36
@ -1048,16 +863,6 @@ Because in the expression's type:
) -> 'ok')
) -> 'ok')
------------------------------ Detailed message ------------------------------
contravar(contravar('a' | 'b')) is not compatible with contravar(contravar('a'))
because
fun((contravar('a' | 'b')) -> 'ok') is not compatible with contravar(contravar('a'))
because
fun((contravar('a' | 'b')) -> 'ok') is not compatible with fun((contravar('a')) -> 'ok')
because
contravar('a') is not compatible with contravar('a' | 'b')
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:563:5
@ -1075,14 +880,6 @@ Because in the expression's type:
Context expects type: 'a'
) -> 'a')
------------------------------ Detailed message ------------------------------
invar('a') is not compatible with fun((atom()) -> atom())
because
fun(('a') -> 'a') is not compatible with fun((atom()) -> atom())
because
atom() is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:569:5
@ -1100,16 +897,6 @@ Because in the expression's type:
Context expects type: 'a'
) -> 'a')
------------------------------ Detailed message ------------------------------
invar('a') is not compatible with invar(atom())
because
fun(('a') -> 'a') is not compatible with invar(atom())
because
fun(('a') -> 'a') is not compatible with fun((atom()) -> atom())
because
atom() is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:585:5
@ -1125,12 +912,6 @@ Because in the expression's type:
Here the type is: 'a'
Context expects type: fun(('a') -> 'a')
------------------------------ Detailed message ------------------------------
'a' is not compatible with invar('a')
because
'a' is not compatible with fun(('a') -> 'a')
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/generic_fun_application.erl:625:1
@ -1175,10 +956,6 @@ Because in the expression's type:
Context expects type: #{...}
The expected map has no corresponding key for: extra.
------------------------------ Detailed message ------------------------------
key `extra` is declared in the former but not in the latter and the latter map has no default association
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:721:25
@ -1205,14 +982,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
) -> 'a')
------------------------------ Detailed message ------------------------------
fun(('a') -> 'a') is not compatible with fun(('a' | 'b') -> 'a' | 'b')
because
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generic_fun_application.erl:752:32

View file

@ -16,15 +16,6 @@ Because in the expression's type:
Differs from the expected type: T
, T | U}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{T | U, T | U} is not compatible with {T, U}
because
T | U is not compatible with T
because
U is not compatible with T
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generics_with_unions.erl:70:19
@ -62,12 +53,6 @@ Because in the expression's type:
Here the type is: [prop('a', number())]
Context expects type: 'wrong_ret'
------------------------------ Detailed message ------------------------------
props('a', number()) is not compatible with 'wrong_ret'
because
[prop('a', number())] is not compatible with 'wrong_ret'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generics_with_unions.erl:217:19
@ -92,12 +77,6 @@ Because in the expression's type:
However the following candidate: [T]
Differs from the expected type: T
------------------------------ Detailed message ------------------------------
[T] | T is not compatible with T
because
[T] is not compatible with T
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generics_with_unions.erl:221:17
@ -114,12 +93,6 @@ Because in the expression's type:
However the following candidate: [T]
Differs from the expected type: T
------------------------------ Detailed message ------------------------------
T | [T] is not compatible with T
because
[T] is not compatible with T
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generics_with_unions.erl:222:19
@ -171,14 +144,6 @@ Because in the expression's type:
Context expects type: K
]
------------------------------ Detailed message ------------------------------
[K] | [[K]] is not compatible with [K]
because
[[K]] is not compatible with [K]
because
[K] is not compatible with K
error: ambiguous_union (See https://fb.me/eqwalizer_errors#ambiguous_union)
┌─ check/src/generics_with_unions.erl:332:31
@ -205,17 +170,6 @@ Because in the expression's type:
}
) -> 'ok')
------------------------------ Detailed message ------------------------------
query() is not compatible with fun(({'i', 'atom'}) -> 'ok')
because
fun(({'a', atom()} | {'b', binary()} | {'i', number()}) -> 'ok') is not compatible with fun(({'i', 'atom'}) -> 'ok')
because
{'i', 'atom'} is not compatible with {'a', atom()} | {'b', binary()} | {'i', number()}
because
at tuple index 2:
{'i', 'atom'} is not compatible with {'i', number()}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/generics_with_unions.erl:392:17
@ -235,15 +189,4 @@ Because in the expression's type:
}
) -> 'ok')
------------------------------ Detailed message ------------------------------
query() is not compatible with fun(({'a', number()}) -> 'ok')
because
fun(({'a', atom()} | {'b', binary()} | {'i', number()}) -> 'ok') is not compatible with fun(({'a', number()}) -> 'ok')
because
{'a', number()} is not compatible with {'a', atom()} | {'b', binary()} | {'i', number()}
because
at tuple index 2:
{'a', number()} is not compatible with {'a', atom()}
16 ERRORS

View file

@ -14,12 +14,6 @@ Because in the expression's type:
However the following candidate: 'b'
Differs from the expected type: 'c'
------------------------------ Detailed message ------------------------------
dyn('a') | 'b' is not compatible with 'c'
because
'b' is not compatible with 'c'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_bounded.erl:25:26
@ -35,16 +29,6 @@ Because in the expression's type:
Here the type is: 'a'
Context expects type: 'b'
------------------------------ Detailed message ------------------------------
'a' is not compatible with dyn('b')
because
'a' is not compatible with dynamic('b')
because
'a' is not compatible with dynamic('b')
because
'a' is not compatible with 'b'
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/gradual_bounded.erl:44:27
@ -85,12 +69,6 @@ Because in the expression's type:
However the following candidate: 'test'
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
'test' | number() is not compatible with number()
because
'test' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_bounded.erl:89:5
@ -107,10 +85,4 @@ Because in the expression's type:
However the following candidate: 'test'
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
'test' | dyn(number()) is not compatible with number()
because
'test' is not compatible with number()
8 ERRORS

View file

@ -13,12 +13,6 @@ Because in the expression's type:
Here the type is: 'undefined'
Context expects type: #{...}
------------------------------ Detailed message ------------------------------
'undefined' is not compatible with complex_map()
because
'undefined' is not compatible with #{id := number(), {secret, id} => number(), atom() => term()}
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/gradual_complex_types.erl:29:25
@ -46,12 +40,6 @@ Because in the expression's type:
Here the type is: #{...}
Context expects type: [T]
------------------------------ Detailed message ------------------------------
complex_map() is not compatible with [T]
because
#{id := number(), {secret, id} => number(), atom() => term()} is not compatible with [T]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_complex_types.erl:48:16
@ -67,12 +55,6 @@ Because in the expression's type:
Here the type is: #{...}
Context expects type: [dynamic()]
------------------------------ Detailed message ------------------------------
complex_map() is not compatible with [dynamic()]
because
#{id := number(), {secret, id} => number(), atom() => term()} is not compatible with [dynamic()]
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/gradual_complex_types.erl:55:25
@ -110,11 +92,4 @@ Because in the expression's type:
Context expects type: number()
}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{dyn_map(), 'ok'} is not compatible with {#{a => 'atom'}, number()}
because
'ok' is not compatible with number()
9 ERRORS

View file

@ -100,12 +100,6 @@ Because in the expression's type:
However the following candidate: 'a'
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
dynamic() | 'a' is not compatible with number()
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_custom.erl:120:3
@ -202,12 +196,6 @@ Because in the expression's type:
Context expects type: 'ok'
No candidate of the expression's type matches the expected type.
------------------------------ Detailed message ------------------------------
file:filename_all() is not compatible with 'ok'
because
string() | binary() is not compatible with 'ok'
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/gradual_custom.erl:210:25
@ -230,12 +218,6 @@ Because in the expression's type:
Context expects type: 'ok'
No candidate of the expression's type matches the expected type.
------------------------------ Detailed message ------------------------------
file:filename_all() is not compatible with 'ok'
because
string() | binary() is not compatible with 'ok'
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/gradual_custom.erl:217:25
@ -258,12 +240,6 @@ Because in the expression's type:
Context expects type: 'ok'
No candidate of the expression's type matches the expected type.
------------------------------ Detailed message ------------------------------
file:filename_all() is not compatible with 'ok'
because
string() | binary() is not compatible with 'ok'
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/gradual_custom.erl:224:25
@ -286,12 +262,6 @@ Because in the expression's type:
Context expects type: 'ok'
No candidate of the expression's type matches the expected type.
------------------------------ Detailed message ------------------------------
file:filename_all() is not compatible with 'ok'
because
string() | binary() is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_custom.erl:245:19
@ -308,12 +278,6 @@ Because in the expression's type:
However the following candidate: 'undefined'
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
number() | 'undefined' is not compatible with number()
because
'undefined' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_custom.erl:257:19
@ -330,12 +294,6 @@ Because in the expression's type:
However the following candidate: atom()
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
number() | atom() | binary() is not compatible with number()
because
atom() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_custom.erl:263:19
@ -352,12 +310,6 @@ Because in the expression's type:
However the following candidate: atom()
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
number() | dynamic() | number() | atom() | dynamic() is not compatible with number()
because
atom() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_custom.erl:269:19
@ -374,12 +326,6 @@ Because in the expression's type:
However the following candidate: atom()
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
number() | dynamic() | atom() | dynamic() is not compatible with number()
because
atom() is not compatible with number()
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/gradual_custom.erl:277:25
@ -402,12 +348,6 @@ Because in the expression's type:
However the following candidate: {none()}
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
dynamic() | {none()} is not compatible with number()
because
{none()} is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_custom.erl:325:13
@ -424,14 +364,6 @@ Because in the expression's type:
However the following candidate: 'undefined'
Differs from the expected type: 'foo' | 'bar' | binary()
------------------------------ Detailed message ------------------------------
'bar' | 'undefined' | 'foo' is not compatible with 'foo' | 'bar' | binary()
because
'undefined' is not compatible with 'foo' | 'bar' | binary()
because
'undefined' is not compatible with 'foo'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_custom.erl:343:3
@ -448,10 +380,4 @@ Because in the expression's type:
However the following candidate: 'bar'
Differs from the expected type: 'foo'
------------------------------ Detailed message ------------------------------
'foo' | 'bar' is not compatible with 'foo'
because
'bar' is not compatible with 'foo'
37 ERRORS

View file

@ -62,14 +62,6 @@ Because in the expression's type:
However the following candidate: 'a'
Differs from the expected type: 'b' | 'c'
------------------------------ Detailed message ------------------------------
'a' | 'b' | 'c' is not compatible with 'b' | 'c'
because
'a' is not compatible with 'b' | 'c'
because
'a' is not compatible with 'b'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_maybe.erl:147:14

View file

@ -16,16 +16,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
) -> 'ok')
------------------------------ Detailed message ------------------------------
opaque:contravariant('a') is not compatible with opaque:contravariant('a' | 'b')
because
fun(('a') -> 'ok') is not compatible with opaque:contravariant('a' | 'b')
because
fun(('a') -> 'ok') is not compatible with fun(('a' | 'b') -> 'ok')
because
'a' | 'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/gradual_misc.erl:38:5
@ -45,13 +35,8 @@ error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types
┌─ check/src/gradual_misc.erl:46:41
46 │ refine_tuple_neg(T) when is_tuple(T) -> T;
│ ^
│ │
│ T.
│ ^ T.
Expression has type: {'b', 'c'}
Context expected type: 'a' | {none()}
expected union does not contain any tuple type of size 2
4 ERRORS

View file

@ -14,14 +14,6 @@ Because in the expression's type:
However the following candidate: #r2{}
Differs from the expected type: #r1{}
------------------------------ Detailed message ------------------------------
#r1{} | #r2{} is not compatible with r1()
because
#r1{} | #r2{} is not compatible with #r1{}
because
#r2{} is not compatible with #r1{}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/guard_b_connections.erl:27:3
@ -38,14 +30,6 @@ Because in the expression's type:
However the following candidate: #r2{}
Differs from the expected type: #r1{}
------------------------------ Detailed message ------------------------------
#r1{} | #r2{} is not compatible with r1()
because
#r1{} | #r2{} is not compatible with #r1{}
because
#r2{} is not compatible with #r1{}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/guard_b_connections.erl:32:3
@ -62,14 +46,6 @@ Because in the expression's type:
However the following candidate: #r2{}
Differs from the expected type: #r1{}
------------------------------ Detailed message ------------------------------
#r1{} | #r2{} is not compatible with r1()
because
#r1{} | #r2{} is not compatible with #r1{}
because
#r2{} is not compatible with #r1{}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/guard_b_connections.erl:38:3
@ -86,14 +62,6 @@ Because in the expression's type:
However the following candidate: #r2{}
Differs from the expected type: #r1{}
------------------------------ Detailed message ------------------------------
#r1{} | #r2{} is not compatible with r1()
because
#r1{} | #r2{} is not compatible with #r1{}
because
#r2{} is not compatible with #r1{}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/guard_b_connections.erl:44:3
@ -110,12 +78,4 @@ Because in the expression's type:
However the following candidate: #r2{}
Differs from the expected type: #r1{}
------------------------------ Detailed message ------------------------------
#r1{} | #r2{} is not compatible with r1()
because
#r1{} | #r2{} is not compatible with #r1{}
because
#r2{} is not compatible with #r1{}
5 ERRORS

View file

@ -30,14 +30,6 @@ Because in the expression's type:
However the following candidate: pid()
Differs from the expected type: number() | atom()
------------------------------ Detailed message ------------------------------
number() | atom() | pid() is not compatible with number() | atom()
because
pid() is not compatible with number() | atom()
because
pid() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/guards_logic.erl:73:5
@ -55,13 +47,6 @@ Because in the expression's type:
Context expects type: number()
, term()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{term(), term()} is not compatible with {number(), number()}
because
term() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/guards_logic.erl:101:46

View file

@ -38,12 +38,6 @@ Because in the expression's type:
However the following candidate: term()
Differs from the expected type: atom()
------------------------------ Detailed message ------------------------------
term() | 'undefined' is not compatible with atom()
because
term() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/hints.erl:52:5
@ -60,12 +54,6 @@ Because in the expression's type:
However the following candidate: term()
Differs from the expected type: atom()
------------------------------ Detailed message ------------------------------
term() | 'undefined' is not compatible with atom()
because
term() is not compatible with atom()
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/hints.erl:55:1

View file

@ -23,14 +23,6 @@ Because in the expression's type:
Differs from the expected type: binary()
]
------------------------------ Detailed message ------------------------------
[atom() | binary()] is not compatible with [binary()]
because
atom() | binary() is not compatible with binary()
because
atom() is not compatible with binary()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/iolists.erl:55:22
@ -49,14 +41,6 @@ Because in the expression's type:
Differs from the expected type: atom()
]
------------------------------ Detailed message ------------------------------
[atom() | binary()] is not compatible with [atom()]
because
atom() | binary() is not compatible with atom()
because
binary() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/iolists.erl:60:27

View file

@ -16,16 +16,6 @@ Because in the expression's type:
Differs from the expected type: atom()
]
------------------------------ Detailed message ------------------------------
[atom() | binary()] is not compatible with [atom()] | [binary()]
because
[atom() | binary()] is not compatible with [atom()]
because
atom() | binary() is not compatible with atom()
because
binary() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/lists_tests.erl:16:28
@ -44,14 +34,4 @@ Because in the expression's type:
Differs from the expected type: atom()
]
------------------------------ Detailed message ------------------------------
[atom() | binary()] is not compatible with [atom()] | [binary()]
because
[atom() | binary()] is not compatible with [atom()]
because
atom() | binary() is not compatible with atom()
because
binary() is not compatible with atom()
2 ERRORS

View file

@ -127,12 +127,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [atom()]
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:116:21
@ -150,12 +144,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [atom()]
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:120:18
@ -207,12 +195,6 @@ Because in the expression's type:
Context expects type: number()
]
------------------------------ Detailed message ------------------------------
[atom()] is not compatible with [number()]
because
atom() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:143:29
@ -323,31 +305,17 @@ error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types
┌─ check/src/misc.erl:352:22
352 │ catch test69_pos(atom).
│ ^^^^
│ │
│ 'atom'.
│ ^^^^ 'atom'.
Expression has type: 'atom'
Context expected type: [atom()] | [number()]
'atom' is not compatible with [atom()] | [number()]
because
'atom' is not compatible with [atom()]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:357:22
357 │ catch test69_pos(atom).
│ ^^^^
│ │
│ 'atom'.
│ ^^^^ 'atom'.
Expression has type: 'atom'
Context expected type: [atom()] | [number()]
'atom' is not compatible with [atom()] | [number()]
because
'atom' is not compatible with [atom()]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:404:11
@ -393,17 +361,6 @@ Because in the expression's type:
]
, [atom() | number()]}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{[number() | atom()], [atom() | number()]} is not compatible with {[atom()], [number()]}
because
[number() | atom()] is not compatible with [atom()]
because
number() | atom() is not compatible with atom()
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:461:5
@ -424,17 +381,6 @@ Because in the expression's type:
]
, [atom() | number()]}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{[atom() | number()], [atom() | number()]} is not compatible with {[atom()] | [number()], [atom()] | [number()]}
because
[atom() | number()] is not compatible with [atom()] | [number()]
because
[atom() | number()] is not compatible with [atom()]
because
atom() | number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:465:12
@ -509,16 +455,6 @@ Because in the expression's type:
Differs from the expected type: atom() | number()
]
------------------------------ Detailed message ------------------------------
[atom() | binary()] is not compatible with [atom() | number()]
because
atom() | binary() is not compatible with atom() | number()
because
binary() is not compatible with atom() | number()
because
binary() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:575:14
@ -552,12 +488,6 @@ Because in the expression's type:
Context expects type: [A]
]
------------------------------ Detailed message ------------------------------
[A] is not compatible with [[A]]
because
A is not compatible with [A]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:611:21
@ -752,13 +682,6 @@ Because in the expression's type:
Context expects type: 'ok'
}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{none(), 'err'} is not compatible with {'ok', 'ok'}
because
'err' is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:741:5
@ -775,16 +698,6 @@ Because in the expression's type:
However the following candidate: 'v2_op'
Differs from the expected type: 'stuff1' | 'v0_op2' | 'stuff2' | 'v0_op1' | 'v1_op2' | ...
------------------------------ Detailed message ------------------------------
v2_op() is not compatible with v1_op()
because
'v2_op' | v1_op() is not compatible with v1_op()
because
'v2_op' | v1_op() is not compatible with 'v1_op1' | 'v1_op2' | stuff() | v0_op()
because
'v2_op' is not compatible with 'v1_op1' | 'v1_op2' | stuff() | v0_op()
error: type_alias_is_non_productive (See https://fb.me/eqwalizer_errors#type_alias_is_non_productive)
┌─ check/src/misc.erl:760:1
@ -834,16 +747,6 @@ Because in the expression's type:
Context expects type: #set{} | #{term() => []}
No candidate matches in the expected union.
------------------------------ Detailed message ------------------------------
misc:set() is not compatible with sets:set()
because
[] is not compatible with sets:set()
because
[] is not compatible with sets:set(term())
because
[] is not compatible with #set{} | #{term() => []}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:850:5
@ -861,13 +764,6 @@ Because in the expression's type:
Context expects type: pid()
}
------------------------------ Detailed message ------------------------------
at tuple index 3:
{'ok', 'lists', number()} is not compatible with {'ok', atom(), pid()}
because
number() is not compatible with pid()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:860:5
@ -907,12 +803,6 @@ Because in the expression's type:
Here the type is: {binary()}
Context expects type: [binary()]
------------------------------ Detailed message ------------------------------
{binary()} is not compatible with erlang:iovec()
because
{binary()} is not compatible with [binary()]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:949:15
@ -939,14 +829,6 @@ Because in the expression's type:
No candidate of the expression's type matches the expected type.
]
------------------------------ Detailed message ------------------------------
['MM' | 'MS' | 'EE' | 'MA' | 'GE'] is not compatible with [erlang:priority_level()]
because
'MM' | 'MS' | 'EE' | 'MA' | 'GE' is not compatible with erlang:priority_level()
because
'MM' | 'MS' | 'EE' | 'MA' | 'GE' is not compatible with 'low' | 'normal' | 'high' | 'max'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:971:5
@ -962,12 +844,6 @@ Because in the expression's type:
Here the type is: {number(), number(), number()}
Context expects type: atom()
------------------------------ Detailed message ------------------------------
erlang:timestamp() is not compatible with atom()
because
{number(), number(), number()} is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/misc.erl:987:12

View file

@ -39,13 +39,6 @@ Because in the expression's type:
Context expects type: atom()
}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{'ok', term()} is not compatible with {atom(), atom()}
because
term() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/neg.erl:27:21

View file

@ -150,12 +150,6 @@ Because in the expression's type:
However the following candidate: 'a'
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
'a' | number() is not compatible with number()
because
'a' is not compatible with number()
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/numbers.erl:538:1
@ -300,13 +294,6 @@ Because in the expression's type:
Context expects type: 'ok'
}
------------------------------ Detailed message ------------------------------
at tuple index 5:
{number(), number(), number(), number(), 'error'} is not compatible with {number(), number(), number(), number(), 'ok'}
because
'error' is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/numbers.erl:658:3

View file

@ -16,16 +16,6 @@ Because in the expression's type:
Context expects type: #{...}
The expected map has no corresponding key for: {ok, error}.
------------------------------ Detailed message ------------------------------
sets:set({'ok', 'error'}) is not compatible with sets:set({'ok', 'ok'})
because
#set{} | #{{ok, error} => []} is not compatible with sets:set({'ok', 'ok'})
because
#set{} | #{{ok, error} => []} is not compatible with #set{} | #{{ok, ok} => []}
because
#{{ok, error} => []} is not compatible with #set{} | #{{ok, ok} => []}
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/opaque.erl:29:1
@ -47,12 +37,6 @@ Because in the expression's type:
Here the type is: {'ok'}
Context expects type: none()
------------------------------ Detailed message ------------------------------
misc:o() is not compatible with none()
because
{'ok'} is not compatible with none()
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/opaque.erl:86:1
@ -93,14 +77,6 @@ Because in the expression's type:
However the following candidate: 'a'
Differs from the expected type: {'ok'}
------------------------------ Detailed message ------------------------------
misc:o() | 'a' is not compatible with misc:o()
because
misc:o() | 'a' is not compatible with {'ok'}
because
'a' is not compatible with {'ok'}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/opaque.erl:135:18
@ -117,14 +93,6 @@ Because in the expression's type:
However the following candidate: 'a'
Differs from the expected type: {'ok'}
------------------------------ Detailed message ------------------------------
misc:o() | 'a' is not compatible with misc:o()
because
misc:o() | 'a' is not compatible with {'ok'}
because
'a' is not compatible with {'ok'}
error: type_alias_is_non_productive (See https://fb.me/eqwalizer_errors#type_alias_is_non_productive)
┌─ check/src/opaque.erl:150:1

View file

@ -13,12 +13,6 @@ Because in the expression's type:
Here the type is: term()
Context expects type: #{...}
------------------------------ Detailed message ------------------------------
term() is not compatible with logger:metadata()
because
term() is not compatible with #{domain => [atom()], file => file:filename(), gl => pid(), line => number(), mfa => {atom(), atom(), number()}, pid => pid(), report_cb => logger:report_cb(), time => logger:timestamp(), atom() => term()}
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/other.erl:59:27

View file

@ -14,14 +14,6 @@ Because in the expression's type:
Context expects type: 'ok' | 'error'
No candidate matches in the expected union.
------------------------------ Detailed message ------------------------------
'warning' is not compatible with foo()
because
'warning' is not compatible with 'ok' | 'error'
because
'warning' is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/otp28.erl:28:5
@ -39,12 +31,6 @@ Because in the expression's type:
Context expects type: atom()
]
------------------------------ Detailed message ------------------------------
[number()] is not compatible with [atom()]
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/otp28.erl:40:5
@ -62,12 +48,6 @@ Because in the expression's type:
Context expects type: pid()
]
------------------------------ Detailed message ------------------------------
[binary()] is not compatible with [pid()]
because
binary() is not compatible with pid()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/otp28.erl:52:5
@ -95,15 +75,6 @@ Because in the expression's type:
}
]
------------------------------ Detailed message ------------------------------
[{atom(), binary()}] is not compatible with [{atom(), atom()}]
because
at tuple index 2:
{atom(), binary()} is not compatible with {atom(), atom()}
because
binary() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/otp28.erl:68:5
@ -121,13 +92,6 @@ Because in the expression's type:
Context expects type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{atom() => binary()} is not compatible with #{atom() => atom()}
the default associations are not compatible
because
binary() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/otp28.erl:76:5
@ -147,13 +111,4 @@ Because in the expression's type:
, atom()}
]
------------------------------ Detailed message ------------------------------
[{atom(), binary(), binary(), atom()}] is not compatible with [{atom(), binary(), atom(), binary()}]
because
at tuple index 3:
{atom(), binary(), binary(), atom()} is not compatible with {atom(), binary(), atom(), binary()}
because
binary() is not compatible with atom()
7 ERRORS

View file

@ -17,17 +17,6 @@ Because in the expression's type:
, term(), term()}
}
------------------------------ Detailed message ------------------------------
gb_sets:set(atom()) is not compatible with gb_sets:set(number())
because
{number(), gb_sets:gb_set_node(atom())} is not compatible with gb_sets:set(number())
because
at tuple index 2:
{number(), gb_sets:gb_set_node(atom())} is not compatible with {number(), gb_sets:gb_set_node(number())}
because
gb_sets:gb_set_node(atom()) is not compatible with gb_sets:gb_set_node(number())
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/otp_opaques.erl:42:5
@ -45,12 +34,6 @@ Because in the expression's type:
Context expects type: A
]
------------------------------ Detailed message ------------------------------
[[A]] is not compatible with [A]
because
[A] is not compatible with A
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/otp_opaques.erl:99:17
@ -67,14 +50,6 @@ Because in the expression's type:
Context expects type: #set{} | #{a => []}
No candidate of the expression's type matches the expected type.
------------------------------ Detailed message ------------------------------
maps:iterator('k', 'v') is not compatible with sets:set('a')
because
{'k', 'v', maps:iterator('k', 'v')} | 'none' | [number()] | [['k']] is not compatible with sets:set('a')
because
{'k', 'v', maps:iterator('k', 'v')} | 'none' | [number()] | [['k']] is not compatible with #set{} | #{a => []}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/otp_opaques.erl:102:13
@ -99,14 +74,6 @@ Because in the expression's type:
Context expects type: #set{} | #{a => []}
No candidate of the expression's type matches the expected type.
------------------------------ Detailed message ------------------------------
maps:iterator('k', 'v') is not compatible with sets:set('a')
because
{'k', 'v', maps:iterator('k', 'v')} | 'none' | [number()] | [['k']] is not compatible with sets:set('a')
because
{'k', 'v', maps:iterator('k', 'v')} | 'none' | [number()] | [['k']] is not compatible with #set{} | #{a => []}
error: expected_fun_type (See https://fb.me/eqwalizer_errors#expected_fun_type)
┌─ check/src/otp_opaques.erl:124:5

View file

@ -30,26 +30,13 @@ Because in the expression's type:
Context expects type: 'b'
)
------------------------------ Detailed message ------------------------------
fun(('a') -> 'z') is not compatible with fun(('a') -> 'b') | fun(('a') -> 'c')
because
fun(('a') -> 'z') is not compatible with fun(('a') -> 'b')
because
'z' is not compatible with 'b'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/overloaded.erl:126:15
126 │ Res = bar({fun(a) -> a end}),
│ ^^^^^^^^^^^^^^^^^
│ │
│ {fun}.
│ ^^^^^^^^^^^^^^^^^ {fun}.
Expression has type: {fun((dynamic()) -> dynamic())}
Context expected type: fun(('a') -> 'b') | fun(('a') -> 'c')
expected union does not contain any tuple type of size 1
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/overloaded.erl:198:37
@ -107,12 +94,6 @@ Because in the expression's type:
However the following candidate: {}
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
number() | {} is not compatible with number()
because
{} is not compatible with number()
error: unbound_type_var (See https://fb.me/eqwalizer_errors#unbound_type_var)
┌─ check/src/overloaded.erl:261:1
@ -130,16 +111,9 @@ error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types
┌─ check/src/overloaded.erl:269:14
269 │ _ = swap(""),
│ ^^
│ │
│ string_lit.
│ ^^ string_lit.
Expression has type: []
Context expected type: atom() | binary()
[] is not compatible with atom() | binary()
because
[] is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/overloaded.erl:290:5

View file

@ -14,12 +14,6 @@ Because in the expression's type:
However the following candidate: pid()
Differs from the expected type: atom()
------------------------------ Detailed message ------------------------------
atom() | pid() is not compatible with atom()
because
pid() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/overloaded_specs_union.erl:19:29
@ -36,12 +30,4 @@ Because in the expression's type:
However the following candidate: pid()
Differs from the expected type: atom() | binary()
------------------------------ Detailed message ------------------------------
atom() | binary() | pid() is not compatible with atom() | binary()
because
pid() is not compatible with atom() | binary()
because
pid() is not compatible with atom()
2 ERRORS

View file

@ -14,10 +14,4 @@ Because in the expression's type:
However the following candidate: 'error'
Differs from the expected type: #{term() => term()}
------------------------------ Detailed message ------------------------------
#{a => 'ok'} | 'error' is not compatible with #{term() => term()}
because
'error' is not compatible with #{term() => term()}
1 ERROR

View file

@ -18,16 +18,9 @@ error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types
┌─ check/src/records.erl:50:21
50 │ mk_rec_neg(rec2) -> #rec2{}.
│ ^^^^^^^
│ │
│ #rec2{...}.
│ ^^^^^^^ #rec2{...}.
Expression has type: #rec2{}
Context expected type: #rec1{} | #rec3{}
#rec2{} is not compatible with #rec1{} | #rec3{}
because
#rec2{} is not compatible with #rec1{}
error: undefined_field (See https://fb.me/eqwalizer_errors#undefined_field)
┌─ check/src/records.erl:59:11
@ -108,13 +101,6 @@ Because in the expression's type:
Context expects type: number()
, number()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{atom(), number()} is not compatible with {number(), atom()}
because
atom() is not compatible with number()
error: undefined_field (See https://fb.me/eqwalizer_errors#undefined_field)
┌─ check/src/records.erl:144:17
@ -181,14 +167,6 @@ Because in the expression's type:
Context expects type: number()
}
------------------------------ Detailed message ------------------------------
#any_box{inner :: 'ok'} is not compatible with int_box()
because
#any_box{inner :: 'ok'} is not compatible with #any_box{inner :: number()}
because
'ok' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:222:5
@ -206,12 +184,6 @@ Because in the expression's type:
Context expects type: number()
}
------------------------------ Detailed message ------------------------------
#any_box{inner :: 'ok'} is not compatible with #any_box{inner :: number()}
because
'ok' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:282:27
@ -228,12 +200,6 @@ Because in the expression's type:
Context expects type: number() | 'false' | 'true'
No candidate matches in the expected union.
------------------------------ Detailed message ------------------------------
'a' is not compatible with number() | boolean()
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:287:23
@ -250,12 +216,6 @@ Because in the expression's type:
Context expects type: number() | 'false' | 'true'
No candidate matches in the expected union.
------------------------------ Detailed message ------------------------------
'a' is not compatible with number() | boolean()
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:292:5
@ -273,14 +233,6 @@ Because in the expression's type:
Context expects type: number()
}
------------------------------ Detailed message ------------------------------
#int_bool_box{inner :: 'true'} is not compatible with only_int_box()
because
#int_bool_box{inner :: 'true'} is not compatible with #int_bool_box{inner :: number()}
because
'true' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:308:28
@ -297,12 +249,6 @@ Because in the expression's type:
Context expects type: number() | 'false' | 'true'
No candidate matches in the expected union.
------------------------------ Detailed message ------------------------------
'a' is not compatible with number() | boolean()
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:314:5
@ -320,14 +266,6 @@ Because in the expression's type:
Context expects type: boolean()
}
------------------------------ Detailed message ------------------------------
#int_bool_box{inner :: number()} is not compatible with only_bool_box()
because
#int_bool_box{inner :: number()} is not compatible with #int_bool_box{inner :: boolean()}
because
number() is not compatible with boolean()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:319:5
@ -343,12 +281,6 @@ Because in the expression's type:
Here the type is: #int_bool_box{inner :: number()}
Context expects type: #any_box{}
------------------------------ Detailed message ------------------------------
only_int_box() is not compatible with #any_box{}
because
#int_bool_box{inner :: number()} is not compatible with #any_box{}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:319:5
@ -383,15 +315,6 @@ Because in the expression's type:
No candidate matches in the expected union.
}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{'int_bool_box', 'a'} is not compatible with {'int_bool_box', number() | boolean()}
because
'a' is not compatible with number() | boolean()
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:334:5
@ -409,15 +332,6 @@ Because in the expression's type:
Context expects type: number()
}
------------------------------ Detailed message ------------------------------
{'int_bool_box', 'a'} is not compatible with only_int_box()
because
at tuple index 2:
{'int_bool_box', 'a'} is not compatible with {'int_bool_box', number()}
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:352:5
@ -434,12 +348,6 @@ Because in the expression's type:
However the following candidate: 'false'
Differs from the expected type: 'true'
------------------------------ Detailed message ------------------------------
boolean() | 'true' is not compatible with 'true'
because
'false' is not compatible with 'true'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:355:13
@ -463,12 +371,6 @@ Because in the expression's type:
Here the type is: #bad_default{}
Context expects type: #int_bool_box{inner :: number()}
------------------------------ Detailed message ------------------------------
#bad_default{} is not compatible with only_int_box()
because
#bad_default{} is not compatible with #int_bool_box{inner :: number()}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:372:5
@ -486,13 +388,6 @@ Because in the expression's type:
Context expects type: 'bad_default'
, number()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{'int_bool_box', number()} is not compatible with {'bad_default', number()}
because
'int_bool_box' is not compatible with 'bad_default'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:388:31
@ -510,12 +405,6 @@ Because in the expression's type:
Context expects type: number()
}
------------------------------ Detailed message ------------------------------
#refined_two_fields{} is not compatible with #refined_two_fields{inner :: number()}
because
term() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/records.erl:402:5
@ -594,12 +483,6 @@ Because in the expression's type:
However the following candidate: 'my_record'
Differs from the expected type: binary()
------------------------------ Detailed message ------------------------------
'my_record' | binary() is not compatible with binary()
because
'my_record' is not compatible with binary()
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/records.erl:517:1

View file

@ -17,16 +17,6 @@ Because in the expression's type:
Context expects type: 'b'
, chainA()}
------------------------------ Detailed message ------------------------------
chainA() is not compatible with chainB()
because
'nil' | {'a', chainA()} is not compatible with chainB()
because
'nil' | {'a', chainA()} is not compatible with 'nil' | {'b', chainB()}
because
{'a', chainA()} is not compatible with 'nil' | {'b', chainB()}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/recursive_aliases.erl:62:20
@ -46,16 +36,6 @@ Because in the expression's type:
Context expects type: 'a'
, chainB()}
------------------------------ Detailed message ------------------------------
chainB() is not compatible with chainA()
because
'nil' | {'b', chainB()} is not compatible with chainA()
because
'nil' | {'b', chainB()} is not compatible with 'nil' | {'a', chainA()}
because
{'b', chainB()} is not compatible with 'nil' | {'a', chainA()}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/recursive_aliases.erl:65:20
@ -75,16 +55,6 @@ Because in the expression's type:
Context expects type: 'a'
, chainAB()}
------------------------------ Detailed message ------------------------------
chainAB() is not compatible with chainA()
because
'nil' | {'a', chainAB()} | {'b', chainAB()} is not compatible with chainA()
because
'nil' | {'a', chainAB()} | {'b', chainAB()} is not compatible with 'nil' | {'a', chainA()}
because
{'b', chainAB()} is not compatible with 'nil' | {'a', chainA()}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/recursive_aliases.erl:68:20
@ -104,16 +74,6 @@ Because in the expression's type:
Context expects type: 'b'
, chainAB()}
------------------------------ Detailed message ------------------------------
chainAB() is not compatible with chainB()
because
'nil' | {'a', chainAB()} | {'b', chainAB()} is not compatible with chainB()
because
'nil' | {'a', chainAB()} | {'b', chainAB()} is not compatible with 'nil' | {'b', chainB()}
because
{'a', chainAB()} is not compatible with 'nil' | {'b', chainB()}
error: type_alias_is_non_productive (See https://fb.me/eqwalizer_errors#type_alias_is_non_productive)
┌─ check/src/recursive_aliases.erl:70:1
@ -143,17 +103,6 @@ Because in the expression's type:
However the following candidate: {'a', atom(), pchainA(atom())}
Differs from the expected type: 'nil' | {'a', pchainAB(atom())} | {'b', pchainAB(atom())}
------------------------------ Detailed message ------------------------------
pchainA(atom()) is not compatible with pchainAB(atom())
because
'nil' | {'a', atom(), pchainA(atom())} is not compatible with pchainAB(atom())
because
'nil' | {'a', atom(), pchainA(atom())} is not compatible with 'nil' | {'a', pchainAB(atom())} | {'b', pchainAB(atom())}
because
{'a', atom(), pchainA(atom())} is not compatible with 'nil' | {'a', pchainAB(atom())} | {'b', pchainAB(atom())}
expected union does not contain any tuple type of size 3
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/recursive_aliases.erl:113:23
@ -172,16 +121,6 @@ Because in the expression's type:
Context expects type: #{a := ..., ...}
The type of the expression is missing the following required keys: a.
------------------------------ Detailed message ------------------------------
mChainB() is not compatible with mChainA()
because
'nil' | #{b := mChainB()} is not compatible with mChainA()
because
'nil' | #{b := mChainB()} is not compatible with 'nil' | #{a := mChainA()}
because
#{b := mChainB()} is not compatible with 'nil' | #{a := mChainA()}
error: expected_fun_type (See https://fb.me/eqwalizer_errors#expected_fun_type)
┌─ check/src/recursive_aliases.erl:138:15
@ -210,16 +149,6 @@ Because in the expression's type:
No candidate matches in the expected union.
, pchainA('a')}
------------------------------ Detailed message ------------------------------
pchainA('a') is not compatible with pchainA('b' | 'c')
because
'nil' | {'a', 'a', pchainA('a')} is not compatible with pchainA('b' | 'c')
because
'nil' | {'a', 'a', pchainA('a')} is not compatible with 'nil' | {'a', 'b' | 'c', pchainA('b' | 'c')}
because
{'a', 'a', pchainA('a')} is not compatible with 'nil' | {'a', 'b' | 'c', pchainA('b' | 'c')}
error: type_alias_is_non_productive (See https://fb.me/eqwalizer_errors#type_alias_is_non_productive)
┌─ check/src/recursive_aliases.erl:202:1

View file

@ -23,13 +23,6 @@ Because in the expression's type:
Context expects type: none()
, A}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{B, A} is not compatible with {none(), none()}
because
B is not compatible with none()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:22:15
@ -55,12 +48,6 @@ Because in the expression's type:
Context expects type: none()
)
------------------------------ Detailed message ------------------------------
fun((B | A) -> A) is not compatible with fun((A | B) -> none())
because
A is not compatible with none()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:34:16
@ -78,12 +65,6 @@ Because in the expression's type:
Context expects type: none()
)
------------------------------ Detailed message ------------------------------
fun((atom() | A) -> A) is not compatible with fun((A | atom()) -> none())
because
A is not compatible with none()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:84:27
@ -133,13 +114,6 @@ Because in the expression's type:
Context expects type: none()
, binary()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{number(), binary()} is not compatible with {none(), none()}
because
number() is not compatible with none()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:126:32
@ -157,13 +131,6 @@ Because in the expression's type:
Context expects type: none()
, atom()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{number(), atom()} is not compatible with {none(), none()}
because
number() is not compatible with none()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:139:28
@ -190,14 +157,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
]
------------------------------ Detailed message ------------------------------
['a' | 'b'] is not compatible with ['a']
because
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:151:28
@ -224,14 +183,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
]
------------------------------ Detailed message ------------------------------
['a' | 'b'] is not compatible with ['a']
because
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:166:5
@ -273,13 +224,6 @@ Because in the expression's type:
Context expects type: 'not_my_rec'
, number(), atom()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{'my_rec', number(), atom()} is not compatible with {'not_my_rec', term(), term()}
because
'my_rec' is not compatible with 'not_my_rec'
error: unknown_id (See https://fb.me/eqwalizer_errors#unknown_id)
┌─ check/src/refine.erl:199:10
@ -310,13 +254,6 @@ Because in the expression's type:
Context expects type: number()
, number()}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{'my_rec', atom(), number()} is not compatible with {'my_rec', number(), atom()}
because
atom() is not compatible with number()
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/refine.erl:218:1
@ -374,13 +311,6 @@ Because in the expression's type:
Context expects type: number()
, number()}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{'my_rec', atom(), number()} is not compatible with {'my_rec', number(), atom()}
because
atom() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:250:26
@ -398,15 +328,6 @@ Because in the expression's type:
Context expects type: number()
, number()}
------------------------------ Detailed message ------------------------------
{'my_rec', atom(), number()} is not compatible with dynamic(#my_rec{})
because
at tuple index 2:
{'my_rec', atom(), number()} is not compatible with {'my_rec', number(), atom()}
because
atom() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:262:26
@ -424,13 +345,6 @@ Because in the expression's type:
Context expects type: atom()
, atom()}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{'my_rec', number(), atom()} is not compatible with {'my_rec', atom(), number()}
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:262:26
@ -448,15 +362,6 @@ Because in the expression's type:
Context expects type: atom()
, atom()}
------------------------------ Detailed message ------------------------------
#my_rec{} is not compatible with dynamic({'my_rec', atom(), number()})
because
at tuple index 2:
{'my_rec', number(), atom()} is not compatible with {'my_rec', atom(), number()}
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:278:21
@ -474,13 +379,6 @@ Because in the expression's type:
Context expects type: atom()
, atom()}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{'my_rec', number(), atom()} is not compatible with {'my_rec', atom(), atom()}
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:282:16
@ -497,12 +395,6 @@ Because in the expression's type:
However the following candidate: atom()
Differs from the expected type: number()
------------------------------ Detailed message ------------------------------
atom() | number() is not compatible with number()
because
atom() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:286:13
@ -519,12 +411,6 @@ Because in the expression's type:
However the following candidate: 'a'
Differs from the expected type: {'my_rec', term(), term()}
------------------------------ Detailed message ------------------------------
#my_rec{} | 'a' is not compatible with {'my_rec', term(), term()}
because
'a' is not compatible with {'my_rec', term(), term()}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/refine.erl:296:5
@ -541,12 +427,6 @@ Because in the expression's type:
However the following candidate: 'undefined'
Differs from the expected type: binary()
------------------------------ Detailed message ------------------------------
'undefined' | binary() is not compatible with binary()
because
'undefined' is not compatible with binary()
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/refine.erl:378:27

View file

@ -13,12 +13,6 @@ Because in the expression's type:
Here the type is: 'undefined'
Context expects type: #{...}
------------------------------ Detailed message ------------------------------
'undefined' is not compatible with complex_map()
because
'undefined' is not compatible with #{id := number(), {secret, id} => number(), atom() => term()}
error: reveal_type (See https://fb.me/eqwalizer_errors#reveal_type)
┌─ check/src/strict_complex_types.erl:29:25
@ -46,12 +40,6 @@ Because in the expression's type:
Here the type is: #{...}
Context expects type: [T]
------------------------------ Detailed message ------------------------------
complex_map() is not compatible with [T]
because
#{id := number(), {secret, id} => number(), atom() => term()} is not compatible with [T]
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/strict_complex_types.erl:48:16
@ -67,10 +55,4 @@ Because in the expression's type:
Here the type is: #{...}
Context expects type: [dynamic()]
------------------------------ Detailed message ------------------------------
complex_map() is not compatible with [dynamic()]
because
#{id := number(), {secret, id} => number(), atom() => term()} is not compatible with [dynamic()]
5 ERRORS

View file

@ -31,12 +31,6 @@ Because in the expression's type:
Context expects type: atom()
)
------------------------------ Detailed message ------------------------------
fun((atom()) -> term()) is not compatible with fun((term()) -> atom())
because
term() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:27:11
@ -53,14 +47,6 @@ Because in the expression's type:
However the following candidate: 'c'
Differs from the expected type: 'a' | 'b'
------------------------------ Detailed message ------------------------------
'a' | 'b' | 'c' is not compatible with 'a' | 'b'
because
'c' is not compatible with 'a' | 'b'
because
'c' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:30:11
@ -87,17 +73,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
, 'a' | 'b'}
------------------------------ Detailed message ------------------------------
{'a' | 'b', 'a' | 'b'} is not compatible with {'a', 'b'} | {'b', 'a'}
because
at tuple index 1:
{'a' | 'b', 'a' | 'b'} is not compatible with {'a', 'b'}
because
'a' | 'b' is not compatible with 'a'
because
'b' is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:38:11
@ -116,17 +91,6 @@ Because in the expression's type:
Differs from the expected type: 'a'
, ab()}
------------------------------ Detailed message ------------------------------
pair_ab() is not compatible with pair_diff_elems()
because
{ab(), ab()} is not compatible with pair_diff_elems()
because
{ab(), ab()} is not compatible with {'a', 'b'} | {'b', 'a'}
because
at tuple index 1:
{ab(), ab()} is not compatible with {'a', 'b'}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:41:11
@ -151,10 +115,6 @@ Because in the expression's type:
Context expects type: #{a := ..., ...}
The type of the expression is missing the following required keys: a.
------------------------------ Detailed message ------------------------------
key `a` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:52:13
@ -171,10 +131,6 @@ Because in the expression's type:
Context expects type: #{...}
The expected map has no corresponding key for: b.
------------------------------ Detailed message ------------------------------
key `b` is declared in the former but not in the latter and the latter map has no default association
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:60:13
@ -191,10 +147,6 @@ Because in the expression's type:
Context expects type: #{a := ..., ...}
The type of the expression is missing the following required keys: a.
------------------------------ Detailed message ------------------------------
key `a` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:64:13
@ -212,13 +164,6 @@ Because in the expression's type:
Context expects type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{term() => number()} is not compatible with #{atom() => number()}
the default associations are not compatible
because
term() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:68:13
@ -236,13 +181,6 @@ Because in the expression's type:
Context expects type: number()
, ... }
------------------------------ Detailed message ------------------------------
#{atom() => term()} is not compatible with #{atom() => number()}
the default associations are not compatible
because
term() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:72:13
@ -259,13 +197,6 @@ Because in the expression's type:
Context expects type: #{...} (no default association)
The expected map has no default association while the type of the expression has one.
------------------------------ Detailed message ------------------------------
#{atom() => term()} is not compatible with #{}
because
#{atom() => term()} is not compatible with #{}
the latter map has no default association while the first map has one
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:79:15
@ -291,13 +222,6 @@ Because in the expression's type:
Context expects type: 'ok'
}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{{}, 'error'} is not compatible with {tuple(), 'ok'}
because
'error' is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:87:5
@ -315,13 +239,6 @@ Because in the expression's type:
Context expects type: 'ok'
}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{[], 'error'} is not compatible with {[pid()], 'ok'}
because
'error' is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:91:5
@ -339,13 +256,6 @@ Because in the expression's type:
Context expects type: 'ok'
}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{[], 'error'} is not compatible with {iolist(), 'ok'}
because
'error' is not compatible with 'ok'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/subtype_neg.erl:94:13
@ -382,10 +292,4 @@ Because in the expression's type:
Context expects type: none()
]
------------------------------ Detailed message ------------------------------
['a'] | [none()] is not compatible with []
because
['a'] is not compatible with []
20 ERRORS

View file

@ -15,13 +15,6 @@ Because in the expression's type:
Context expects type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{number() => number()} is not compatible with #{number() => atom()}
the default associations are not compatible
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:41:5
@ -40,15 +33,6 @@ Because in the expression's type:
Differs from the expected type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{number() => 'zero' | number()} is not compatible with #{number() => atom()}
the default associations are not compatible
because
'zero' | number() is not compatible with atom()
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:56:5
@ -66,15 +50,6 @@ Because in the expression's type:
Context expects type: number()
, ... }
------------------------------ Detailed message ------------------------------
#{one := 'one', zero := number()} is not compatible with #{one => number(), zero := number()}
because
at key `one`:
#{one := 'one', zero := number()} is not compatible with #{one => number(), zero := number()}
because
'one' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:80:5
@ -108,15 +83,6 @@ Because in the expression's type:
Context expects type: n()
, ... }
------------------------------ Detailed message ------------------------------
#{b() => term()} is not compatible with #{n() => term()}
the default associations are not compatible
because
b() is not compatible with n()
because
boolean() is not compatible with n()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:140:26
@ -134,17 +100,6 @@ Because in the expression's type:
Context expects type: n()
, ... }
------------------------------ Detailed message ------------------------------
#{a := b()} is not compatible with #{a := n()}
because
at key `a`:
#{a := b()} is not compatible with #{a := n()}
because
b() is not compatible with n()
because
boolean() is not compatible with n()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:145:26
@ -162,17 +117,6 @@ Because in the expression's type:
Context expects type: n()
, ... }
------------------------------ Detailed message ------------------------------
#{a := b()} is not compatible with #{a => n()}
because
at key `a`:
#{a := b()} is not compatible with #{a => n()}
because
b() is not compatible with n()
because
boolean() is not compatible with n()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:155:26
@ -189,10 +133,6 @@ Because in the expression's type:
Context expects type: #{a := ..., ...}
The type of the expression is missing the following required keys: a.
------------------------------ Detailed message ------------------------------
key `a` is declared as required in the latter but not in the former
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/t_maps.erl:165:1
@ -216,17 +156,6 @@ Because in the expression's type:
Context expects type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{a := a(), n() => a()} is not compatible with #{a() => a()}
the default associations are not compatible
because
n() is not compatible with a()
because
number() is not compatible with a()
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:208:5
@ -244,17 +173,6 @@ Because in the expression's type:
Context expects type: number()
, ... }
------------------------------ Detailed message ------------------------------
#{a := a(), n() => a()} is not compatible with #{n() => a()}
because
#{a := a(), n() => a()} is not compatible with #{n() => a()}
key `a` is declared in the former but not in the latter and key `a` isn't compatible with the default association of the latter map
because
'a' is not compatible with n()
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:216:5
@ -272,17 +190,6 @@ Because in the expression's type:
Context expects type: number()
, ... }
------------------------------ Detailed message ------------------------------
#{a := a(), n() => a()} is not compatible with #{n() => a()}
because
#{a := a(), n() => a()} is not compatible with #{n() => a()}
key `a` is declared in the former but not in the latter and key `a` isn't compatible with the default association of the latter map
because
'a' is not compatible with n()
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:224:5
@ -300,17 +207,6 @@ Because in the expression's type:
Context expects type: number()
, ... }
------------------------------ Detailed message ------------------------------
#{a => a(), n() => a()} is not compatible with #{n() => a()}
because
#{a => a(), n() => a()} is not compatible with #{n() => a()}
key `a` is declared in the former but not in the latter and key `a` isn't compatible with the default association of the latter map
because
'a' is not compatible with n()
because
'a' is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:242:5
@ -328,17 +224,6 @@ Because in the expression's type:
Context expects type: F1
, ... }
------------------------------ Detailed message ------------------------------
#{bar := B1, foo := F1} is not compatible with foo_bar(B1, F1)
because
#{bar := B1, foo := F1} is not compatible with #{bar := F1, foo := B1}
because
at key `bar`:
#{bar := B1, foo := F1} is not compatible with #{bar := F1, foo := B1}
because
B1 is not compatible with F1
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:254:5
@ -356,17 +241,6 @@ Because in the expression's type:
Context expects type: F1
, ... }
------------------------------ Detailed message ------------------------------
#{bar := B1, foo := F1} is not compatible with foo_bar_opt(B1, F1)
because
#{bar := B1, foo := F1} is not compatible with #{bar => F1, foo => B1}
because
at key `bar`:
#{bar := B1, foo := F1} is not compatible with #{bar => F1, foo => B1}
because
B1 is not compatible with F1
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:266:5
@ -385,17 +259,6 @@ Because in the expression's type:
Differs from the expected type: K1 | K2
, ... }
------------------------------ Detailed message ------------------------------
#{K1 | V2 => V1 | K2} is not compatible with kv(K1 | K2, V1 | V2)
because
#{K1 | V2 => V1 | K2} is not compatible with #{K1 | K2 => V1 | V2}
the default associations are not compatible
because
K1 | V2 is not compatible with K1 | K2
because
V2 is not compatible with K1 | K2
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:283:19
@ -412,10 +275,6 @@ Because in the expression's type:
Context expects type: #{...}
The expected map has no corresponding key for: b.
------------------------------ Detailed message ------------------------------
key `b` is declared in the former but not in the latter and the latter map has no default association
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:307:22
@ -433,17 +292,6 @@ Because in the expression's type:
Context expects type: number()
, n()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{a(), n()} is not compatible with {n(), a()}
because
a() is not compatible with n()
because
atom() is not compatible with n()
because
atom() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:321:5
@ -461,17 +309,6 @@ Because in the expression's type:
Context expects type: number()
, n()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{a(), n()} is not compatible with {n(), a()}
because
a() is not compatible with n()
because
atom() is not compatible with n()
because
atom() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:334:25
@ -489,13 +326,6 @@ Because in the expression's type:
Context expects type: K
, ... }
------------------------------ Detailed message ------------------------------
#{V => K} is not compatible with #{K => V}
the default associations are not compatible
because
V is not compatible with K
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:351:25
@ -515,17 +345,6 @@ Because in the expression's type:
Context expects type: atom()
, ... }
------------------------------ Detailed message ------------------------------
#{a() => n()} | #{n() => a()} | #{id => 'id' | 'no_id'} is not compatible with #{a() | n() => a()}
because
#{a() => n()} is not compatible with #{a() | n() => a()}
the default associations are not compatible
because
n() is not compatible with a()
because
number() is not compatible with a()
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/t_maps.erl:356:1
@ -556,15 +375,6 @@ Because in the expression's type:
No candidate of the expression's type matches the expected type.
, a()}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{'a' | 'b', a()} is not compatible with {n(), a()}
because
'a' | 'b' is not compatible with n()
because
'a' | 'b' is not compatible with number()
error: clause_not_covered (See https://fb.me/eqwalizer_errors#clause_not_covered)
┌─ check/src/t_maps.erl:429:1
@ -611,10 +421,6 @@ Because in the expression's type:
Context expects type: #{n := ..., ...}
The type of the expression is missing the following required keys: n.
------------------------------ Detailed message ------------------------------
key `n` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:536:5
@ -633,17 +439,6 @@ Because in the expression's type:
Differs from the expected type: 'b' | 'c'
, ... }
------------------------------ Detailed message ------------------------------
#{a => 'b' | 'c' | 'a'} is not compatible with #{a => 'b' | 'c'}
because
at key `a`:
#{a => 'b' | 'c' | 'a'} is not compatible with #{a => 'b' | 'c'}
because
'b' | 'c' | 'a' is not compatible with 'b' | 'c'
because
'a' is not compatible with 'b' | 'c'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:571:5
@ -660,15 +455,6 @@ Because in the expression's type:
Context expects type: #{item_v2 := ..., ...}
The type of the expression is missing the following required keys: item_v2.
------------------------------ Detailed message ------------------------------
rec_shape() is not compatible with rec_shape_v2()
because
#{item := rec_shape() | 'undefined'} is not compatible with rec_shape_v2()
because
#{item := rec_shape() | 'undefined'} is not compatible with #{item_v2 := rec_shape_v2() | 'undefined'}
key `item_v2` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:629:5
@ -687,14 +473,6 @@ Because in the expression's type:
Differs from the expected type: 'a' | #{item := 'a' | gen_shape('a')}
, ... }
------------------------------ Detailed message ------------------------------
gen_shape('a' | 'b') is not compatible with 'a' | #{item := 'a' | #{item := 'a' | gen_shape('a')}}
because
#{item := 'a' | 'b' | gen_shape('a' | 'b')} is not compatible with 'a' | #{item := 'a' | #{item := 'a' | gen_shape('a')}}
because
#{item := 'a' | 'b' | gen_shape('a' | 'b')} is not compatible with 'a'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:641:5
@ -711,15 +489,6 @@ Because in the expression's type:
Context expects type: #{item := ..., ...}
The type of the expression is missing the following required keys: item.
------------------------------ Detailed message ------------------------------
gen_shape_v2('a') is not compatible with gen_shape('a')
because
#{item_v2 := 'a' | gen_shape_v2('a')} is not compatible with gen_shape('a')
because
#{item_v2 := 'a' | gen_shape_v2('a')} is not compatible with #{item := 'a' | gen_shape('a')}
key `item` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:648:5
@ -736,10 +505,6 @@ Because in the expression's type:
Context expects type: #{...}
The expected map has no corresponding key for: d.
------------------------------ Detailed message ------------------------------
key `d` is declared in the former but not in the latter and the latter map has no default association
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:661:5
@ -757,15 +522,6 @@ Because in the expression's type:
Context expects type: 'ka'
, ... }
------------------------------ Detailed message ------------------------------
#{a => 'va', b => 'vb', c => 'vc', d => 'vd', e => 've'} is not compatible with #{a => 'ka', b => 'kb', c => 'kc'}
because
at key `a`:
#{a => 'va', b => 'vb', c => 'vc', d => 'vd', e => 've'} is not compatible with #{a => 'ka', b => 'kb', c => 'kc'}
because
'va' is not compatible with 'ka'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:675:5
@ -782,10 +538,6 @@ Because in the expression's type:
Context expects type: #{c := ..., ...}
The type of the expression is missing the following required keys: c.
------------------------------ Detailed message ------------------------------
key `c` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:682:5
@ -802,10 +554,6 @@ Because in the expression's type:
Context expects type: #{b := ..., ...}
The type of the expression is missing the following required keys: b.
------------------------------ Detailed message ------------------------------
key `b` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:689:5
@ -822,10 +570,6 @@ Because in the expression's type:
Context expects type: #{b := ..., ...}
The type of the expression is missing the following required keys: b.
------------------------------ Detailed message ------------------------------
key `b` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:710:5
@ -842,10 +586,6 @@ Because in the expression's type:
Context expects type: #{k_req3 := ..., k_req2 := ..., k_req1 := ..., ...}
The type of the expression is missing the following required keys: k_req3, k_req2, k_req1.
------------------------------ Detailed message ------------------------------
keys `k_req1`, `k_req2`, `k_req3` are declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:732:27
@ -862,13 +602,6 @@ Because in the expression's type:
Context expects type: #{...} (no default association)
The expected map has no default association while the type of the expression has one.
------------------------------ Detailed message ------------------------------
#{'a' | 'b' => boolean()} is not compatible with #{a => 'true', b => boolean()}
key a is not present in the former map but is incompatible with its default association
because
boolean() is not compatible with 'true'
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:737:27
@ -885,10 +618,6 @@ Because in the expression's type:
Context expects type: #{b := ..., ...}
The type of the expression is missing the following required keys: b.
------------------------------ Detailed message ------------------------------
key `b` is declared as required in the latter but not in the former
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/t_maps.erl:742:27
@ -905,11 +634,4 @@ Because in the expression's type:
Context expects type: #{...} (no default association)
The expected map has no default association while the type of the expression has one.
------------------------------ Detailed message ------------------------------
#{'a' | 'b' => boolean()} is not compatible with #{a => boolean()}
because
#{'a' | 'b' => boolean()} is not compatible with #{a => boolean()}
the latter map has no default association while the first map has one
44 ERRORS

View file

@ -22,12 +22,6 @@ Because in the expression's type:
However the following candidate: []
Differs from the expected type: atom()
------------------------------ Detailed message ------------------------------
[] | 'error' is not compatible with atom()
because
[] is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/tries.erl:75:16

View file

@ -16,17 +16,6 @@ Because in the expression's type:
Differs from the expected type: 'ok'
, 'arg' | 'nil'}
------------------------------ Detailed message ------------------------------
t4() is not compatible with t5()
because
{'msg', 'ok' | 'err', 'arg' | 'nil'} is not compatible with t5()
because
{'msg', 'ok' | 'err', 'arg' | 'nil'} is not compatible with {'msg', 'ok', 'arg'} | {'msg', 'err', 'arg'} | {'msg', 'ok', 'nil'} | {'msg', 'err', 'nil'}
because
at tuple index 2:
{'msg', 'ok' | 'err', 'arg' | 'nil'} is not compatible with {'msg', 'ok', 'arg'}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/tuple_union.erl:66:26
@ -47,14 +36,4 @@ Because in the expression's type:
No candidate of the expression's type matches the expected type.
, tree2()}
------------------------------ Detailed message ------------------------------
tree3() is not compatible with tree1()
because
{'leaf', atom()} | {'b1' | 'b2' | 'b3', tree2()} is not compatible with tree1()
because
{'leaf', atom()} | {'b1' | 'b2' | 'b3', tree2()} is not compatible with {'leaf', atom()} | {'b1', tree1()} | {'b2', tree1()}
because
{'b1' | 'b2' | 'b3', tree2()} is not compatible with {'leaf', atom()} | {'b1', tree1()} | {'b2', tree1()}
2 ERRORS

View file

@ -22,12 +22,6 @@ Because in the expression's type:
However the following candidate: string()
Differs from the expected type: binary()
------------------------------ Detailed message ------------------------------
string() | binary() is not compatible with binary()
because
string() is not compatible with binary()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/type_asserts.erl:63:26
@ -63,17 +57,6 @@ Because in the expression's type:
Context expects type: atom()
, atom()}
------------------------------ Detailed message ------------------------------
'false' | {number(), atom()} is not compatible with 'false' | {atom(), number()}
because
{number(), atom()} is not compatible with 'false' | {atom(), number()}
because
at tuple index 1:
{number(), atom()} is not compatible with {atom(), number()}
because
number() is not compatible with atom()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/type_asserts.erl:92:3
@ -91,13 +74,6 @@ Because in the expression's type:
Context expects type: number()
}
------------------------------ Detailed message ------------------------------
at tuple index 2:
{'false' | number(), term()} is not compatible with {'false' | number(), number()}
because
term() is not compatible with number()
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/type_asserts.erl:105:39
@ -150,17 +126,6 @@ Because in the expression's type:
The expected map has no corresponding key for: kb.
, ... }
------------------------------ Detailed message ------------------------------
#{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} is not compatible with #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}} | #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} | #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}}
because
#{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} is not compatible with #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}}
the default associations are not compatible
because
#{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'} is not compatible with #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}
because
#{ka := 'va', kb := 'vb', kc := 'vc'} is not compatible with #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/type_asserts.erl:129:9
@ -179,17 +144,6 @@ Because in the expression's type:
The expected map has no corresponding key for: kb.
, ... }
------------------------------ Detailed message ------------------------------
#{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} is not compatible with #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}} | #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} | #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}}
because
#{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} is not compatible with #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}}
the default associations are not compatible
because
#{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'} is not compatible with #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}
because
#{ka := 'va', kb := 'vb', kc := 'vc'} is not compatible with #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/type_asserts.erl:132:9
@ -208,17 +162,6 @@ Because in the expression's type:
The expected map has no corresponding key for: kb.
, ... }
------------------------------ Detailed message ------------------------------
#{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} is not compatible with #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}} | #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} | #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}}
because
#{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'}} is not compatible with #{dynamic() => #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}}
the default associations are not compatible
because
#{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kb := 'vb', kc := 'vc'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb', kc := 'vc'} | #{kb := 'vb'} is not compatible with #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}
because
#{ka := 'va', kb := 'vb', kc := 'vc'} is not compatible with #{kc := 'vc'} | #{ka := 'va'} | #{ka := 'va', kc := 'vc'} | #{ka := 'va', kb := 'vb'} | #{kb := 'vb'}
error: incompatible_types (See https://fb.me/eqwalizer_errors#incompatible_types)
┌─ check/src/type_asserts.erl:156:24

View file

@ -15,11 +15,4 @@ Because in the expression's type:
Context expects type: atom()
}
------------------------------ Detailed message ------------------------------
at tuple index 1:
{binary()} is not compatible with {atom()}
because
binary() is not compatible with atom()
1 ERROR

Some files were not shown because too many files have changed in this diff Show more