dialyzer: expand PLT, drop blanket codebase suppression
Ignore file was silencing every warning under lib/towerops/**. Root cause was plt_add_deps: :apps_direct missing Plug/Phoenix/Oban/Decimal /Redix/ssl/public_key — hundreds of false `unknown_function` warnings were being papered over. Expand plt_add_apps to cover the common deps, narrow the ignore file to real dep-PLT gaps only, and fix two concrete bugs uncovered by the change: - ScopedResource.fetch_preload/4: spec was atom() | [atom()] but callers pass keyword lists (e.g. [rules: :targets]). - ToweropsNative: tag NIF stubs with @dialyzer :nowarn_function so dialyzer trusts the @spec instead of the fallback body. Remaining 328 real warnings surface for follow-up.
This commit is contained in:
parent
fc51974d36
commit
2653e2516d
4 changed files with 33 additions and 46 deletions
|
|
@ -1,69 +1,37 @@
|
|||
# Dialyzer false positives to ignore
|
||||
# These are known issues from dependencies with incomplete PLT information
|
||||
# Dialyzer warnings to ignore.
|
||||
#
|
||||
# Most warnings in our codebase are false positives from Ecto, Plug, Oban, and Phoenix
|
||||
# not exporting their internal types and functions in their PLT files.
|
||||
#
|
||||
# We ignore these systematically since they're not real bugs - all tests pass and
|
||||
# the application runs correctly.
|
||||
# Dependency PLT gaps should be handled via `plt_add_apps` in mix.exs.
|
||||
# Only suppress genuine false positives here — fix real warnings instead.
|
||||
[
|
||||
# === Dependency behavior warnings ===
|
||||
|
||||
# Ecto.Type behavior - callback info not exported
|
||||
# Ecto.Type behaviour — callbacks aren't always exported
|
||||
{"deps/ecto/lib/ecto/type.ex", :callback_info_missing},
|
||||
|
||||
# Oban.Worker behavior - callback info not exported
|
||||
# Oban.Worker behaviour — PLT gap
|
||||
{"deps/oban/lib/oban/worker.ex", :callback_info_missing},
|
||||
{"deps/oban/lib/oban/worker.ex", :unknown_function},
|
||||
|
||||
# Phoenix behaviors - callback info not exported
|
||||
# Phoenix behaviours
|
||||
{"deps/phoenix/lib/phoenix/endpoint.ex", :callback_info_missing},
|
||||
{"deps/phoenix/lib/phoenix/router.ex", :callback_info_missing},
|
||||
|
||||
# Plug behaviors - callback info not exported
|
||||
# Plug behaviours
|
||||
{"deps/plug/lib/plug/debugger.ex", :unknown_function},
|
||||
{"deps/plug/lib/plug/error_handler.ex", :unknown_function},
|
||||
|
||||
# Honeybadger - unknown function false positives
|
||||
# Honeybadger
|
||||
{"deps/honeybadger/lib/honeybadger/plug.ex", :unknown_function},
|
||||
|
||||
# Cloak - callback info and unknown function warnings
|
||||
# Cloak
|
||||
{"deps/cloak/lib/cloak/vault.ex", :unknown_function},
|
||||
{"/home/runner/work/elixir/elixir/lib/elixir/lib/gen_server.ex", :callback_info_missing},
|
||||
{"deps/cloak_ecto/lib/cloak_ecto/type.ex", :callback_info_missing},
|
||||
{"deps/cloak_ecto/lib/cloak_ecto/types/binary.ex", :unknown_function},
|
||||
|
||||
# === Vendored library warnings ===
|
||||
|
||||
# SnmpKit vendored library - ignore all warnings (both lib/ and src/)
|
||||
# Vendored SnmpKit — out of scope for typing cleanup
|
||||
~r/lib\/snmpkit/,
|
||||
~r/lib\/snmp_lib/,
|
||||
~r/src\/snmpkit/,
|
||||
~r/src\/snmp_lib/,
|
||||
|
||||
# === Application code with dependency false positives ===
|
||||
|
||||
# Ignore unknown_function and unknown_type warnings from Ecto/Plug/Phoenix
|
||||
# These are false positives - the functions exist but aren't in the PLT
|
||||
~r/lib\/towerops.*\.ex/,
|
||||
~r/lib\/towerops.*\.heex/,
|
||||
~r/lib\/mix\/tasks.*\.ex/,
|
||||
|
||||
# === Gleam type system interop warnings ===
|
||||
#
|
||||
# Gleam's type system doesn't map 1:1 to Erlang's type system, causing false positives:
|
||||
#
|
||||
# 1. contract_supertype: Gleam only has `Int`, but Dialyzer infers `non_neg_integer()`.
|
||||
# We cannot make Gleam specs more specific.
|
||||
#
|
||||
# 2. call_without_opaque: Gleam stdlib uses opaque types (bytes_tree, Decoder) that
|
||||
# Dialyzer doesn't understand. The code works correctly at runtime.
|
||||
#
|
||||
# 3. no_return/invalid_contract: Dialyzer thinks bytes_tree functions will crash because
|
||||
# it doesn't understand the opaque type transformations.
|
||||
#
|
||||
# All Gleam code compiles and passes tests - these are type system artifacts, not bugs.
|
||||
|
||||
# All Gleam files in src/towerops/ (excluding vendored snmpkit above)
|
||||
# Gleam type system doesn't map 1:1 to Erlang's — artifacts, not bugs.
|
||||
~r/src\/towerops\/.*\.gleam/
|
||||
]
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ defmodule ToweropsNative do
|
|||
|
||||
@on_load :load_nif
|
||||
|
||||
# NIF stubs return fallback values when the NIF fails to load (defensive).
|
||||
# Dialyzer only sees the stub bodies, so tell it to trust the @spec instead.
|
||||
@dialyzer {:nowarn_function, [resolve_oid: 1, init_mib_library: 0, load_mib_directory: 1]}
|
||||
|
||||
def load_nif do
|
||||
nif_path = :filename.join(:code.priv_dir(:towerops), ~c"towerops_nif")
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ defmodule ToweropsWeb.ScopedResource do
|
|||
end
|
||||
end
|
||||
|
||||
@spec fetch_preload(module(), Ecto.UUID.t(), Ecto.UUID.t(), atom() | [atom()]) ::
|
||||
@spec fetch_preload(module(), Ecto.UUID.t(), Ecto.UUID.t(), atom() | list() | keyword()) ::
|
||||
{:ok, struct()} | {:error, :not_found | :forbidden}
|
||||
def fetch_preload(schema, id, organization_id, preloads) do
|
||||
with {:ok, resource} <- fetch(schema, id, organization_id) do
|
||||
|
|
|
|||
19
mix.exs
19
mix.exs
|
|
@ -105,9 +105,24 @@ defmodule Towerops.MixProject do
|
|||
defp dialyzer do
|
||||
[
|
||||
plt_file: {:no_warn, "priv/plts/dialyzer.plt"},
|
||||
# Faster incremental analysis
|
||||
plt_add_deps: :apps_direct,
|
||||
plt_add_apps: [:mix, :ex_unit, :ecto],
|
||||
plt_add_apps: [
|
||||
:mix,
|
||||
:ex_unit,
|
||||
:ecto,
|
||||
:plug,
|
||||
:plug_crypto,
|
||||
:phoenix,
|
||||
:phoenix_pubsub,
|
||||
:phoenix_live_view,
|
||||
:phoenix_template,
|
||||
:oban,
|
||||
:decimal,
|
||||
:redix,
|
||||
:telemetry,
|
||||
:ssl,
|
||||
:public_key
|
||||
],
|
||||
flags: [:unmatched_returns, :error_handling, :underspecs, :unknown],
|
||||
ignore_warnings: ".dialyzer_ignore.exs"
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue