elixir-type_check

TypeCheck: Fast and flexible runtime type-checking for your Elixir projects.

MIT License

Downloads
63.3K
Stars
511
Committers
18
elixir-type_check - v0.12.0 Latest Release

Published by Qqwy over 2 years ago

Additions:

  • The default options used are now fetched from the application configuration. This means that you can configure a default for your app as well as for each of your dependencies(!) by adding config :app_name, :type_check [...] to your configuration file(s). (c.f. #61)
  • TypeCheck.External module, with functions to work with typespecs in modules outside of your control. Thank you very much, @orsinium! (c.f. #113)
    • fetch_spec to build a TypeCheck type from any function that has a @spec.
    • fetch_type to build a TypeCheck type from any @type.
    • enforce_spec! to wrap a call to any function that has a @spec with a runtime type-check on the input parameters and return value.
    • apply and apply! to wrap a call to any function with the function spec type that you give it.
  • TypeCheck.Defstruct.defstruct!, a way to combine defstruct, @enforce_keys and the creation of the struct's type, reducing boilerplate and the possibility of mistakes. (c.f. #118 )

Fixes:

  • Long-standing issue where Dialyzer would sometimes complain in apps using TypeCheck is resolved. (c.f. #95)
  • Creation of the new maybe_nonempty_list type will no longer get stuck in an infinite loop on creation. (c.f. #120)
elixir-type_check - v0.11.0

Published by Qqwy over 2 years ago

Wooh, this is a big release!

Most important features:

  • We now support all of Elixir's builtin basic types!
  • We now support all of the remote types of the Elixir standard library!
  • Support for most of the map-type syntactic sugars.
  • An optional Credo check to enforce that all your functions have a spec.

Full changelog

Additions

  • Support for fancier map syntaxes:
    • %{required(key_type) => value_type} Maps with a single kind of required key-value type.
    • %{optional(key_type) => value_type} Maps with a single kind of optional key-value type.
    • %{:some => a(), :fixed => b(), :keys => c(), optional(atom()) => any()} Maps with any number of fixed keys and a single optional key-value type.
    • TypeCheck now supports nearly all kinds of map types that see use. Archaic combinations of optional and required are not supported, but also not very useful types in practice.
    • Because of this, the inspection of the builtin type map(key, value) has been changed to look the same as an optional map. This is a minor backwards-incompatible change.
  • Desugaring %{} has changed from 'any map' to 'the empty map' in line with Elixir's Typespecs. This is a minor backwards-incompatible change.
  • Support for the builtin types port(), reference() and (based on these) identifier().
  • Support for the builtin type struct().
  • Support for the builtin type timeout().
  • Support for the builtin type nonempty_charlist() and maybe_improper_list and (based on these) iolist() and iodata().
  • Adding types depending on these builtins to the default type overrides. We now support all modules of the full standard library!
  • TypeCheck.Credo.Check.Readability.Specs: an opt-in alternative Credo check which will check whether all functions have either a @spec! or 'normal' @spec. (Fixes #102).

Fixes

  • The TypeCheck.Builtin module is now actually spectested itself. Some consistency bugs were found and solved as a result.
elixir-type_check - v0.10.7

Published by Qqwy over 2 years ago

Fixes:

  • Ensures fixed-maps are checked for superfluous keys (c.f. #96). Thank you very much, @spatrik!
elixir-type_check - v0.10.4

Published by Qqwy almost 3 years ago

Fixes

  • Fixes issue where sometimes results of specs returning a struct would remove some or all struct fields. (c.f. #78 and PR #82 )
  • Related: Ensures that when a @type! containing a %__MODULE__{} is used before that module's defstruct, a clear CompileError is created (c.f. #83).
elixir-type_check - v0.10.3

Published by Qqwy almost 3 years ago

Fixes

Ensures calls to def/defp/defmacro/defmacrop are always qualified

(i.e. prefixed with 'Kernel.'), so they will also work in defprotocol
modules or other places where the normal versions of these macros are
hidden/overridden.

This fixes a bug reported on the Elixir forums by user 'belteconti'.

(c.f. PR #75 )

elixir-type_check - v0.10.2

Published by Qqwy almost 3 years ago

Fixes:

  • Fixes issue where FixedMaps would accept maps any maps (even those missing the required keys) sometimes. (c.f. #74)
elixir-type_check - Version 0.10.0

Published by Qqwy about 3 years ago

Version 0.10.0 has been released! Ⲗ

Additions & Improvements

Support for function-types (for typechecks as well as property-testing generators):

  • (-> result_type)
  • (...-> result_type)
  • (param_type, param2_type -> result_type)

Type-checking function-types

Type-checking a function value against a function-type works a bit differently from most other types.
The reason for this is that we can only ascertain whether the function-value works correctly when the function-value is called.

Specifically:

  • When a call to TypeCheck.conforms/3 (and variants) or a function wrapped with a @spec! is called, we can immediately check whether a particular parameter:
    • is a function
    • accepts the expected arity
  • Then, the parameter-which-is-a-function is wrapped in a 'wrapper function' which, when called:
    • typechecks whether the passed parameters are of the expected types (This checks whether your function uses the parameter-function correctly.)
    • calls the original function with the parameters.
    • typechecks whether the result is of the expected type. (This checks whether the parameter-function works correctly.)
    • returns the result.

In other words, the 'wrapper function' which is added for a type (param_type, param_type2 -> result_type) works similarly
to a named function with the spec @spec! myfunction(param_type, param_type2) :: result_type.

As an example:

      iex> # The following passes the first check...
      iex> fun = TypeCheck.conforms!(&div/2, (integer(), integer() -> boolean()))
      iex> # ... but once the function returns, the wrapper will raise
      iex> fun.(20, 5)
      ** (TypeCheck.TypeError) The call to `#Function<...>/2` failed,
          because the returned result does not adhere to the spec `boolean()`.
          Rather, its value is: `4`.
          Details:
            The result of calling `#Function<...>.(20, 5)`
            does not adhere to spec `(integer(), integer() -> boolean())`. Reason:
              Returned result:
                `4` is not a boolean.

This was quite the adventure to implement. I am happy that it turned out to be possible, and it is working great!

Data generation for function types

For property-testing generators, the data passed to a generated function is converted into a seed (using [param1, param2, param3] |> :erlang.term_to_binary |> Murmur.hash_x86_32) and this seed is then used as seed for the data returned from the function.
This means that for any particular test run, any generated function will be pure (i.e. when given the same input multiple times, the same output will be returned).

Fixes

  • Wrapping private functions no longer make the function public. (c.f. #64)
  • Wrapping macros now works correctly. (also related to #64)
  • Using __MODULE__ inside a struct inside a type now expands correctly. (c.f. #66)
elixir-type_check - Version 0.9.0

Published by Qqwy about 3 years ago

Version 0.9.0 has been released! 😊

Additions & Improvements

Support for bitstring literal types.

The types bitstring(), binary() and String.t() were already supported.
However, support has now been added for the types:

  • <<>> (matching an empty bitstring),
  • <<_ :: size>> (matching a bitstring of exactly size bits long),
  • <<_ :: _ * unit>> (matching any bitstring of x * unit where x :: pos_integer()),
  • <<_ :: size, _ :: _ * unit>> (matching any bitstring of size + x * unit where x :: pos_integer()).

Property-testing generators have also been constructed for them, so you can immediatly start using them with spectests.

elixir-type_check - Version 0.8.1

Published by Qqwy about 3 years ago

Fixes

  • Improved documentation with a page comparing TypeCheck with Elixir's plain typespecs. c.f. #59
  • Addition of missing override for the type Range.t(). c.f. #58

Thank you very much, @baldwindavid 💚 !

elixir-type_check - Version 0.8.0

Published by Qqwy about 3 years ago

Version 0.8.0 has been released! 🚢

Additions & Improvements

  • Pretty-printing of types and TypeError output in multiple colors:

image

(This is the 'Rating' example from the Type-checking and spec-testing with TypeCheck article).
Types and values are pretty-printed in colour, similarly to how this is normally done in IEx.

  • Nicer indentation of errors. Amongst other things, this means that error-highlighting in the documentation now works correctly (although in 100% 'red').
  • use TypeCheck now also calls require TypeCheck.Type so there no longer is a need to call this manually if you want to e.g. use TypeCheck.Type.build/1 (which is rather common if you want to test out particular types quickly in IEx).
  • named types are now printed in abbreviated fashion if they are repeated multiple times in an error message. This makes a nested error message much easier to read, especially for larger specs.
  • Remote/user-defined types are now also 'named types' which profit from this change.
    For instance in above example picture, we first talk about Rating.t() and String.t() and only when looking at the problem in detail do we expand this to %Rating{} and binary().
  • [type] no longer creates a fixed_list(type) but instead a list(type) (just as Elixir's own typespecs.)
  • Support for [...] and [type, ...]as alias for nonempty_list() and nonempty_list(type) respectively.

Fixes

  • Fixes prettyprinting of TypeCheck.Builtin.Range.
  • Remove support for list literals with multiple elements.
  • Improved documentation. c.f. #56

Thank you very much, @baldwindavid and @0urobor0s !

elixir-type_check -

Published by Qqwy about 3 years ago

Version 0.7.0 has been released! rocket

Added

  • Addition of the option enable_runtime_checks. When false, all runtime checks in the given module are completely disabled. This is useful to for instance disable checks in a particular environment. (c.f. #52) Thank you, @baldwindavid!
  • Adding DateTime.t to the default overrides, as it was still missing.
elixir-type_check - 0.6.0 - Addition of spectest & 'default overrides' Elixir's standard library types

Published by Qqwy about 3 years ago

Version 0.6.0 has been released! 🚀

Its main changes are the addition of spectests and the implementation of a very large portion of the types in all modules of Elixir's standard library.

Additions & Improvements:

  • Adding TypeCheck.ExUnit, with the function spectest to test function-specifications.
    • Possibility to use options :except, :only, :initial_seed.
    • Possibility to pass custom options to StreamData.
  • Adding TypeCheck.DefaultOverrides with many sub-modules containing checked typespecs for the types in Elixir's standard library (75% done).
    • Ensure that these types are correct also on older Elixir versions (1.9, 1.10, 1.11)
  • By default load these 'DefaultOverrides', but have the option to turn this behaviour off in TypeCheck.Option.
  • Nice generators for Enum.t, Collectable.t, String.t.
  • Support for the builtin types:
    • pid()
    • nonempty_list(), nonempty_list(type).
  • Allow use TypeCheck in IEx or other non-module contexts, to require TypeCheck and import TypeCheck.Builtin in the current scope (without importing/using the macros that only work at the module level.)
  • The introspection function __type_check__/1 is now added to any module that contains a use TypeCheck.

Fixes

  • Fixes the Inspect implementation of custom structs, by falling back to Any, which is more useful than attempting to use a customized implementation that would try to read the values in the struct and failing because the struct-type containing types in the fields.
  • Fixes conditional compilation warnings when optional dependency :stream_data was not included in your project.
Package Rankings
Top 6.47% on Hex.pm
Badges
Extracted from project README
hex.pm version Documentation ci Coverage Status