Search documentation of Metastatic

# Metastatic.Semantic.Patterns (Metastatic v0.13.2)

View Source

Language-aware pattern registry for semantic enrichment.

This module provides a pattern matching engine that maps function names to semantic operation kinds. Patterns are organized by language and domain, enabling precise detection of framework-specific operations.

## Pattern Types

Three types of patterns are supported:

1. Exact match - Full function name: `"Repo.get"`
2. Prefix match - Module prefix with wildcard: `"Repo.*"`
3. Suffix match - Method name at end: `"*.findByPk"`
4. Regex match - Complex patterns: `~r/\.objects\.get/`

## Usage

    alias Metastatic.Semantic.Patterns

    # Match a function name against patterns for a language
    case Patterns.match("Repo.get", :elixir, args) do
      {:ok, op_kind} -> # Found a match
      :no_match -> # No pattern matched
    end

## Pattern Registration

Patterns are defined in domain-specific modules (e.g., `Domains.Database`) and registered here. Each pattern specifies:

- Language(s) it applies to
- Function name pattern
- Operation kind metadata
- Optional: target extraction strategy

## Summary

### Types

language()

Language identifier

pattern_spec()

Pattern specification

### Functions

clear_all()

Clears all registered patterns (useful for testing).

get_patterns(domain, language)

Gets all registered patterns for a domain and language.

match(func_name, language, args, receiver \\ nil)

Matches a function name against registered patterns for a language.

register(domain, language, patterns)

Registers patterns for a domain and language.

## Types

# language()

    @type language() ::
      :elixir | :python | :ruby | :javascript | :erlang | :haskell | atom()

Language identifier

# pattern_spec()

    @type pattern_spec() :: %{
      operation: Metastatic.Semantic.OpKind.operation(),
      framework: Metastatic.Semantic.OpKind.framework() | nil,
      extract_target: :first_arg | :receiver | :none | nil
    }

Pattern specification

## Functions

# clear_all()

    @spec clear_all() :: :ok

Clears all registered patterns (useful for testing).

# get_patterns(domain, language)

    @spec get_patterns(Metastatic.Semantic.OpKind.domain(), language()) :: [
      {String.t() | Regex.t(), pattern_spec()}
    ]

Gets all registered patterns for a domain and language.

# match(func_name, language, args, receiver \\ nil)

    @spec match(String.t(), language(), list(), term()) ::
      {:ok, Metastatic.Semantic.OpKind.t()} | :no_match

Matches a function name against registered patterns for a language.

Returns `{:ok, op_kind}` if a pattern matches, or `:no_match` otherwise.

## Parameters

- `func_name` - The function name to match (e.g., "Repo.get", "session.query")
- `language` - The source language (e.g., :elixir, :python)
- `args` - AST arguments for target extraction
- `receiver` - Optional receiver AST for method calls

## Examples

    iex> Patterns.match("Repo.get", :elixir, [{:variable, [], "User"}, {:literal, [subtype: :integer], 1}])
    {:ok, [domain: :db, operation: :retrieve, target: "User", async: false, framework: :ecto]}

    iex> Patterns.match("unknown_function", :elixir, [])
    :no_match

# register(domain, language, patterns)

    @spec register(Metastatic.Semantic.OpKind.domain(), language(), [
      {String.t() | Regex.t(), pattern_spec()}
    ]) :: :ok

Registers patterns for a domain and language.

This is called by domain modules (e.g., `Domains.Database`) during compilation.

## Examples

    Patterns.register(:db, :elixir, [
      {"Repo.get", %{operation: :retrieve, framework: :ecto, extract_target: :first_arg}},
      {"Repo.all", %{operation: :retrieve_all, framework: :ecto}}
    ])