Packages
metastatic
0.7.1
0.26.0
0.25.0
0.24.1
0.24.0
0.23.0
0.22.2
0.22.1
0.22.0
0.21.3
0.21.2
0.21.1
0.21.0
0.20.3
0.20.2
0.20.1
0.20.0
0.19.0
0.18.0
0.17.0
0.16.0
0.15.1
0.15.0
0.14.2
0.14.1
0.14.0
0.13.3
0.13.2
0.13.1
0.13.0
0.12.0
0.11.0
0.10.4
0.10.3
0.10.2
0.10.1
0.10.0
0.9.2
0.9.1
0.9.0
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.1
0.7.0
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.2
0.4.1
0.4.0
0.3.5
0.3.4
0.3.3
0.3.2
0.3.1
0.3.0
0.2.0
0.1.3
0.1.2
0.1.1
0.1.0
Cross-language code meta-model library using unified MetaAST representation. Parse, transform, and translate code across Python, Elixir, Ruby, Erlang, Haskell, and more via a shared three-tuple AST format.
Current section
Files
Jump to
Current section
Files
lib/metastatic/analysis/encapsulation/result.ex
defmodule Metastatic.Analysis.Encapsulation.Result do
@moduledoc """
Result structure for encapsulation analysis.
Encapsulation is the principle of hiding internal state and requiring all
interaction to go through well-defined interfaces (methods). This analyzer
detects violations of encapsulation principles.
## Violation Types
- **Public State** - Instance variables accessible without getters/setters
- **Missing Accessors** - State modified directly instead of through methods
- **Excessive Accessors** - Too many getters/setters (data class smell)
- **Leaky Abstraction** - Internal implementation details exposed
- **Visibility Violations** - Private methods called externally
## Severity Levels
- `:critical` - Severe encapsulation breach
- `:high` - Significant encapsulation issue
- `:medium` - Moderate concern
- `:low` - Minor issue or code smell
## Examples
iex> result = %Metastatic.Analysis.Encapsulation.Result{
...> container_name: "User",
...> violations: [],
...> score: 100,
...> assessment: :excellent
...> }
iex> result.assessment
:excellent
"""
@type severity :: :critical | :high | :medium | :low
@type violation_type ::
:public_state
| :missing_accessor
| :excessive_accessors
| :leaky_abstraction
| :visibility_violation
| :direct_state_access
@type violation :: %{
type: violation_type(),
severity: severity(),
message: String.t(),
location: String.t() | nil,
suggestion: String.t() | nil
}
@type assessment :: :excellent | :good | :fair | :poor | :very_poor
@type t :: %__MODULE__{
container_name: String.t() | nil,
container_type: :module | :class | :namespace | nil,
violations: [violation()],
score: non_neg_integer(),
assessment: assessment(),
public_methods: non_neg_integer(),
private_methods: non_neg_integer(),
accessor_count: non_neg_integer(),
state_variables: [String.t()],
recommendations: [String.t()]
}
defstruct container_name: nil,
container_type: nil,
violations: [],
score: 100,
assessment: :excellent,
public_methods: 0,
private_methods: 0,
accessor_count: 0,
state_variables: [],
recommendations: []
@doc """
Calculate encapsulation score based on violations.
Score starts at 100 and is reduced based on violation severity:
- Critical: -20 points
- High: -10 points
- Medium: -5 points
- Low: -2 points
## Examples
iex> violations = [
...> %{type: :public_state, severity: :critical, message: "Public var", location: nil, suggestion: nil},
...> %{type: :missing_accessor, severity: :high, message: "Direct access", location: nil, suggestion: nil}
...> ]
iex> Metastatic.Analysis.Encapsulation.Result.calculate_score(violations)
70
"""
@spec calculate_score([violation()]) :: non_neg_integer()
def calculate_score(violations) do
penalty =
Enum.reduce(violations, 0, fn violation, acc ->
case violation.severity do
:critical -> acc + 20
:high -> acc + 10
:medium -> acc + 5
:low -> acc + 2
end
end)
max(0, 100 - penalty)
end
@doc """
Assess encapsulation quality based on score.
## Examples
iex> Metastatic.Analysis.Encapsulation.Result.assess(95)
:excellent
iex> Metastatic.Analysis.Encapsulation.Result.assess(65)
:fair
iex> Metastatic.Analysis.Encapsulation.Result.assess(35)
:very_poor
"""
@spec assess(non_neg_integer()) :: assessment()
def assess(score) do
cond do
score >= 90 -> :excellent
score >= 75 -> :good
score >= 60 -> :fair
score >= 40 -> :poor
true -> :very_poor
end
end
@doc """
Generate recommendations based on violations.
## Examples
iex> violations = [%{type: :public_state, severity: :critical, message: "x", location: nil, suggestion: nil}]
iex> recs = Metastatic.Analysis.Encapsulation.Result.generate_recommendations(violations, 5, 0)
iex> Enum.any?(recs, &String.contains?(&1, "private"))
true
"""
@spec generate_recommendations([violation()], non_neg_integer(), non_neg_integer()) :: [
String.t()
]
def generate_recommendations(violations, _public_count, accessor_count) do
recs = []
# Check for public state violations
recs =
if Enum.any?(violations, &(&1.type == :public_state)) do
["Make instance variables private and provide controlled access through methods" | recs]
else
recs
end
# Check for missing accessors
recs =
if Enum.any?(violations, &(&1.type == :missing_accessor)) do
["Add getter/setter methods instead of accessing state directly" | recs]
else
recs
end
# Check for excessive accessors (data class smell)
recs =
if accessor_count > 10 do
[
"Consider if this is a data class - encapsulation may require behavior, not just accessors"
| recs
]
else
recs
end
# Check for leaky abstractions
recs =
if Enum.any?(violations, &(&1.type == :leaky_abstraction)) do
[
"Hide implementation details - provide higher-level methods that encapsulate behavior"
| recs
]
else
recs
end
# Default recommendation if no specific issues
recs =
if Enum.empty?(recs) do
[
"Encapsulation is good - continue maintaining clear boundaries between interface and implementation"
]
else
recs
end
Enum.reverse(recs)
end
@doc """
Create a violation record.
## Examples
iex> Metastatic.Analysis.Encapsulation.Result.violation(:public_state, :critical, "Variable 'x' is public", "x", "Make 'x' private")
%{type: :public_state, severity: :critical, message: "Variable 'x' is public", location: "x", suggestion: "Make 'x' private"}
"""
@spec violation(violation_type(), severity(), String.t(), String.t() | nil, String.t() | nil) ::
violation()
def violation(type, severity, message, location \\ nil, suggestion \\ nil) do
%{
type: type,
severity: severity,
message: message,
location: location,
suggestion: suggestion
}
end
end