defmodule Archeometer.Schema.Module do
  @moduledoc """
  Represents an Elixir module. Holds the relevant schema data that will be
  used in the project analysis.

  This schema has the following fields:
  - `name` is the name of the module.
  - `num_lines` is the length of the module delcaration body.
  - `coverage` is a number between 0 and 1 representing the module testing
    coverage percentage.
  - `path` is the file path where the module was declared.
  - `has_struct` is 1 when the module has a struct and 0 if not.
  - `has_ecto_schema` is 1 when the module defines an ecto schema and 0 if not.
  - `is_test` is 1 when the module is a test.
  - `app` is a reference to `Archeometer.Schema.App`. It is the module's
    corresponding OTP application
  - `in_refs` stands for "incoming references". That is, all references of the
    current module in other modules. Or in other words all the usages of the
    current module.
  - `out_refs` stands for "outgoing reference". That is, all references from other
    modules in the current one. Or said on other words, the current module
  - `functions` is a reference to `Archeometer.Schema.Function`. All the
    functions defined in the module.
  - `macros` is a reference to `Archeometer.Schema.Macro`. All the macros
    defined in the module.
  - `behaviours` is a reference to `Archeometer.Schema.Behaviour`. Behaviours
    implemented in the module.
  - `credo_issues` is a reference to `Archeometer.Schema.CredoIssue`.
    Credo issues detected on the module.

  use Archeometer.Schema

  alias Archeometer.Schema.{App, XRef, Function, Macro, Behaviour, CredoIssue}

  defschema(:modules) do
    field(:id, primary_key: true)
    belongs_to(App, key: :app_id)
    has(XRef, as: :in_refs, key: :callee_id)
    has(XRef, as: :out_refs, key: :caller_id)
    has(Function, as: :functions)
    has(Macro, as: :macros)
    has(Behaviour, as: :behaviours)
    has(CredoIssue, as: :credo_issues)