mirror of
https://github.com/WhatsApp/erlang-language-platform.git
synced 2025-12-23 12:26:48 +00:00
Compare commits
142 commits
2025-11-04
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a4eccf14d | ||
|
|
4bba415bc1 | ||
|
|
6456f325c3 | ||
|
|
5c7cfae09d | ||
|
|
220acfd4f7 | ||
|
|
fc09ff94fd | ||
|
|
8e82f1cee4 | ||
|
|
8cb6ac7620 | ||
|
|
8b4c533527 | ||
|
|
b12cf72c7e | ||
|
|
ce0125dec9 | ||
|
|
d7b1c561ad | ||
|
|
3804bd1706 | ||
|
|
439ebade1b | ||
|
|
54dd1089ed | ||
|
|
fa05043043 | ||
|
|
79c33480c5 | ||
|
|
7057624c73 | ||
|
|
4a051d1af8 | ||
|
|
91a0d968db | ||
|
|
cc0a9c26d5 | ||
|
|
83d5b4dfd0 | ||
|
|
9015d80659 | ||
|
|
8997372e1a | ||
|
|
bef3dd15f2 | ||
|
|
56e66e2cd5 | ||
|
|
a0e076cb17 | ||
|
|
8ff602f1c3 | ||
|
|
4a83d0edde | ||
|
|
271065da03 | ||
|
|
37b7c5e28e | ||
|
|
d4e14636b4 | ||
|
|
b2ea905e7f | ||
|
|
858b8e64ab | ||
|
|
271a52c37c | ||
|
|
ba4505e981 | ||
|
|
d2da476882 | ||
|
|
166770cc92 | ||
|
|
b525eac0ea | ||
|
|
2bd3d57d02 | ||
|
|
eb5e0abbf8 | ||
|
|
887d287c94 | ||
|
|
553c90d631 | ||
|
|
a16af7e9e2 | ||
|
|
0085fba772 | ||
|
|
babf61214c | ||
|
|
7b0b29ae21 | ||
|
|
4bfedaee9a | ||
|
|
290b931170 | ||
|
|
0930edd693 | ||
|
|
2d693f3578 | ||
|
|
0aef1f4005 | ||
|
|
29c017c565 | ||
|
|
ed8820b3b2 | ||
|
|
a239a322cf | ||
|
|
a4ded31602 | ||
|
|
6dbefe9bd0 | ||
|
|
4df5a7ae81 | ||
|
|
f6b54832d7 | ||
|
|
1a086de994 | ||
|
|
77e0ff9bc8 | ||
|
|
debed39b42 | ||
|
|
c404d942df | ||
|
|
0f7069d02e | ||
|
|
e1296c5c14 | ||
|
|
4e6851c71a | ||
|
|
61512bf9b9 | ||
|
|
4726f8144d | ||
|
|
016e0d7c1e | ||
|
|
fd8fb4abeb | ||
|
|
c9cba57e40 | ||
|
|
796f015f20 | ||
|
|
d42e431df4 | ||
|
|
9ef2fec36e | ||
|
|
3461b85029 | ||
|
|
1fc2f63da8 | ||
|
|
8bd2c5e571 | ||
|
|
8558c9d5dc | ||
|
|
cbe9a058cc | ||
|
|
e4b89ebac5 | ||
|
|
f80d50389d | ||
|
|
eafb4940c7 | ||
|
|
270b8f4614 | ||
|
|
89c0c87b0f | ||
|
|
3e873e691d | ||
|
|
87bc60c524 | ||
|
|
38c84d39a6 | ||
|
|
7b124c7f06 | ||
|
|
06892be8c1 | ||
|
|
0da6ec3079 | ||
|
|
8997d5eb03 | ||
|
|
4fa7b6c8ac | ||
|
|
8dbbd1f6d4 | ||
|
|
fe49f6ba3c | ||
|
|
be0cb21ea7 | ||
|
|
0de513221f | ||
|
|
473c0f1c56 | ||
|
|
bc2c3f05d4 | ||
|
|
0c2b43eb27 | ||
|
|
fbdb3e1baf | ||
|
|
5470044b61 | ||
|
|
9860cc85f1 | ||
|
|
5820634ce2 | ||
|
|
99501811a5 | ||
|
|
b25b590a27 | ||
|
|
1788ac77bd | ||
|
|
44409a4346 | ||
|
|
7571e57155 | ||
|
|
77ff228aae | ||
|
|
e9a9035e5a | ||
|
|
5187bf3d3f | ||
|
|
74ed6b2de4 | ||
|
|
cac1c952f9 | ||
|
|
89ca280740 | ||
|
|
479c76ce85 | ||
|
|
65de999b3b | ||
|
|
9a91229311 | ||
|
|
8efb4fe29c | ||
|
|
dcf4e3a4ff | ||
|
|
8394c84d6b | ||
|
|
717422ebfe | ||
|
|
30a992691f | ||
|
|
20b8d9950a | ||
|
|
aca24c8fc3 | ||
|
|
276297e366 | ||
|
|
a8bb2de049 | ||
|
|
ed673119e4 | ||
|
|
42ef1d1924 | ||
|
|
6fe7f108a1 | ||
|
|
59ec8ab042 | ||
|
|
f050c6c671 | ||
|
|
395db3dda7 | ||
|
|
4486d66840 | ||
|
|
f4b93ec388 | ||
|
|
c5263ed926 | ||
|
|
e0c5e94ac0 | ||
|
|
b01a09f2ff | ||
|
|
49fb231fe9 | ||
|
|
412ccca85e | ||
|
|
85c1586d7d | ||
|
|
6f2ee22321 | ||
|
|
4227771616 |
774 changed files with 12580 additions and 14617 deletions
|
|
@ -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
|
||||
|
|
|
|||
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
12
.vscode/tasks.json
vendored
|
|
@ -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
18
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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>>()
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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:?}")?;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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}")?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
";
|
||||
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}),
|
||||
],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Project Initialisation Failed: invalid or missing buck 2 configuration
|
||||
|
|
@ -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
|
||||
138
crates/elp/src/resources/test/diagnostics/lint_no_stream.stdout
Normal file
138
crates/elp/src/resources/test/diagnostics/lint_no_stream.stdout
Normal 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 ')'
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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"}
|
||||
|
|
|
|||
|
|
@ -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]).
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
module specified: erlang_diagnostics_errors_gen
|
||||
No matches found
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
│
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue